##// END OF EJS Templates
fix traceback of extdiff after a merge...
Benoit Boissinot -
r3330:49966b5a default
parent child Browse files
Show More
@@ -1,184 +1,187
1 1 # extdiff.py - external diff program support for mercurial
2 2 #
3 3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7 #
8 8 # The `extdiff' Mercurial extension allows you to use external programs
9 9 # to compare revisions, or revision with working dir. The external diff
10 10 # programs are called with a configurable set of options and two
11 11 # non-option arguments: paths to directories containing snapshots of
12 12 # files to compare.
13 13 #
14 14 # To enable this extension:
15 15 #
16 16 # [extensions]
17 17 # hgext.extdiff =
18 18 #
19 19 # The `extdiff' extension also allows to configure new diff commands, so
20 20 # you do not need to type "hg extdiff -p kdiff3" always.
21 21 #
22 22 # [extdiff]
23 23 # # add new command that runs GNU diff(1) in 'context diff' mode
24 24 # cmd.cdiff = gdiff
25 25 # opts.cdiff = -Nprc5
26 26
27 27 # # add new command called vdiff, runs kdiff3
28 28 # cmd.vdiff = kdiff3
29 29
30 30 # # add new command called meld, runs meld (no need to name twice)
31 31 # cmd.meld =
32 32
33 33 # # add new command called vimdiff, runs gvimdiff with DirDiff plugin
34 34 # #(see http://www.vim.org/scripts/script.php?script_id=102)
35 35 # # Non english user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
36 36 # # your .vimrc
37 37 # cmd.vimdiff = gvim
38 38 # opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
39 39 #
40 40 # Each custom diff commands can have two parts: a `cmd' and an `opts'
41 41 # part. The cmd.xxx option defines the name of an executable program
42 42 # that will be run, and opts.xxx defines a set of command-line options
43 43 # which will be inserted to the command between the program name and
44 44 # the files/directories to diff (i.e. the cdiff example above).
45 45 #
46 46 # You can use -I/-X and list of file or directory names like normal
47 47 # "hg diff" command. The `extdiff' extension makes snapshots of only
48 48 # needed files, so running the external diff program will actually be
49 49 # pretty fast (at least faster than having to compare the entire tree).
50 50
51 51 from mercurial.demandload import demandload
52 52 from mercurial.i18n import gettext as _
53 53 from mercurial.node import *
54 54 demandload(globals(), 'mercurial:cmdutil,util os shutil tempfile')
55 55
56 56 def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
57 57 def snapshot_node(files, node):
58 58 '''snapshot files as of some revision'''
59 59 changes = repo.changelog.read(node)
60 60 mf = repo.manifest.read(changes[0])
61 61 dirname = '%s.%s' % (os.path.basename(repo.root), short(node))
62 62 base = os.path.join(tmproot, dirname)
63 63 os.mkdir(base)
64 64 if not ui.quiet:
65 65 ui.write_err(_('making snapshot of %d files from rev %s\n') %
66 66 (len(files), short(node)))
67 67 for fn in files:
68 if not fn in mf:
69 # skipping new file after a merge ?
70 continue
68 71 wfn = util.pconvert(fn)
69 72 ui.note(' %s\n' % wfn)
70 73 dest = os.path.join(base, wfn)
71 74 destdir = os.path.dirname(dest)
72 75 if not os.path.isdir(destdir):
73 76 os.makedirs(destdir)
74 77 repo.wwrite(wfn, repo.file(fn).read(mf[fn]), open(dest, 'w'))
75 78 return dirname
76 79
77 80 def snapshot_wdir(files):
78 81 '''snapshot files from working directory.
79 82 if not using snapshot, -I/-X does not work and recursive diff
80 83 in tools like kdiff3 and meld displays too many files.'''
81 84 dirname = os.path.basename(repo.root)
82 85 base = os.path.join(tmproot, dirname)
83 86 os.mkdir(base)
84 87 if not ui.quiet:
85 88 ui.write_err(_('making snapshot of %d files from working dir\n') %
86 89 (len(files)))
87 90 for fn in files:
88 91 wfn = util.pconvert(fn)
89 92 ui.note(' %s\n' % wfn)
90 93 dest = os.path.join(base, wfn)
91 94 destdir = os.path.dirname(dest)
92 95 if not os.path.isdir(destdir):
93 96 os.makedirs(destdir)
94 97 fp = open(dest, 'w')
95 98 for chunk in util.filechunkiter(repo.wopener(wfn)):
96 99 fp.write(chunk)
97 100 return dirname
98 101
99 102 node1, node2 = cmdutil.revpair(ui, repo, opts['rev'])
100 103 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
101 104 modified, added, removed, deleted, unknown = repo.status(
102 105 node1, node2, files, match=matchfn)[:5]
103 106 if not (modified or added or removed):
104 107 return 0
105 108
106 109 tmproot = tempfile.mkdtemp(prefix='extdiff.')
107 110 try:
108 111 dir1 = snapshot_node(modified + removed, node1)
109 112 if node2:
110 113 dir2 = snapshot_node(modified + added, node2)
111 114 else:
112 115 dir2 = snapshot_wdir(modified + added)
113 116 cmdline = ('%s %s %s %s' %
114 117 (util.shellquote(diffcmd), ' '.join(diffopts),
115 118 util.shellquote(dir1), util.shellquote(dir2)))
116 119 ui.debug('running %r in %s\n' % (cmdline, tmproot))
117 120 util.system(cmdline, cwd=tmproot)
118 121 return 1
119 122 finally:
120 123 ui.note(_('cleaning up temp directory\n'))
121 124 shutil.rmtree(tmproot)
122 125
123 126 def extdiff(ui, repo, *pats, **opts):
124 127 '''use external program to diff repository (or selected files)
125 128
126 129 Show differences between revisions for the specified files, using
127 130 an external program. The default program used is diff, with
128 131 default options "-Npru".
129 132
130 133 To select a different program, use the -p option. The program
131 134 will be passed the names of two directories to compare. To pass
132 135 additional options to the program, use the -o option. These will
133 136 be passed before the names of the directories to compare.
134 137
135 138 When two revision arguments are given, then changes are
136 139 shown between those revisions. If only one revision is
137 140 specified then that revision is compared to the working
138 141 directory, and, when no revisions are specified, the
139 142 working directory files are compared to its parent.'''
140 143 program = opts['program'] or 'diff'
141 144 if opts['program']:
142 145 option = opts['option']
143 146 else:
144 147 option = opts['option'] or ['-Npru']
145 148 return dodiff(ui, repo, program, option, pats, opts)
146 149
147 150 cmdtable = {
148 151 "extdiff":
149 152 (extdiff,
150 153 [('p', 'program', '', _('comparison program to run')),
151 154 ('o', 'option', [], _('pass option to comparison program')),
152 155 ('r', 'rev', [], _('revision')),
153 156 ('I', 'include', [], _('include names matching the given patterns')),
154 157 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
155 158 _('hg extdiff [OPT]... [FILE]...')),
156 159 }
157 160
158 161 def uisetup(ui):
159 162 for cmd, path in ui.configitems('extdiff'):
160 163 if not cmd.startswith('cmd.'): continue
161 164 cmd = cmd[4:]
162 165 if not path: path = cmd
163 166 diffopts = ui.config('extdiff', 'opts.' + cmd, '')
164 167 diffopts = diffopts and [diffopts] or []
165 168 def save(cmd, path, diffopts):
166 169 '''use closure to save diff command to use'''
167 170 def mydiff(ui, repo, *pats, **opts):
168 171 return dodiff(ui, repo, path, diffopts, pats, opts)
169 172 mydiff.__doc__ = '''use %(path)r to diff repository (or selected files)
170 173
171 174 Show differences between revisions for the specified
172 175 files, using the %(path)r program.
173 176
174 177 When two revision arguments are given, then changes are
175 178 shown between those revisions. If only one revision is
176 179 specified then that revision is compared to the working
177 180 directory, and, when no revisions are specified, the
178 181 working directory files are compared to its parent.''' % {
179 182 'path': path,
180 183 }
181 184 return mydiff
182 185 cmdtable[cmd] = (save(cmd, path, diffopts),
183 186 cmdtable['extdiff'][1][1:],
184 187 _('hg %s [OPT]... [FILE]...') % cmd)
@@ -1,29 +1,38
1 1 #!/bin/sh
2 2
3 3 echo "[extensions]" >> $HGRCPATH
4 4 echo "extdiff=" >> $HGRCPATH
5 5
6 6 hg init a
7 7 cd a
8 8 echo a > a
9 9 hg add
10 10 diff -N /dev/null /dev/null 2> /dev/null
11 11 if [ $? -ne 0 ]; then
12 12 opt="-p gdiff"
13 13 fi
14 14 hg extdiff -o -Nr $opt
15 15
16 16 echo "[extdiff]" >> $HGRCPATH
17 17 echo "cmd.falabala=echo" >> $HGRCPATH
18 18 echo "opts.falabala=diffing" >> $HGRCPATH
19 19
20 20 hg falabala
21 21
22 22 hg help falabala
23 23
24 24 hg ci -d '0 0' -mtest1
25 25
26 26 echo b >> a
27 27 hg ci -d '1 0' -mtest2
28 28
29 hg falabala -r 0:1 || echo "diff-like tools yield a non-zero exit code"
29 hg falabala -r 0:1
30
31 # test diff during merge
32 hg update 0
33 echo b >> b
34 hg add b
35 hg ci -m "new branch" -d '1 0'
36 hg update -C 1
37 hg merge tip
38 hg falabala || echo "diff-like tools yield a non-zero exit code"
@@ -1,32 +1,39
1 1 adding a
2 2 making snapshot of 0 files from rev 000000000000
3 3 making snapshot of 1 files from working dir
4 4 diff -Nr a.000000000000/a a/a
5 5 0a1
6 6 > a
7 7 making snapshot of 0 files from rev 000000000000
8 8 making snapshot of 1 files from working dir
9 9 diffing a.000000000000 a
10 10 hg falabala [OPT]... [FILE]...
11 11
12 12 use 'echo' to diff repository (or selected files)
13 13
14 14 Show differences between revisions for the specified
15 15 files, using the 'echo' program.
16 16
17 17 When two revision arguments are given, then changes are
18 18 shown between those revisions. If only one revision is
19 19 specified then that revision is compared to the working
20 20 directory, and, when no revisions are specified, the
21 21 working directory files are compared to its parent.
22 22
23 23 options:
24 24
25 25 -o --option pass option to comparison program
26 26 -r --rev revision
27 27 -I --include include names matching the given patterns
28 28 -X --exclude exclude names matching the given patterns
29 29 making snapshot of 1 files from rev e27a2475d60a
30 30 making snapshot of 1 files from rev 5e49ec8d3f05
31 31 diffing a.e27a2475d60a a.5e49ec8d3f05
32 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
34 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 (branch merge, don't forget to commit)
36 making snapshot of 1 files from rev 5e49ec8d3f05
37 making snapshot of 1 files from working dir
38 diffing a.5e49ec8d3f05 a
32 39 diff-like tools yield a non-zero exit code
@@ -1,96 +1,104
1 1 #!/bin/sh
2 2
3 3 cat <<'EOF' > merge
4 4 #!/bin/sh
5 5 echo merging for `basename $1`
6 6 EOF
7 7 chmod +x merge
8 8
9 9 mkdir t
10 10 cd t
11 11 hg init
12 12 echo This is file a1 > a
13 13 hg add a
14 14 hg commit -m "commit #0" -d "1000000 0"
15 15 echo This is file b1 > b
16 16 hg add b
17 17 hg commit -m "commit #1" -d "1000000 0"
18 18
19 19 hg update 0
20 20 echo This is file c1 > c
21 21 hg add c
22 22 hg commit -m "commit #2" -d "1000000 0"
23 23 echo This is file b1 > b
24 24 echo %% no merges expected
25 25 env HGMERGE=../merge hg merge 1
26 hg diff --nodates
27 hg status
26 28 cd ..; /bin/rm -rf t
27 29
28 30 mkdir t
29 31 cd t
30 32 hg init
31 33 echo This is file a1 > a
32 34 hg add a
33 35 hg commit -m "commit #0" -d "1000000 0"
34 36 echo This is file b1 > b
35 37 hg add b
36 38 hg commit -m "commit #1" -d "1000000 0"
37 39
38 40 hg update 0
39 41 echo This is file c1 > c
40 42 hg add c
41 43 hg commit -m "commit #2" -d "1000000 0"
42 44 echo This is file b2 > b
43 45 echo %% merge should fail
44 46 env HGMERGE=../merge hg merge 1
45 47 echo %% merge of b expected
46 48 env HGMERGE=../merge hg merge -f 1
49 hg diff --nodates
50 hg status
47 51 cd ..; /bin/rm -rf t
48 52 echo %%
49 53
50 54 mkdir t
51 55 cd t
52 56 hg init
53 57 echo This is file a1 > a
54 58 hg add a
55 59 hg commit -m "commit #0" -d "1000000 0"
56 60 echo This is file b1 > b
57 61 hg add b
58 62 hg commit -m "commit #1" -d "1000000 0"
59 63 echo This is file b22 > b
60 64 hg commit -m "commit #2" -d "1000000 0"
61 65 hg update 1
62 66 echo This is file c1 > c
63 67 hg add c
64 68 hg commit -m "commit #3" -d "1000000 0"
65 69
66 70 echo 'Contents of b should be "this is file b1"'
67 71 cat b
68 72
69 73 echo This is file b22 > b
70 74 echo %% merge fails
71 75 env HGMERGE=../merge hg merge 2
72 76 echo %% merge expected!
73 77 env HGMERGE=../merge hg merge -f 2
78 hg diff --nodates
79 hg status
74 80 cd ..; /bin/rm -rf t
75 81
76 82 mkdir t
77 83 cd t
78 84 hg init
79 85 echo This is file a1 > a
80 86 hg add a
81 87 hg commit -m "commit #0" -d "1000000 0"
82 88 echo This is file b1 > b
83 89 hg add b
84 90 hg commit -m "commit #1" -d "1000000 0"
85 91 echo This is file b22 > b
86 92 hg commit -m "commit #2" -d "1000000 0"
87 93 hg update 1
88 94 echo This is file c1 > c
89 95 hg add c
90 96 hg commit -m "commit #3" -d "1000000 0"
91 97 echo This is file b33 > b
92 98 echo %% merge of b should fail
93 99 env HGMERGE=../merge hg merge 2
94 100 echo %% merge of b expected
95 101 env HGMERGE=../merge hg merge -f 2
102 hg diff --nodates
103 hg status
96 104 cd ..; /bin/rm -rf t
@@ -1,33 +1,59
1 1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2 2 %% no merges expected
3 3 merging for b
4 4 merging b
5 5 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
6 6 (branch merge, don't forget to commit)
7 diff -r d9e5953b9dec b
8 --- /dev/null
9 +++ b/b
10 @@ -0,0 +1,1 @@
11 +This is file b1
12 M b
7 13 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
8 14 %% merge should fail
9 15 abort: 'b' already exists in the working dir and differs from remote
10 16 %% merge of b expected
11 17 merging for b
12 18 merging b
13 19 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
14 20 (branch merge, don't forget to commit)
21 diff -r d9e5953b9dec b
22 --- /dev/null
23 +++ b/b
24 @@ -0,0 +1,1 @@
25 +This is file b2
26 M b
15 27 %%
16 28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 29 Contents of b should be "this is file b1"
18 30 This is file b1
19 31 %% merge fails
20 32 abort: outstanding uncommitted changes
21 33 %% merge expected!
22 34 merging for b
23 35 merging b
24 36 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
25 37 (branch merge, don't forget to commit)
38 diff -r c1dd73cbf59f b
39 --- a/b
40 +++ b/b
41 @@ -1,1 +1,1 @@ This is file b1
42 -This is file b1
43 +This is file b22
44 M b
26 45 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 46 %% merge of b should fail
28 47 abort: outstanding uncommitted changes
29 48 %% merge of b expected
30 49 merging for b
31 50 merging b
32 51 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
33 52 (branch merge, don't forget to commit)
53 diff -r c1dd73cbf59f b
54 --- a/b
55 +++ b/b
56 @@ -1,1 +1,1 @@ This is file b1
57 -This is file b1
58 +This is file b33
59 M b
General Comments 0
You need to be logged in to leave comments. Login now