diff --git a/hgext/convert/p4.py b/hgext/convert/p4.py --- a/hgext/convert/p4.py +++ b/hgext/convert/p4.py @@ -48,7 +48,7 @@ class p4_source(converter_source): def _parse_view(self, path): "Read changes affecting the path" - cmd = "p4 -G changes -s submitted '%s'" % path + cmd = 'p4 -G changes -s submitted "%s"' % path stdout = util.popen(cmd) for d in loaditer(stdout): c = d.get("change", None) @@ -67,7 +67,7 @@ class p4_source(converter_source): else: views = {"//": ""} else: - cmd = "p4 -G client -o '%s'" % path + cmd = 'p4 -G client -o "%s"' % path clientspec = marshal.load(util.popen(cmd)) views = {} @@ -142,7 +142,7 @@ class p4_source(converter_source): return self.heads def getfile(self, name, rev): - cmd = "p4 -G print '%s#%s'" % (self.depotname[name], rev) + cmd = 'p4 -G print "%s#%s"' % (self.depotname[name], rev) stdout = util.popen(cmd) mode = None diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -50,16 +50,25 @@ from mercurial.node import short from mercurial import cmdutil, util, commands import os, shlex, shutil, tempfile -def snapshot_node(ui, repo, files, node, tmproot): - '''snapshot files as of some revision''' +def snapshot(ui, repo, files, node, tmproot): + '''snapshot files as of some revision + if not using snapshot, -I/-X does not work and recursive diff + in tools like kdiff3 and meld displays too many files.''' dirname = os.path.basename(repo.root) if dirname == "": dirname = "root" - dirname = '%s.%s' % (dirname, short(node)) + if node is not None: + dirname = '%s.%s' % (dirname, short(node)) base = os.path.join(tmproot, dirname) os.mkdir(base) - ui.note(_('making snapshot of %d files from rev %s\n') % - (len(files), short(node))) + if node is not None: + ui.note(_('making snapshot of %d files from rev %s\n') % + (len(files), short(node))) + else: + ui.note(_('making snapshot of %d files from working directory\n') % + (len(files))) + wopener = util.opener(base) + fns_and_mtime = [] ctx = repo[node] for fn in files: wfn = util.pconvert(fn) @@ -68,47 +77,18 @@ def snapshot_node(ui, repo, files, node, continue ui.note(' %s\n' % wfn) dest = os.path.join(base, wfn) - destdir = os.path.dirname(dest) - if not os.path.isdir(destdir): - os.makedirs(destdir) - data = repo.wwritedata(wfn, ctx[wfn].data()) - open(dest, 'wb').write(data) - return dirname - - -def snapshot_wdir(ui, repo, files, tmproot): - '''snapshot files from working directory. - if not using snapshot, -I/-X does not work and recursive diff - in tools like kdiff3 and meld displays too many files.''' - dirname = os.path.basename(repo.root) - if dirname == "": - dirname = "root" - base = os.path.join(tmproot, dirname) - os.mkdir(base) - ui.note(_('making snapshot of %d files from working directory\n') % - (len(files))) - - fns_and_mtime = [] - - for fn in files: - wfn = util.pconvert(fn) - ui.note(' %s\n' % wfn) - dest = os.path.join(base, wfn) - destdir = os.path.dirname(dest) - if not os.path.isdir(destdir): - os.makedirs(destdir) - - fp = open(dest, 'wb') - for chunk in util.filechunkiter(repo.wopener(wfn)): - fp.write(chunk) - fp.close() - - fns_and_mtime.append((dest, repo.wjoin(fn), os.path.getmtime(dest))) - - + fctx = ctx[wfn] + data = repo.wwritedata(wfn, fctx.data()) + if 'l' in fctx.flags(): + wopener.symlink(data, wfn) + else: + wopener(wfn, 'w').write(data) + if 'x' in fctx.flags(): + util.set_flags(dest, False, True) + if node is None: + fns_and_mtime.append((dest, repo.wjoin(fn), os.path.getmtime(dest))) return dirname, fns_and_mtime - def dodiff(ui, repo, diffcmd, diffopts, pats, opts): '''Do the actuall diff: @@ -139,24 +119,17 @@ def dodiff(ui, repo, diffcmd, diffopts, dir2root = '' try: # Always make a copy of node1 - dir1 = snapshot_node(ui, repo, modified + removed, node1, tmproot) + dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0] changes = len(modified) + len(removed) + len(added) - fns_and_mtime = [] - # If node2 in not the wc or there is >1 change, copy it - if node2: - dir2 = snapshot_node(ui, repo, modified + added, node2, tmproot) - elif changes > 1: - #we only actually need to get the files to copy back to the working - #dir in this case (because the other cases are: diffing 2 revisions - #or single file -- in which case the file is already directly passed - #to the diff tool). - dir2, fns_and_mtime = snapshot_wdir(ui, repo, modified + added, tmproot) + if node2 or changes > 1: + dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot) else: # This lets the diff tool open the changed file directly dir2 = '' dir2root = repo.root + fns_and_mtime = [] # If only one change, diff the files instead of the directories if changes == 1 : diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -513,7 +513,7 @@ class workingctx(changectx): return True def __contains__(self, key): - return self._dirstate[key] not in "?r" + return self._repo.dirstate[key] not in "?r" def _manifest(self): """generate a manifest corresponding to the working directory""" diff --git a/tests/test-convert-p4 b/tests/test-convert-p4 old mode 100644 new mode 100755 --- a/tests/test-convert-p4 +++ b/tests/test-convert-p4 @@ -63,9 +63,9 @@ hg -R dst log --template 'rev=#rev# desc echo % interesting names echo dddd > "d d" -mkdir " e " -echo fff >" e /f " -p4 add "d d" " e /f " +mkdir " e" +echo fff >" e/ f" +p4 add "d d" " e/ f" p4 submit -d "add d e f" echo % convert again diff --git a/tests/test-convert-p4.out b/tests/test-convert-p4.out --- a/tests/test-convert-p4.out +++ b/tests/test-convert-p4.out @@ -62,10 +62,10 @@ rev=1 desc="change a" tags="" files="a" rev=0 desc="initial" tags="" files="a b/c" % interesting names //depot/test-mercurial-import/d d#1 - opened for add -//depot/test-mercurial-import/ e /f #1 - opened for add +//depot/test-mercurial-import/ e/ f#1 - opened for add Submitting change 5. Locking 2 files ... -add //depot/test-mercurial-import/ e /f #1 +add //depot/test-mercurial-import/ e/ f#1 add //depot/test-mercurial-import/d d#1 Change 5 submitted. % convert again @@ -80,7 +80,7 @@ scanning source... sorting... converting... 0 add d e f -rev=4 desc="add d e f" tags="tip" files=" e /f d d" +rev=4 desc="add d e f" tags="tip" files=" e/ f d d" rev=3 desc="change a b/c" tags="" files="a b/c" rev=2 desc="change b/c" tags="" files="b/c" rev=1 desc="change a" tags="" files="a" diff --git a/tests/test-extdiff b/tests/test-extdiff --- a/tests/test-extdiff +++ b/tests/test-extdiff @@ -28,7 +28,7 @@ hg ci -d '1 0' -mtest2 hg falabala -r 0:1 # test diff during merge -hg update 0 +hg update -C 0 echo c >> c hg add c hg ci -m "new branch" -d '1 0' @@ -43,3 +43,24 @@ hg falabala -c 1 # check diff are made from the first parent hg falabala -c 3 || echo "diff-like tools yield a non-zero exit code" #hg log + +echo +echo '% test extdiff of multiple files in tmp dir:' +hg update -C 0 > /dev/null +echo changed > a +echo changed > b +chmod +x b +echo '% diff in working directory, before' +hg diff --git +echo '% edit with extdiff -p' +# prepare custom diff/edit tool +cat > differ.sh << EOT +#!/bin/sh +sleep 1 # avoid unchanged-timestamp problems +echo edited >> a/a +echo edited >> a/b +EOT +chmod +x differ.sh +hg extdiff -p `pwd`/differ.sh # will change to /tmp/extdiff.TMP and populate directories a.TMP and a and start tool +echo '% diff in working directory, after' +hg diff --git diff --git a/tests/test-extdiff.out b/tests/test-extdiff.out --- a/tests/test-extdiff.out +++ b/tests/test-extdiff.out @@ -34,3 +34,38 @@ diffing a.2a13a4d2da36/a [tmp]/test-extd diffing a.8a5febb7f867/a a.34eed99112ab/a diffing a.2a13a4d2da36/a a.46c0e4daeb72/a diff-like tools yield a non-zero exit code + +% test extdiff of multiple files in tmp dir: +% diff in working directory, before +diff --git a/a b/a +--- a/a ++++ b/a +@@ -1,1 +1,1 @@ +-a ++changed +diff --git a/b b/b +old mode 100644 +new mode 100755 +--- a/b ++++ b/b +@@ -1,1 +1,1 @@ +-b ++changed +% edit with extdiff -p +% diff in working directory, after +diff --git a/a b/a +--- a/a ++++ b/a +@@ -1,1 +1,2 @@ +-a ++changed ++edited +diff --git a/b b/b +old mode 100644 +new mode 100755 +--- a/b ++++ b/b +@@ -1,1 +1,2 @@ +-b ++changed ++edited diff --git a/tests/test-issue1438 b/tests/test-issue1438 old mode 100644 new mode 100755