1 # Copyright (C) 2005-2010 Aaron Bentley and Panometrics, Inc.
2 # Ben Finney <benf@cybersource.com.au>
3 # Gianluca Montecchi <gian@grys.it>
4 # Marien Zwart <marienz@gentoo.org>
5 # W. Trevor King <wking@drexel.edu>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License along
18 # with this program; if not, write to the Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 import bzrlib.builtins
44 if libbe.TESTING == True:
54 client = None # bzrlib module
56 def __init__(self, *args, **kwargs):
57 base.VCS.__init__(self, *args, **kwargs)
60 def _vcs_version(self):
63 return bzrlib.__version__
65 def _vcs_get_user_id(self):
66 # excerpted from bzrlib.builtins.cmd_whoami.run()
68 c = bzrlib.branch.Branch.open_containing(self.repo)[0].get_config()
69 except errors.NotBranchError:
70 c = bzrlib.config.GlobalConfig()
73 def _vcs_detect(self, path):
74 if self._u_search_parent_directories(path, '.bzr') != None :
78 def _vcs_root(self, path):
79 """Find the root of the deepest repository containing path."""
80 cmd = bzrlib.builtins.cmd_root()
81 cmd.outf = StringIO.StringIO()
82 cmd.run(filename=path)
83 return cmd.outf.getvalue().rstrip('\n')
85 def _vcs_init(self, path):
86 cmd = bzrlib.builtins.cmd_init()
87 cmd.outf = StringIO.StringIO()
88 cmd.run(location=path)
90 def _vcs_destroy(self):
91 vcs_dir = os.path.join(self.repo, '.bzr')
92 if os.path.exists(vcs_dir):
93 shutil.rmtree(vcs_dir)
95 def _vcs_add(self, path):
96 path = os.path.join(self.repo, path)
97 cmd = bzrlib.builtins.cmd_add()
98 cmd.outf = StringIO.StringIO()
99 cmd.run(file_list=[path], file_ids_from=self.repo)
101 def _vcs_exists(self, path, revision=None):
102 manifest = self._vcs_listdir(
103 self.repo, revision=revision, recursive=True)
108 def _vcs_remove(self, path):
109 # --force to also remove unversioned files.
110 path = os.path.join(self.repo, path)
111 cmd = bzrlib.builtins.cmd_remove()
112 cmd.outf = StringIO.StringIO()
113 cmd.run(file_list=[path], file_deletion_strategy='force')
115 def _vcs_update(self, path):
118 def _parse_revision_string(self, revision=None):
121 rev_opt = bzrlib.option.Option.OPTIONS['revision']
123 rev_spec = rev_opt.type(revision)
124 except bzrlib.errors.NoSuchRevisionSpec:
125 raise base.InvalidRevision(revision)
128 def _vcs_get_file_contents(self, path, revision=None):
130 return base.VCS._vcs_get_file_contents(self, path, revision)
131 path = os.path.join(self.repo, path)
132 revision = self._parse_revision_string(revision)
133 cmd = bzrlib.builtins.cmd_cat()
134 cmd.outf = StringIO.StringIO()
136 cmd.run(filename=path, revision=revision)
137 except bzrlib.errors.BzrCommandError, e:
138 if 'not present in revision' in str(e):
139 raise base.InvalidPath(path, root=self.repo, revision=revision)
141 return cmd.outf.getvalue()
143 def _vcs_path(self, id, revision):
144 manifest = self._vcs_listdir(
145 self.repo, revision=revision, recursive=True)
146 return self._u_find_id_from_manifest(id, manifest, revision=revision)
148 def _vcs_isdir(self, path, revision):
150 self._vcs_listdir(path, revision)
151 except AttributeError, e:
152 if 'children' in str(e):
157 def _vcs_listdir(self, path, revision, recursive=False):
158 path = os.path.join(self.repo, path)
159 revision = self._parse_revision_string(revision)
160 cmd = bzrlib.builtins.cmd_ls()
161 cmd.outf = StringIO.StringIO()
163 cmd.run(revision=revision, path=path, recursive=recursive)
164 except bzrlib.errors.BzrCommandError, e:
165 if 'not present in revision' in str(e):
166 raise base.InvalidPath(path, root=self.repo, revision=revision)
168 children = cmd.outf.getvalue().rstrip('\n').splitlines()
169 children = [self._u_rel_path(c, path) for c in children]
172 def _vcs_commit(self, commitfile, allow_empty=False):
173 cmd = bzrlib.builtins.cmd_commit()
174 cmd.outf = StringIO.StringIO()
178 cmd.run(file=commitfile, unchanged=allow_empty)
179 except bzrlib.errors.BzrCommandError, e:
180 strings = ['no changes to commit.', # bzr 1.3.1
181 'No changes to commit.'] # bzr 1.15.1
182 if self._u_any_in_string(strings, str(e)) == True:
183 raise base.EmptyCommit()
187 return self._vcs_revision_id(-1)
189 def _vcs_revision_id(self, index):
190 cmd = bzrlib.builtins.cmd_revno()
191 cmd.outf = StringIO.StringIO()
192 cmd.run(location=self.repo)
193 current_revision = int(cmd.outf.getvalue())
194 if index > current_revision or index < -current_revision:
197 return str(index) # bzr commit 0 is the empty tree.
198 return str(current_revision+index+1)
200 def _diff(self, revision):
201 revision = self._parse_revision_string(revision)
202 cmd = bzrlib.builtins.cmd_diff()
203 cmd.outf = StringIO.StringIO()
204 # for some reason, cmd_diff uses sys.stdout not self.outf for output.
206 sys.stdout = cmd.outf
208 status = cmd.run(revision=revision, file_list=[self.repo])
211 assert status in [0,1], "Invalid status %d" % status
212 return cmd.outf.getvalue()
214 def _parse_diff(self, diff_text):
218 === modified file 'dir/changed'
219 --- dir/changed 2010-01-16 01:54:53 +0000
220 +++ dir/changed 2010-01-16 01:54:54 +0000
227 === removed file 'dir/deleted'
228 --- dir/deleted 2010-01-16 01:54:53 +0000
229 +++ dir/deleted 1970-01-01 00:00:00 +0000
235 === removed file 'dir/moved'
236 --- dir/moved 2010-01-16 01:54:53 +0000
237 +++ dir/moved 1970-01-01 00:00:00 +0000
244 === added file 'dir/moved2'
245 --- dir/moved2 1970-01-01 00:00:00 +0000
246 +++ dir/moved2 2010-01-16 01:54:34 +0000
253 === added file 'dir/new'
254 --- dir/new 1970-01-01 00:00:00 +0000
255 +++ dir/new 2010-01-16 01:54:54 +0000
264 for line in diff_text.splitlines():
265 if not line.startswith('=== '):
267 fields = line.split()
269 file = fields[-1].strip("'")
270 if action == 'added':
272 elif action == 'modified':
273 modified.append(file)
274 elif action == 'removed':
276 return (new,modified,removed)
278 def _vcs_changed(self, revision):
279 return self._parse_diff(self._diff(revision))
282 if libbe.TESTING == True:
283 base.make_vcs_testcase_subclasses(Bzr, sys.modules[__name__])
285 unitsuite =unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
286 suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()])