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