# HG changeset patch # User Bryan O'Sullivan # Date 1123637078 28800 # Node ID c2e77581bc841e5bf978bc51e3323d1b49916a9e # Parent a82eae8404470ca198cbf650ca9b819d613bdecf# Parent 6390c377a9e617e01061d33f3729948d72b6f54f Merge with mpm. diff -r a82eae840447 -r c2e77581bc84 .hgignore --- a/.hgignore Sun Aug 07 12:43:11 2005 -0800 +++ b/.hgignore Tue Aug 09 17:24:38 2005 -0800 @@ -4,10 +4,11 @@ \.so$ \.pyc$ \.swp$ +\.prof$ ^tests/.*\.err$ ^build/ ^dist/ -^doc/.*\.[0-9]$ +^doc/.*\.[0-9](\.(x|ht)ml)?$ ^MANIFEST$ ^\.pc/ ^patches/ diff -r a82eae840447 -r c2e77581bc84 CONTRIBUTORS --- a/CONTRIBUTORS Sun Aug 07 12:43:11 2005 -0800 +++ b/CONTRIBUTORS Tue Aug 09 17:24:38 2005 -0800 @@ -19,10 +19,12 @@ Arun Sharma Kevin Smith Radoslaw Szkodzinski +Samuel Tardieu K Thananchayan Andrew Thompson Michael S. Tsirkin Rafael Villar Burke +Tristan Wibberley Mark Williamson If you are a contributor and don't see your name here, please let me know. diff -r a82eae840447 -r c2e77581bc84 TODO --- a/TODO Sun Aug 07 12:43:11 2005 -0800 +++ b/TODO Tue Aug 09 17:24:38 2005 -0800 @@ -26,17 +26,18 @@ - commands.py: number of args too much magic (e.g. in import_()) - optionally only show merges (two parents) - automatic pull fallback to old-http:// -- hg pull http://foo tries hostname - 'foo?cmd=changegroup&roots=0000000000000000000000000000000000000000' - pass options to ssh (debug/verbose/remote hg command etc.) - create a commented .hg/hgrc on init/clone - hg pull default in a subdir doesn't work, if it is a relative path - hg clone should store corrected relative paths, so moving a directory containing related repositories works again -- mention synonyms (co, ci, ...) in help -- show global options in help - if everyone knows 'hg clone': hg init [DIR] - if everyone knows 'hg update -m': remove -t +- hg revert does not forget added files, it probably should. +- hg pull should state if there are more heads than before. +- hg clone: locking the repository while hardlinking. +- hg clone: fall back to pull if hardlink not possible. +- "hg diff not_existing" should yield an error message. Web: - optionally only show merges (two parents) @@ -51,3 +52,5 @@ - link children in hgweb - allow verbose mode - hide trivial parent (like in show_changeset) +- default port for hg serve configurable in hgrc +- download tarball via web interface diff -r a82eae840447 -r c2e77581bc84 doc/hg.1.txt --- a/doc/hg.1.txt Sun Aug 07 12:43:11 2005 -0800 +++ b/doc/hg.1.txt Tue Aug 09 17:24:38 2005 -0800 @@ -346,6 +346,10 @@ options: + -m, --modified show only modified files + -a, --added show only added files + -r, --removed show only removed files + -u, --unknown show only unknown (not tracked) files -I, --include include names matching the given patterns -X, --exclude exclude names matching the given patterns diff -r a82eae840447 -r c2e77581bc84 mercurial/commands.py --- a/mercurial/commands.py Sun Aug 07 12:43:11 2005 -0800 +++ b/mercurial/commands.py Tue Aug 09 17:24:38 2005 -0800 @@ -273,7 +273,8 @@ def show_version(ui): """output version and copyright information""" - ui.write("Mercurial version %s\n" % version.get_version()) + ui.write("Mercurial Distributed SCM (version %s)\n" + % version.get_version()) ui.status( "\nCopyright (C) 2005 Matt Mackall \n" "This is free software; see the source for copying conditions. " @@ -283,56 +284,95 @@ def help_(ui, cmd=None): """show help for a given command or all commands""" - if cmd: - try: - i = find(cmd) - ui.write("%s\n\n" % i[2]) + if cmd and cmd != 'shortlist': + key, i = find(cmd) + # synopsis + ui.write("%s\n\n" % i[2]) + + # description + doc = i[0].__doc__ + if ui.quiet: + doc = doc.splitlines(0)[0] + ui.write("%s\n" % doc.rstrip()) + + # aliases + if not ui.quiet: + aliases = ', '.join(key.split('|')[1:]) + if aliases: + ui.write("\naliases: %s\n" % aliases) - if i[1]: - for s, l, d, c in i[1]: - opt = ' ' - if s: - opt = opt + '-' + s + ' ' - if l: - opt = opt + '--' + l + ' ' - if d: - opt = opt + '(' + str(d) + ')' - ui.write(opt, "\n") - if c: - ui.write(' %s\n' % c) - ui.write("\n") + # options + if not ui.quiet and i[1]: + ui.write("\noptions:\n\n") + for s, l, d, c in i[1]: + opt = ' ' + if s: + opt = opt + '-' + s + ' ' + if l: + opt = opt + '--' + l + ' ' + if d: + opt = opt + '(' + str(d) + ')' + ui.write(opt, "\n") + if c: + ui.write(' %s\n' % c) - ui.write(i[0].__doc__, "\n") - except UnknownCommand: - ui.warn("hg: unknown command %s\n" % cmd) - sys.exit(0) else: + # program name if ui.verbose: show_version(ui) - ui.write('\n') - if ui.verbose: - ui.write('hg commands:\n\n') else: - ui.write('basic hg commands (use "hg help -v" for more):\n\n') + ui.status("Mercurial Distributed SCM\n") + ui.status('\n') + + # list of commands + if cmd == "shortlist": + ui.status('basic commands (use "hg help" ' + 'for the full list or option "-v" for details):\n\n') + elif ui.verbose: + ui.status('list of commands:\n\n') + else: + ui.status('list of commands (use "hg help -v" ' + 'to show aliases and global options):\n\n') h = {} + cmds = {} for c, e in table.items(): f = c.split("|")[0] - if not ui.verbose and not f.startswith("^"): + if cmd == "shortlist" and not f.startswith("^"): continue + f = f.lstrip("^") if not ui.debugflag and f.startswith("debug"): continue - f = f.lstrip("^") d = "" if e[0].__doc__: d = e[0].__doc__.splitlines(0)[0].rstrip() h[f] = d + cmds[f]=c.lstrip("^") fns = h.keys() fns.sort() m = max(map(len, fns)) for f in fns: - ui.write(' %-*s %s\n' % (m, f, h[f])) + if ui.verbose: + commands = cmds[f].replace("|",", ") + ui.write(" %s:\n %s\n"%(commands,h[f])) + else: + ui.write(' %-*s %s\n' % (m, f, h[f])) + + # global options + if ui.verbose: + ui.write("\nglobal options:\n\n") + for s, l, d, c in globalopts: + opt = ' ' + if s: + opt = opt + '-' + s + ' ' + if l: + opt = opt + '--' + l + ' ' + if d: + opt = opt + '(' + str(d) + ')' + ui.write(opt, "\n") + if c: + ui.write(' %s\n' % c) # Commands start here, listed alphabetically @@ -698,6 +738,7 @@ hgpatch = False elif line == '# HG changeset patch': hgpatch = True + message = [] # We may have collected garbage else: message.append(line) @@ -1031,21 +1072,23 @@ M = modified A = added R = removed - ? = not tracked''' + ? = not tracked + ''' cwd = repo.getcwd() files, matchfn = matchpats(repo, cwd, pats, opts) (c, a, d, u) = [[pathto(cwd, x) for x in n] for n in repo.changes(files=files, match=matchfn)] - for f in c: - ui.write("M ", f, "\n") - for f in a: - ui.write("A ", f, "\n") - for f in d: - ui.write("R ", f, "\n") - for f in u: - ui.write("? ", f, "\n") + changetypes = [('modified', 'M', c), + ('added', 'A', a), + ('removed', 'R', d), + ('unknown', '?', u)] + + for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]] + or changetypes): + for f in changes: + ui.write("%s %s\n" % (char, f)) def tag(ui, repo, name, rev=None, **opts): """add a tag for the current tip or a given revision""" @@ -1138,14 +1181,16 @@ # Command options and aliases are listed here, alphabetically table = { - "^add": (add, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - "hg add [FILE]..."), - "addremove": (addremove, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - "hg addremove [OPTION]... [FILE]..."), + "^add": + (add, + [('I', 'include', [], 'include path in search'), + ('X', 'exclude', [], 'exclude path from search')], + "hg add [FILE]..."), + "addremove": + (addremove, + [('I', 'include', [], 'include path in search'), + ('X', 'exclude', [], 'exclude path from search')], + "hg addremove [OPTION]... [FILE]..."), "^annotate": (annotate, [('r', 'rev', '', 'revision'), @@ -1179,10 +1224,11 @@ "debugstate": (debugstate, [], 'debugstate'), "debugindex": (debugindex, [], 'debugindex FILE'), "debugindexdot": (debugindexdot, [], 'debugindexdot FILE'), - "debugwalk": (debugwalk, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'debugwalk [OPTIONS]... [FILE]...'), + "debugwalk": + (debugwalk, + [('I', 'include', [], 'include path in search'), + ('X', 'exclude', [], 'exclude path from search')], + 'debugwalk [OPTIONS]... [FILE]...'), "^diff": (diff, [('r', 'rev', [], 'revision'), @@ -1193,10 +1239,11 @@ (export, [('o', 'output', "", 'output to file')], "hg export [-o OUTFILE] REV..."), - "forget": (forget, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - "hg forget FILE..."), + "forget": + (forget, + [('I', 'include', [], 'include path in search'), + ('X', 'exclude', [], 'exclude path from search')], + "hg forget FILE..."), "heads": (heads, [], 'hg heads'), "help": (help_, [], 'hg help [COMMAND]'), "identify|id": (identify, [], 'hg identify'), @@ -1259,10 +1306,15 @@ ('t', 'templates', "", 'template map'), ('6', 'ipv6', None, 'use IPv6 in addition to IPv4')], "hg serve [OPTION]..."), - "^status": (status, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'hg status [FILE]...'), + "^status": + (status, + [('m', 'modified', None, 'show only modified files'), + ('a', 'added', None, 'show only added files'), + ('r', 'removed', None, 'show only removed files'), + ('u', 'unknown', None, 'show only unknown (not tracked) files'), + ('I', 'include', [], 'include path in search'), + ('X', 'exclude', [], 'exclude path from search')], + "hg status [FILE]..."), "tag": (tag, [('l', 'local', None, 'make the tag local'), @@ -1283,9 +1335,9 @@ "version": (show_version, [], 'hg version'), } -globalopts = [('v', 'verbose', None, 'verbose'), - ('', 'debug', None, 'debug'), - ('q', 'quiet', None, 'quiet'), +globalopts = [('v', 'verbose', None, 'verbose mode'), + ('', 'debug', None, 'debug mode'), + ('q', 'quiet', None, 'quiet mode'), ('', 'profile', None, 'profile'), ('R', 'repository', "", 'repository root directory'), ('', 'traceback', None, 'print traceback on exception'), @@ -1299,7 +1351,7 @@ def find(cmd): for e in table.keys(): if re.match("(%s)$" % e, cmd): - return table[e] + return e, table[e] raise UnknownCommand(cmd) @@ -1327,11 +1379,11 @@ if options["version"]: return ("version", show_version, [], options, cmdoptions) elif not args: - return ("help", help_, [], options, cmdoptions) + return ("help", help_, ["shortlist"], options, cmdoptions) else: cmd, args = args[0], args[1:] - i = find(cmd) + i = find(cmd)[1] # combine global options into local c = list(i[1]) @@ -1367,12 +1419,12 @@ help_(u, inst.args[0]) else: u.warn("hg: %s\n" % inst.args[1]) - help_(u) + help_(u, 'shortlist') sys.exit(-1) except UnknownCommand, inst: u = ui.ui() u.warn("hg: unknown command '%s'\n" % inst.args[0]) - help_(u) + help_(u, 'shortlist') sys.exit(1) if options["time"]: @@ -1455,5 +1507,8 @@ u.debug(inst, "\n") u.warn("%s: invalid arguments\n" % cmd) help_(u, cmd) + except UnknownCommand, inst: + u.warn("hg: unknown command '%s'\n" % inst.args[0]) + help_(u, 'shortlist') sys.exit(-1) diff -r a82eae840447 -r c2e77581bc84 mercurial/hg.py --- a/mercurial/hg.py Sun Aug 07 12:43:11 2005 -0800 +++ b/mercurial/hg.py Tue Aug 09 17:24:38 2005 -0800 @@ -22,16 +22,16 @@ # This avoids a collision between a file named foo and a dir named # foo.i or foo.d def encodedir(self, path): - path.replace(".hg/", ".hg.hg/") - path.replace(".i/", ".i.hg/") - path.replace(".d/", ".i.hg/") - return path + return (path + .replace(".hg/", ".hg.hg/") + .replace(".i/", ".i.hg/") + .replace(".d/", ".d.hg/")) def decodedir(self, path): - path.replace(".d.hg/", ".d/") - path.replace(".i.hg/", ".i/") - path.replace(".hg.hg/", ".hg/") - return path + return (path + .replace(".d.hg/", ".d/") + .replace(".i.hg/", ".i/") + .replace(".hg.hg/", ".hg/")) def read(self, node): t = self.revision(node) @@ -1784,8 +1784,11 @@ # Note: urllib2 takes proxy values from the environment and those will # take precedence for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]: - if os.environ.has_key(env): - del os.environ[env] + try: + if os.environ.has_key(env): + del os.environ[env] + except OSError: + pass proxy_handler = urllib2.BaseHandler() if host and not no_proxy: diff -r a82eae840447 -r c2e77581bc84 mercurial/hgweb.py --- a/mercurial/hgweb.py Sun Aug 07 12:43:11 2005 -0800 +++ b/mercurial/hgweb.py Tue Aug 09 17:24:38 2005 -0800 @@ -70,7 +70,7 @@ if m: yield tmpl[:m.start(0)] v = map.get(m.group(1), "") - v = callable(v) and v() or v + v = callable(v) and v(**map) or v fl = m.group(2) if fl: @@ -224,14 +224,8 @@ tn = None yield diffblock(mdiff.unidiff(to, date1, tn, date2, f), f, tn) - def header(self): - yield self.t("header") - - def footer(self): - yield self.t("footer") - def changelog(self, pos): - def changenav(): + def changenav(**map): def seq(factor = 1): yield 1 * factor yield 3 * factor @@ -254,7 +248,7 @@ yield self.t("naventry", label="tip") - def changelist(): + def changelist(**map): parity = (start - end) & 1 cl = self.repo.changelog l = [] # build a list in forward order for efficiency @@ -295,7 +289,7 @@ def search(self, query): - def changelist(): + def changelist(**map): cl = self.repo.changelog count = 0 qw = query.lower().split() @@ -361,7 +355,7 @@ files.append(self.t("filenodelink", filenode = hex(mf.get(f, nullid)), file = f)) - def diff(): + def diff(**map): yield self.diff(p1, n, None) yield self.t('changeset', @@ -382,7 +376,7 @@ fl = self.repo.file(f) count = fl.count() - def entries(): + def entries(**map): l = [] parity = (count - 1) & 1 @@ -457,7 +451,7 @@ t = float(cs[2].split(' ')[0]) mfn = cs[0] - def annotate(): + def annotate(**map): parity = 1 last = None for r, l in fl.annotate(n): @@ -527,7 +521,7 @@ short = os.path.basename(remain) files[short] = (f, n) - def filelist(): + def filelist(**map): parity = 0 fl = files.keys() fl.sort() @@ -563,7 +557,7 @@ i = self.repo.tagslist() i.reverse() - def entries(): + def entries(**map): parity = 0 for k,n in i: yield self.t("tagentry", @@ -583,7 +577,7 @@ cs = cl.read(n) mf = self.repo.manifest.read(cs[0]) - def diff(): + def diff(**map): yield self.diff(p1, n, file) yield self.t("filediff", @@ -600,6 +594,12 @@ # find tag, changeset, file def run(self): + def header(**map): + yield self.t("header", **map) + + def footer(**map): + yield self.t("footer", **map) + self.refresh() args = cgi.parse() @@ -618,11 +618,14 @@ self.t = templater(m, self.filters, {"url":url, "repo":self.reponame, - "header":self.header(), - "footer":self.footer(), + "header":header, + "footer":footer, }) - if not args.has_key('cmd') or args['cmd'][0] == 'changelog': + if not args.has_key('cmd'): + args['cmd'] = [self.t.cache['default'],] + + if args['cmd'][0] == 'changelog': c = self.repo.changelog.count() - 1 hi = c if args.has_key('rev'): diff -r a82eae840447 -r c2e77581bc84 mercurial/revlog.py --- a/mercurial/revlog.py Sun Aug 07 12:43:11 2005 -0800 +++ b/mercurial/revlog.py Tue Aug 09 17:24:38 2005 -0800 @@ -185,8 +185,8 @@ for r in range(p + 1, self.count()): n = self.node(r) for pn in self.parents(n): - if pn == p: - c.append(p) + if pn == node: + c.append(n) continue elif pn == nullid: continue diff -r a82eae840447 -r c2e77581bc84 mercurial/util.py diff -r a82eae840447 -r c2e77581bc84 templates/map --- a/templates/map Sun Aug 07 12:43:11 2005 -0800 +++ b/templates/map Tue Aug 09 17:24:38 2005 -0800 @@ -1,3 +1,4 @@ +default = "changelog" header = header.tmpl footer = footer.tmpl search = search.tmpl diff -r a82eae840447 -r c2e77581bc84 tests/test-help --- a/tests/test-help Sun Aug 07 12:43:11 2005 -0800 +++ b/tests/test-help Tue Aug 09 17:24:38 2005 -0800 @@ -1,11 +1,15 @@ #!/bin/sh +hg +hg -q hg help hg -q help hg add -h hg add --skjdfks hg help diff +hg help status +hg -q help status hg help foo -hg -q commands +hg skjdfks exit 0 diff -r a82eae840447 -r c2e77581bc84 tests/test-help.out --- a/tests/test-help.out Sun Aug 07 12:43:11 2005 -0800 +++ b/tests/test-help.out Tue Aug 09 17:24:38 2005 -0800 @@ -1,23 +1,7 @@ -+ hg help -basic hg commands (use "hg help -v" for more): ++ hg +Mercurial Distributed SCM - add add the specified files on the next commit - annotate show changeset information per file line - clone make a copy of an existing repository - commit commit the specified files or all outstanding changes - diff diff working directory (or selected files) - export dump the header and diffs for one or more changesets - init create a new repository in the current directory - log show the revision history of the repository or a single file - pull pull changes from the specified source - push push changes to the specified destination - remove remove the specified files on the next commit - revert revert modified files or dirs back to their unmodified states - serve export the repository via HTTP - status show changed files in the working directory - update update or merge working directory -+ hg -q help -basic hg commands (use "hg help -v" for more): +basic commands (use "hg help" for the full list or option "-v" for details): add add the specified files on the next commit annotate show changeset information per file line @@ -34,42 +18,170 @@ serve export the repository via HTTP status show changed files in the working directory update update or merge working directory ++ hg -q + add add the specified files on the next commit + annotate show changeset information per file line + clone make a copy of an existing repository + commit commit the specified files or all outstanding changes + diff diff working directory (or selected files) + export dump the header and diffs for one or more changesets + init create a new repository in the current directory + log show the revision history of the repository or a single file + pull pull changes from the specified source + push push changes to the specified destination + remove remove the specified files on the next commit + revert revert modified files or dirs back to their unmodified states + serve export the repository via HTTP + status show changed files in the working directory + update update or merge working directory ++ hg help +Mercurial Distributed SCM + +list of commands (use "hg help -v" to show aliases and global options): + + add add the specified files on the next commit + addremove add all new files, delete all missing files + annotate show changeset information per file line + cat output the latest or given revision of a file + clone make a copy of an existing repository + commit commit the specified files or all outstanding changes + copy mark a file as copied or renamed for the next commit + diff diff working directory (or selected files) + export dump the header and diffs for one or more changesets + forget don't add the specified files on the next commit + heads show current repository heads + help show help for a given command or all commands + identify print information about the working copy + import import an ordered set of patches + init create a new repository in the current directory + locate locate files matching specific patterns + log show the revision history of the repository or a single file + manifest output the latest or given revision of the project manifest + parents show the parents of the working dir or revision + paths show path or list of available paths + pull pull changes from the specified source + push push changes to the specified destination + rawcommit raw commit interface + recover roll back an interrupted transaction + remove remove the specified files on the next commit + revert revert modified files or dirs back to their unmodified states + root print the root (top) of the current working dir + serve export the repository via HTTP + status show changed files in the working directory + tag add a tag for the current tip or a given revision + tags list repository tags + tip show the tip revision + undo undo the last commit or pull + update update or merge working directory + verify verify the integrity of the repository + version output version and copyright information ++ hg -q help + add add the specified files on the next commit + addremove add all new files, delete all missing files + annotate show changeset information per file line + cat output the latest or given revision of a file + clone make a copy of an existing repository + commit commit the specified files or all outstanding changes + copy mark a file as copied or renamed for the next commit + diff diff working directory (or selected files) + export dump the header and diffs for one or more changesets + forget don't add the specified files on the next commit + heads show current repository heads + help show help for a given command or all commands + identify print information about the working copy + import import an ordered set of patches + init create a new repository in the current directory + locate locate files matching specific patterns + log show the revision history of the repository or a single file + manifest output the latest or given revision of the project manifest + parents show the parents of the working dir or revision + paths show path or list of available paths + pull pull changes from the specified source + push push changes to the specified destination + rawcommit raw commit interface + recover roll back an interrupted transaction + remove remove the specified files on the next commit + revert revert modified files or dirs back to their unmodified states + root print the root (top) of the current working dir + serve export the repository via HTTP + status show changed files in the working directory + tag add a tag for the current tip or a given revision + tags list repository tags + tip show the tip revision + undo undo the last commit or pull + update update or merge working directory + verify verify the integrity of the repository + version output version and copyright information + hg add -h hg add: option -h not recognized hg add [FILE]... +add the specified files on the next commit + +options: + -I --include include path in search -X --exclude exclude path from search - -add the specified files on the next commit + hg add --skjdfks hg add: option --skjdfks not recognized hg add [FILE]... +add the specified files on the next commit + +options: + -I --include include path in search -X --exclude exclude path from search - -add the specified files on the next commit + hg help diff hg diff [-r REV1 [-r REV2]] [FILE]... +diff working directory (or selected files) + +options: + -r --rev revision -I --include include path in search -X --exclude exclude path from search ++ hg help status +hg status [FILE]... -diff working directory (or selected files) +show changed files in the working directory + + M = modified + A = added + R = removed + ? = not tracked + +options: + + -m --modified + show only modified files + -a --added + show only added files + -r --removed + show only removed files + -u --unknown + show only unknown (not tracked) files + -I --include + include path in search + -X --exclude + exclude path from search ++ hg -q help status +hg status [FILE]... + +show changed files in the working directory + hg help foo -hg: unknown command foo -+ hg -q commands -hg: unknown command 'commands' -basic hg commands (use "hg help -v" for more): +hg: unknown command 'foo' +Mercurial Distributed SCM + +basic commands (use "hg help" for the full list or option "-v" for details): add add the specified files on the next commit annotate show changeset information per file line @@ -86,3 +198,24 @@ serve export the repository via HTTP status show changed files in the working directory update update or merge working directory ++ hg skjdfks +hg: unknown command 'skjdfks' +Mercurial Distributed SCM + +basic commands (use "hg help" for the full list or option "-v" for details): + + add add the specified files on the next commit + annotate show changeset information per file line + clone make a copy of an existing repository + commit commit the specified files or all outstanding changes + diff diff working directory (or selected files) + export dump the header and diffs for one or more changesets + init create a new repository in the current directory + log show the revision history of the repository or a single file + pull pull changes from the specified source + push push changes to the specified destination + remove remove the specified files on the next commit + revert revert modified files or dirs back to their unmodified states + serve export the repository via HTTP + status show changed files in the working directory + update update or merge working directory