96 return wctx |
96 return wctx |
97 else: |
97 else: |
98 return ctx.p1() |
98 return ctx.p1() |
99 |
99 |
100 |
100 |
|
101 def get_diff_chunks( |
|
102 ui, |
|
103 repo, |
|
104 diffopts, |
|
105 ctx1, |
|
106 ctx2, |
|
107 match, |
|
108 changes=None, |
|
109 stat=False, |
|
110 prefix=b'', |
|
111 root=b'', |
|
112 hunksfilterfn=None, |
|
113 ): |
|
114 if root: |
|
115 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root) |
|
116 else: |
|
117 relroot = b'' |
|
118 copysourcematch = None |
|
119 |
|
120 def compose(f, g): |
|
121 return lambda x: f(g(x)) |
|
122 |
|
123 def pathfn(f): |
|
124 return posixpath.join(prefix, f) |
|
125 |
|
126 if relroot != b'': |
|
127 # XXX relative roots currently don't work if the root is within a |
|
128 # subrepo |
|
129 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) |
|
130 uirelroot = uipathfn(pathfn(relroot)) |
|
131 relroot += b'/' |
|
132 for matchroot in match.files(): |
|
133 if not matchroot.startswith(relroot): |
|
134 ui.warn( |
|
135 _(b'warning: %s not inside relative root %s\n') |
|
136 % (uipathfn(pathfn(matchroot)), uirelroot) |
|
137 ) |
|
138 |
|
139 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path') |
|
140 match = matchmod.intersectmatchers(match, relrootmatch) |
|
141 copysourcematch = relrootmatch |
|
142 |
|
143 checkroot = repo.ui.configbool( |
|
144 b'devel', b'all-warnings' |
|
145 ) or repo.ui.configbool(b'devel', b'check-relroot') |
|
146 |
|
147 def relrootpathfn(f): |
|
148 if checkroot and not f.startswith(relroot): |
|
149 raise AssertionError( |
|
150 b"file %s doesn't start with relroot %s" % (f, relroot) |
|
151 ) |
|
152 return f[len(relroot) :] |
|
153 |
|
154 pathfn = compose(relrootpathfn, pathfn) |
|
155 |
|
156 if stat: |
|
157 diffopts = diffopts.copy(context=0, noprefix=False) |
|
158 # If an explicit --root was given, don't respect ui.relative-paths |
|
159 if not relroot: |
|
160 pathfn = compose(scmutil.getuipathfn(repo), pathfn) |
|
161 |
|
162 return ctx2.diff( |
|
163 ctx1, |
|
164 match, |
|
165 changes, |
|
166 opts=diffopts, |
|
167 pathfn=pathfn, |
|
168 copysourcematch=copysourcematch, |
|
169 hunksfilterfn=hunksfilterfn, |
|
170 ) |
|
171 |
|
172 |
101 def diffordiffstat( |
173 def diffordiffstat( |
102 ui, |
174 ui, |
103 repo, |
175 repo, |
104 diffopts, |
176 diffopts, |
105 ctx1, |
177 ctx1, |
113 root=b'', |
185 root=b'', |
114 listsubrepos=False, |
186 listsubrepos=False, |
115 hunksfilterfn=None, |
187 hunksfilterfn=None, |
116 ): |
188 ): |
117 '''show diff or diffstat.''' |
189 '''show diff or diffstat.''' |
118 if root: |
190 |
119 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root) |
191 chunks = get_diff_chunks( |
120 else: |
192 ui, |
121 relroot = b'' |
193 repo, |
122 copysourcematch = None |
194 diffopts, |
123 |
195 ctx1, |
124 def compose(f, g): |
196 ctx2, |
125 return lambda x: f(g(x)) |
197 match, |
126 |
198 changes=changes, |
127 def pathfn(f): |
199 stat=stat, |
128 return posixpath.join(prefix, f) |
200 prefix=prefix, |
129 |
201 root=root, |
130 if relroot != b'': |
202 hunksfilterfn=hunksfilterfn, |
131 # XXX relative roots currently don't work if the root is within a |
203 ) |
132 # subrepo |
|
133 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) |
|
134 uirelroot = uipathfn(pathfn(relroot)) |
|
135 relroot += b'/' |
|
136 for matchroot in match.files(): |
|
137 if not matchroot.startswith(relroot): |
|
138 ui.warn( |
|
139 _(b'warning: %s not inside relative root %s\n') |
|
140 % (uipathfn(pathfn(matchroot)), uirelroot) |
|
141 ) |
|
142 |
|
143 relrootmatch = scmutil.match(ctx2, pats=[relroot], default=b'path') |
|
144 match = matchmod.intersectmatchers(match, relrootmatch) |
|
145 copysourcematch = relrootmatch |
|
146 |
|
147 checkroot = repo.ui.configbool( |
|
148 b'devel', b'all-warnings' |
|
149 ) or repo.ui.configbool(b'devel', b'check-relroot') |
|
150 |
|
151 def relrootpathfn(f): |
|
152 if checkroot and not f.startswith(relroot): |
|
153 raise AssertionError( |
|
154 b"file %s doesn't start with relroot %s" % (f, relroot) |
|
155 ) |
|
156 return f[len(relroot) :] |
|
157 |
|
158 pathfn = compose(relrootpathfn, pathfn) |
|
159 |
204 |
160 if stat: |
205 if stat: |
161 diffopts = diffopts.copy(context=0, noprefix=False) |
206 diffopts = diffopts.copy(context=0, noprefix=False) |
162 width = 80 |
207 width = 80 |
163 if not ui.plain(): |
208 if not ui.plain(): |
164 width = ui.termwidth() - graphwidth |
209 width = ui.termwidth() - graphwidth |
165 # If an explicit --root was given, don't respect ui.relative-paths |
|
166 if not relroot: |
|
167 pathfn = compose(scmutil.getuipathfn(repo), pathfn) |
|
168 |
|
169 chunks = ctx2.diff( |
|
170 ctx1, |
|
171 match, |
|
172 changes, |
|
173 opts=diffopts, |
|
174 pathfn=pathfn, |
|
175 copysourcematch=copysourcematch, |
|
176 hunksfilterfn=hunksfilterfn, |
|
177 ) |
|
178 |
210 |
179 if fp is not None or ui.canwritewithoutlabels(): |
211 if fp is not None or ui.canwritewithoutlabels(): |
180 out = fp or ui |
212 out = fp or ui |
181 if stat: |
213 if stat: |
182 chunks = [patch.diffstat(util.iterlines(chunks), width=width)] |
214 chunks = [patch.diffstat(util.iterlines(chunks), width=width)] |
247 stat=stat, |
279 stat=stat, |
248 graphwidth=graphwidth, |
280 graphwidth=graphwidth, |
249 hunksfilterfn=self._makehunksfilter(ctx), |
281 hunksfilterfn=self._makehunksfilter(ctx), |
250 ) |
282 ) |
251 |
283 |
|
284 def getdiffstats(self, ui, ctx, diffopts, stat=False): |
|
285 chunks = get_diff_chunks( |
|
286 ui, |
|
287 ctx.repo(), |
|
288 diffopts, |
|
289 diff_parent(ctx), |
|
290 ctx, |
|
291 match=self._makefilematcher(ctx), |
|
292 stat=stat, |
|
293 hunksfilterfn=self._makehunksfilter(ctx), |
|
294 ) |
|
295 |
|
296 diffdata = [] |
|
297 for filename, additions, removals, binary in patch.diffstatdata( |
|
298 util.iterlines(chunks) |
|
299 ): |
|
300 diffdata.append( |
|
301 { |
|
302 b"name": filename, |
|
303 b"additions": additions, |
|
304 b"removals": removals, |
|
305 b"binary": binary, |
|
306 } |
|
307 ) |
|
308 |
|
309 return diffdata |
|
310 |
252 |
311 |
253 def changesetlabels(ctx): |
312 def changesetlabels(ctx): |
254 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()] |
313 labels = [b'log.changeset', b'changeset.%s' % ctx.phasestr()] |
255 if ctx.obsolete(): |
314 if ctx.obsolete(): |
256 labels.append(b'changeset.obsolete') |
315 labels.append(b'changeset.obsolete') |
523 fm.data( |
582 fm.data( |
524 copies=fm.formatdict(copies or {}, key=b'name', value=b'source') |
583 copies=fm.formatdict(copies or {}, key=b'name', value=b'source') |
525 ) |
584 ) |
526 |
585 |
527 if self._includestat or b'diffstat' in datahint: |
586 if self._includestat or b'diffstat' in datahint: |
528 self.ui.pushbuffer() |
587 data = self._differ.getdiffstats( |
529 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=True) |
588 self.ui, ctx, self._diffopts, stat=True |
530 fm.data(diffstat=self.ui.popbuffer()) |
589 ) |
|
590 fm.data(diffstat=fm.formatlist(data, name=b'diffstat')) |
531 if self._includediff or b'diff' in datahint: |
591 if self._includediff or b'diff' in datahint: |
532 self.ui.pushbuffer() |
592 self.ui.pushbuffer() |
533 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False) |
593 self._differ.showdiff(self.ui, ctx, self._diffopts, stat=False) |
534 fm.data(diff=self.ui.popbuffer()) |
594 fm.data(diff=self.ui.popbuffer()) |
535 |
595 |