33 return util.matcher(repo, cwd, pats or ['.'], opts.get('include'), |
33 return util.matcher(repo, cwd, pats or ['.'], opts.get('include'), |
34 opts.get('exclude'), head) |
34 opts.get('exclude'), head) |
35 |
35 |
36 def makewalk(repo, pats, opts, head = ''): |
36 def makewalk(repo, pats, opts, head = ''): |
37 cwd = repo.getcwd() |
37 cwd = repo.getcwd() |
38 files, matchfn = matchpats(repo, cwd, pats, opts, head) |
38 files, matchfn, anypats = matchpats(repo, cwd, pats, opts, head) |
39 exact = dict(zip(files, files)) |
39 exact = dict(zip(files, files)) |
40 def walk(): |
40 def walk(): |
41 for src, fn in repo.walk(files = files, match = matchfn): |
41 for src, fn in repo.walk(files = files, match = matchfn): |
42 yield src, fn, util.pathto(cwd, fn), fn in exact |
42 yield src, fn, util.pathto(cwd, fn), fn in exact |
43 return files, matchfn, walk() |
43 return files, matchfn, walk() |
191 for f in d: |
191 for f in d: |
192 to = repo.file(f).read(mmap[f]) |
192 to = repo.file(f).read(mmap[f]) |
193 tn = None |
193 tn = None |
194 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text)) |
194 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text)) |
195 |
195 |
196 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None, brinfo=None): |
196 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None): |
197 """show a single changeset or file revision""" |
197 """show a single changeset or file revision""" |
198 changelog = repo.changelog |
198 log = repo.changelog |
199 if filelog: |
199 if changenode is None: |
200 log = filelog |
200 changenode = log.node(rev) |
201 filerev = rev |
201 elif not rev: |
202 node = filenode = filelog.node(filerev) |
202 rev = log.rev(changenode) |
203 changerev = filelog.linkrev(filenode) |
|
204 changenode = changenode or changelog.node(changerev) |
|
205 else: |
|
206 log = changelog |
|
207 changerev = rev |
|
208 if changenode is None: |
|
209 changenode = changelog.node(changerev) |
|
210 elif not changerev: |
|
211 rev = changerev = changelog.rev(changenode) |
|
212 node = changenode |
|
213 |
203 |
214 if ui.quiet: |
204 if ui.quiet: |
215 ui.write("%d:%s\n" % (rev, hg.short(node))) |
205 ui.write("%d:%s\n" % (rev, hg.short(changenode))) |
216 return |
206 return |
217 |
207 |
218 changes = changelog.read(changenode) |
208 changes = log.read(changenode) |
219 |
209 |
220 t, tz = changes[2].split(' ') |
210 t, tz = changes[2].split(' ') |
221 # a conversion tool was sticking non-integer offsets into repos |
211 # a conversion tool was sticking non-integer offsets into repos |
222 try: |
212 try: |
223 tz = int(tz) |
213 tz = int(tz) |
224 except ValueError: |
214 except ValueError: |
225 tz = 0 |
215 tz = 0 |
226 date = time.asctime(time.localtime(float(t))) + " %+05d" % (int(tz)/-36) |
216 date = time.asctime(time.localtime(float(t))) + " %+05d" % (int(tz)/-36) |
227 |
217 |
228 parents = [(log.rev(p), ui.verbose and hg.hex(p) or hg.short(p)) |
218 parents = [(log.rev(p), ui.verbose and hg.hex(p) or hg.short(p)) |
229 for p in log.parents(node) |
219 for p in log.parents(changenode) |
230 if ui.debugflag or p != hg.nullid] |
220 if ui.debugflag or p != hg.nullid] |
231 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1: |
221 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1: |
232 parents = [] |
222 parents = [] |
233 |
223 |
234 if ui.verbose: |
224 if ui.verbose: |
235 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode))) |
225 ui.write("changeset: %d:%s\n" % (rev, hg.hex(changenode))) |
236 else: |
226 else: |
237 ui.write("changeset: %d:%s\n" % (changerev, hg.short(changenode))) |
227 ui.write("changeset: %d:%s\n" % (rev, hg.short(changenode))) |
238 |
228 |
239 for tag in repo.nodetags(changenode): |
229 for tag in repo.nodetags(changenode): |
240 ui.status("tag: %s\n" % tag) |
230 ui.status("tag: %s\n" % tag) |
241 for parent in parents: |
231 for parent in parents: |
242 ui.write("parent: %d:%s\n" % parent) |
232 ui.write("parent: %d:%s\n" % parent) |
243 if filelog: |
|
244 ui.debug("file rev: %d:%s\n" % (filerev, hg.hex(filenode))) |
|
245 |
233 |
246 if brinfo and changenode in brinfo: |
234 if brinfo and changenode in brinfo: |
247 br = brinfo[changenode] |
235 br = brinfo[changenode] |
248 ui.write("branch: %s\n" % " ".join(br)) |
236 ui.write("branch: %s\n" % " ".join(br)) |
249 |
237 |
558 addremove(ui, repo, *pats, **opts) |
546 addremove(ui, repo, *pats, **opts) |
559 cwd = repo.getcwd() |
547 cwd = repo.getcwd() |
560 if not pats and cwd: |
548 if not pats and cwd: |
561 opts['include'] = [os.path.join(cwd, i) for i in opts['include']] |
549 opts['include'] = [os.path.join(cwd, i) for i in opts['include']] |
562 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']] |
550 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']] |
563 fns, match = matchpats(repo, (pats and repo.getcwd()) or '', pats, opts) |
551 fns, match, anypats = matchpats(repo, (pats and repo.getcwd()) or '', |
|
552 pats, opts) |
564 if pats: |
553 if pats: |
565 c, a, d, u = repo.changes(files = fns, match = match) |
554 c, a, d, u = repo.changes(files = fns, match = match) |
566 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r'] |
555 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r'] |
567 else: |
556 else: |
568 files = [] |
557 files = [] |
847 if opts['fullpath']: |
836 if opts['fullpath']: |
848 ui.write(os.path.join(repo.root, abs), end) |
837 ui.write(os.path.join(repo.root, abs), end) |
849 else: |
838 else: |
850 ui.write(rel, end) |
839 ui.write(rel, end) |
851 |
840 |
852 def log(ui, repo, f=None, **opts): |
841 def log(ui, repo, *pats, **opts): |
853 """show the revision history of the repository or a single file""" |
842 """show revision history of entire repository or files""" |
854 if f: |
843 # This code most commonly needs to iterate backwards over the |
855 files = relpath(repo, [f]) |
844 # history it is interested in. This has awful (quadratic-looking) |
856 filelog = repo.file(files[0]) |
845 # performance, so we use iterators that walk forwards through |
857 log = filelog |
846 # windows of revisions, yielding revisions in reverse order, while |
858 lookup = filelog.lookup |
847 # walking the windows backwards. |
859 else: |
848 files, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts) |
860 files = None |
849 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0'])) |
861 filelog = None |
850 wanted = {} |
862 log = repo.changelog |
851 slowpath = anypats |
863 lookup = repo.lookup |
852 window = 300 |
864 revlist = [] |
853 if not slowpath and not files: |
865 revs = [log.rev(lookup(rev)) for rev in opts['rev']] |
854 # No files, no patterns. Display all revs. |
866 while revs: |
855 wanted = dict(zip(revs, revs)) |
867 if len(revs) == 1: |
856 if not slowpath: |
868 revlist.append(revs.pop(0)) |
857 # Only files, no patterns. Check the history of each file. |
869 else: |
858 def filerevgen(filelog): |
870 a = revs.pop(0) |
859 for i in xrange(filelog.count() - 1, 0, -window): |
871 b = revs.pop(0) |
860 revs = [] |
872 off = a > b and -1 or 1 |
861 for j in xrange(max(0, i - window), i): |
873 revlist.extend(range(a, b + off, off)) |
862 revs.append(filelog.linkrev(filelog.node(j))) |
874 |
863 revs.reverse() |
875 for i in revlist or range(log.count() - 1, -1, -1): |
864 for rev in revs: |
876 show_changeset(ui, repo, filelog=filelog, rev=i) |
865 yield rev |
|
866 |
|
867 minrev, maxrev = min(revs), max(revs) |
|
868 for filelog in map(repo.file, files): |
|
869 # A zero count may be a directory or deleted file, so |
|
870 # try to find matching entries on the slow path. |
|
871 if filelog.count() == 0: |
|
872 slowpath = True |
|
873 break |
|
874 for rev in filerevgen(filelog): |
|
875 if rev <= maxrev: |
|
876 if rev < minrev: break |
|
877 wanted[rev] = 1 |
|
878 if slowpath: |
|
879 # The slow path checks files modified in every changeset. |
|
880 def mfrevgen(): |
|
881 for i in xrange(repo.changelog.count() - 1, 0, -window): |
|
882 for j in xrange(max(0, i - window), i): |
|
883 yield j, repo.changelog.read(repo.lookup(str(j)))[3] |
|
884 |
|
885 for rev, mf in mfrevgen(): |
|
886 if filter(matchfn, mf): |
|
887 wanted[rev] = 1 |
|
888 |
|
889 def changerevgen(): |
|
890 class dui: |
|
891 # Implement and delegate some ui protocol. Save hunks of |
|
892 # output for later display in the desired order. |
|
893 def __init__(self, ui): |
|
894 self.ui = ui |
|
895 self.hunk = {} |
|
896 def bump(self, rev): |
|
897 self.rev = rev |
|
898 self.hunk[rev] = [] |
|
899 def status(self, *args): |
|
900 if not self.quiet: self.write(*args) |
|
901 def write(self, *args): |
|
902 self.hunk[self.rev].append(args) |
|
903 def __getattr__(self, key): |
|
904 return getattr(self.ui, key) |
|
905 for i in xrange(0, len(revs), window): |
|
906 nrevs = [rev for rev in revs[i : min(i + window, len(revs))] |
|
907 if rev in wanted] |
|
908 srevs = list(nrevs) |
|
909 srevs.sort() |
|
910 du = dui(ui) |
|
911 for rev in srevs: |
|
912 du.bump(rev) |
|
913 yield rev, du |
|
914 for rev in nrevs: |
|
915 for args in du.hunk[rev]: |
|
916 ui.write(*args) |
|
917 |
|
918 for rev, dui in changerevgen(): |
|
919 show_changeset(dui, repo, rev) |
877 if opts['patch']: |
920 if opts['patch']: |
878 if filelog: |
921 changenode = repo.changelog.node(rev) |
879 filenode = filelog.node(i) |
|
880 i = filelog.linkrev(filenode) |
|
881 changenode = repo.changelog.node(i) |
|
882 prev, other = repo.changelog.parents(changenode) |
922 prev, other = repo.changelog.parents(changenode) |
883 dodiff(sys.stdout, ui, repo, prev, changenode, files) |
923 dodiff(dui, dui, repo, prev, changenode, files) |
884 ui.write("\n\n") |
924 du.write("\n\n") |
885 |
925 |
886 def manifest(ui, repo, rev=None): |
926 def manifest(ui, repo, rev=None): |
887 """output the latest or given revision of the project manifest""" |
927 """output the latest or given revision of the project manifest""" |
888 if rev: |
928 if rev: |
889 try: |
929 try: |
1376 ('I', 'include', [], 'include path in search'), |
1416 ('I', 'include', [], 'include path in search'), |
1377 ('X', 'exclude', [], 'exclude path from search')], |
1417 ('X', 'exclude', [], 'exclude path from search')], |
1378 'hg locate [OPTION]... [PATTERN]...'), |
1418 'hg locate [OPTION]... [PATTERN]...'), |
1379 "^log|history": |
1419 "^log|history": |
1380 (log, |
1420 (log, |
1381 [('r', 'rev', [], 'revision'), |
1421 [('I', 'include', [], 'include path in search'), |
|
1422 ('X', 'exclude', [], 'exclude path from search'), |
|
1423 ('r', 'rev', [], 'revision'), |
1382 ('p', 'patch', None, 'show patch')], |
1424 ('p', 'patch', None, 'show patch')], |
1383 'hg log [-r REV1 [-r REV2]] [-p] [FILE]'), |
1425 'hg log [-r REV1 [-r REV2]] [-p] [FILE]'), |
1384 "manifest": (manifest, [], 'hg manifest [REV]'), |
1426 "manifest": (manifest, [], 'hg manifest [REV]'), |
1385 "outgoing|out": (outgoing, [], 'hg outgoing [DEST]'), |
1427 "outgoing|out": (outgoing, [], 'hg outgoing [DEST]'), |
1386 "parents": (parents, [], 'hg parents [REV]'), |
1428 "parents": (parents, [], 'hg parents [REV]'), |