From 268713c0e2ed76edd84a2196b5c14fe1bc4ff08a Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 29 Dec 2009 10:39:09 -0500 Subject: Updated Darcs backend towards supporting .children(revision). ._vcs_isdir() and ._vcs_listdir() will need to parse the output of darcs show files [options] --patch REVISION PATH but both the --patch option and the PATH argument are new, and I can't get a recent enough version of Darcs to compile on my system. Theoretically they will work, but they remain untested for now. I don't think it's worth rolling my own darcs show files --patch REVISION to support earlier versions of Darcs, since the only solution I can think of now would be to check out the given revision and use os.walk() or some such, and that would be really ugly... Also added .version_cmp() for easy version comparison. Reindented ._vcs_get_file_contents() to remove trailing elses since the if clauses all contain returns. --- libbe/storage/vcs/darcs.py | 154 +++++++++++++++++++++++++++++++++------------ 1 file changed, 114 insertions(+), 40 deletions(-) (limited to 'libbe/storage/vcs/darcs.py') diff --git a/libbe/storage/vcs/darcs.py b/libbe/storage/vcs/darcs.py index 9a371d9..6d47ea5 100644 --- a/libbe/storage/vcs/darcs.py +++ b/libbe/storage/vcs/darcs.py @@ -53,9 +53,47 @@ class Darcs(base.VCS): def _vcs_version(self): status,output,error = self._u_invoke_client('--version') - num_part = output.split(' ')[0] - self.parsed_version = [int(i) for i in num_part.split('.')] - return output + return output.rstrip('\n') + + def version_cmp(self, *args): + """ + Compare the installed darcs version V_i with another version + V_o (given in *args). Returns + 1 if V_i > V_o, + 0 if V_i == V_o, and + -1 if V_i < V_o + >>> d = Darcs(repo='.') + >>> d._vcs_version = lambda : "2.3.1 (release)" + >>> d.version_cmp(2,3,1) + 0 + >>> d.version_cmp(2,3,2) + -1 + >>> d.version_cmp(2,3,0) + 1 + >>> d.version_cmp(3) + -1 + >>> d._vcs_version = lambda : "2.0.0pre2" + >>> d._parsed_version = None + >>> d.version_cmp(3) + Traceback (most recent call last): + ... + NotImplementedError: Cannot parse "2.0.0pre2" portion of Darcs version "2.0.0pre2" + invalid literal for int() with base 10: '0pre2' + """ + if not hasattr(self, '_parsed_version') \ + or self._parsed_version == None: + num_part = self._vcs_version().split(' ')[0] + try: + self._parsed_version = [int(i) for i in num_part.split('.')] + except ValueError, e: + raise NotImplementedError( + 'Cannot parse "%s" portion of Darcs version "%s"\n %s' + % (num_part, self._vcs_version(), str(e))) + cmps = [cmp(a,b) for a,b in zip(self._parsed_version, args)] + for c in cmps: + if c != 0: + return c + return 0 def _vcs_get_user_id(self): # following http://darcs.net/manual/node4.html#SECTION00410030000000000000 @@ -113,45 +151,81 @@ class Darcs(base.VCS): def _vcs_get_file_contents(self, path, revision=None): if revision == None: return base.VCS._vcs_get_file_contents(self, path, revision) + if self.version_cmp(2, 0, 0) == 1: + status,output,error = self._u_invoke_client( \ + 'show', 'contents', '--patch', revision, path) + return output + # Darcs versions < 2.0.0pre2 lack the 'show contents' command + + status,output,error = self._u_invoke_client( \ + 'diff', '--unified', '--from-patch', revision, path, + unicode_output=False) + major_patch = output + status,output,error = self._u_invoke_client( \ + 'diff', '--unified', '--patch', revision, path, + unicode_output=False) + target_patch = output + + # '--output -' to be supported in GNU patch > 2.5.9 + # but that hasn't been released as of June 30th, 2009. + + # Rewrite path to status before the patch we want + args=['patch', '--reverse', path] + status,output,error = self._u_invoke(args, stdin=major_patch) + # Now apply the patch we want + args=['patch', path] + status,output,error = self._u_invoke(args, stdin=target_patch) + + if os.path.exists(os.path.join(self.repo, path)) == True: + contents = base.VCS._vcs_get_file_contents(self, path) else: - if self.parsed_version[0] >= 2: - status,output,error = self._u_invoke_client( \ - 'show', 'contents', '--patch', revision, path) - return output + contents = '' + + # Now restore path to it's current incarnation + args=['patch', '--reverse', path] + status,output,error = self._u_invoke(args, stdin=target_patch) + args=['patch', path] + status,output,error = self._u_invoke(args, stdin=major_patch) + current_contents = base.VCS._vcs_get_file_contents(self, path) + return contents + + def _vcs_path(self, id, revision): + return self._u_find_id(id, revision) + + def _vcs_isdir(self, path, revision): + if self.version_cmp(2, 3, 1) == 1: + # Sun Nov 15 20:32:06 EST 2009 thomashartman1@gmail.com + # * add versioned show files functionality (darcs show files -p 'some patch') + status,output,error = self._u_invoke_client( \ + 'show', 'files', '--no-files', '--patch', revision) + children = output.rstrip('\n').splitlines() + rpath = '.' + children = [self._u_rel_path(c, rpath) for c in children] + if path in children: + return True + return False + # Darcs versions <= 2.3.1 lack the --patch option for 'show files' + raise NotImplementedError + + def _vcs_listdir(self, path, revision): + if self.version_cmp(2, 3, 1) == 1: + # Sun Nov 15 20:32:06 EST 2009 thomashartman1@gmail.com + # * add versioned show files functionality (darcs show files -p 'some patch') + # Wed Dec 9 05:42:21 EST 2009 Luca Molteni + # * resolve issue835 show file with file directory arguments + path = path.rstrip(os.path.sep) + status,output,error = self._u_invoke_client( \ + 'show', 'files', '--patch', revision, path) + files = output.rstrip('\n').splitlines() + if path == '.': + descendents = [self._u_rel_path(f, path) for f in files + if f != '.'] else: - # Darcs versions < 2.0.0pre2 lack the 'show contents' command - - status,output,error = self._u_invoke_client( \ - 'diff', '--unified', '--from-patch', revision, path, - unicode_output=False) - major_patch = output - status,output,error = self._u_invoke_client( \ - 'diff', '--unified', '--patch', revision, path, - unicode_output=False) - target_patch = output - - # '--output -' to be supported in GNU patch > 2.5.9 - # but that hasn't been released as of June 30th, 2009. - - # Rewrite path to status before the patch we want - args=['patch', '--reverse', path] - status,output,error = self._u_invoke(args, stdin=major_patch) - # Now apply the patch we want - args=['patch', path] - status,output,error = self._u_invoke(args, stdin=target_patch) - - if os.path.exists(os.path.join(self.repo, path)) == True: - contents = base.VCS._vcs_get_file_contents(self, path) - else: - contents = '' - - # Now restore path to it's current incarnation - args=['patch', '--reverse', path] - status,output,error = self._u_invoke(args, stdin=target_patch) - args=['patch', path] - status,output,error = self._u_invoke(args, stdin=major_patch) - current_contents = base.VCS._vcs_get_file_contents(self, path) - return contents + descendents = [self._u_rel_path(f, path) for f in files + if f.startswith(path)] + return [f for f in descendents if f.count(os.path.sep) == 0] + # Darcs versions <= 2.3.1 lack the --patch option for 'show files' + raise NotImplementedError def _vcs_commit(self, commitfile, allow_empty=False): id = self.get_user_id() -- cgit