mercurial/commands.py
changeset 580 353a2ce50423
parent 577 5291a16324c0
child 582 df8a5a0098d4
equal deleted inserted replaced
579:ffeb2c3a1966 580:353a2ce50423
    31         p = os.getcwd()[len(repo.root) + 1: ]
    31         p = os.getcwd()[len(repo.root) + 1: ]
    32         return [ util.pconvert(os.path.normpath(os.path.join(p, x)))
    32         return [ util.pconvert(os.path.normpath(os.path.join(p, x)))
    33                  for x in args ]
    33                  for x in args ]
    34     return args
    34     return args
    35 
    35 
    36 def dodiff(ui, repo, files = None, node1 = None, node2 = None):
    36 revrangesep = ':'
       
    37 
       
    38 def revrange(ui, repo, revs = [], revlog = None):
       
    39     if revlog is None:
       
    40         revlog = repo.changelog
       
    41     revcount = revlog.count()
       
    42     def fix(val, defval):
       
    43         if not val: return defval
       
    44         try:
       
    45             num = int(val)
       
    46             if str(num) != val: raise ValueError
       
    47             if num < 0: num += revcount
       
    48             if not (0 <= num < revcount):
       
    49                 raise ValueError
       
    50         except ValueError:
       
    51             try:
       
    52                 num = repo.changelog.rev(repo.lookup(val))
       
    53             except KeyError:
       
    54                 try:
       
    55                     num = revlog.rev(revlog.lookup(val))
       
    56                 except KeyError:
       
    57                     ui.warn('abort: invalid revision identifier %s\n' % val)
       
    58                     sys.exit(1)
       
    59         return num
       
    60     for spec in revs:
       
    61         if spec.find(revrangesep) >= 0:
       
    62             start, end = spec.split(revrangesep, 1)
       
    63             start = fix(start, 0)
       
    64             end = fix(end, revcount - 1)
       
    65             if end > start:
       
    66                 end += 1
       
    67                 step = 1
       
    68             else:
       
    69                 end -= 1
       
    70                 step = -1
       
    71             for rev in xrange(start, end, step):
       
    72                 yield str(rev)
       
    73         else:
       
    74             yield spec
       
    75 
       
    76 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None):
    37     def date(c):
    77     def date(c):
    38         return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
    78         return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
    39 
    79 
    40     (c, a, d, u) = repo.changes(node1, node2, files)
    80     (c, a, d, u) = repo.changes(node1, node2, files)
    41     if files:
    81     if files:
    68     for f in c:
   108     for f in c:
    69         to = None
   109         to = None
    70         if f in mmap:
   110         if f in mmap:
    71             to = repo.file(f).read(mmap[f])
   111             to = repo.file(f).read(mmap[f])
    72         tn = read(f)
   112         tn = read(f)
    73         sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
   113         fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
    74     for f in a:
   114     for f in a:
    75         to = None
   115         to = None
    76         tn = read(f)
   116         tn = read(f)
    77         sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
   117         fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
    78     for f in d:
   118     for f in d:
    79         to = repo.file(f).read(mmap[f])
   119         to = repo.file(f).read(mmap[f])
    80         tn = None
   120         tn = None
    81         sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
   121         fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
    82 
   122 
    83 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
   123 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
    84     """show a single changeset or file revision"""
   124     """show a single changeset or file revision"""
    85     changelog = repo.changelog
   125     changelog = repo.changelog
    86     if filelog:
   126     if filelog:
   419     if files:
   459     if files:
   420         files = relpath(repo, files)
   460         files = relpath(repo, files)
   421     else:
   461     else:
   422         files = relpath(repo, [""])
   462         files = relpath(repo, [""])
   423 
   463 
   424     dodiff(ui, repo, files, *revs)
   464     dodiff(sys.stdout, ui, repo, files, *revs)
   425 
   465 
   426 def export(ui, repo, changeset):
   466 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
   427     """dump the changeset header and diffs for a revision"""
       
   428     node = repo.lookup(changeset)
   467     node = repo.lookup(changeset)
   429     prev, other = repo.changelog.parents(node)
   468     prev, other = repo.changelog.parents(node)
   430     change = repo.changelog.read(node)
   469     change = repo.changelog.read(node)
   431     print "# HG changeset patch"
   470 
   432     print "# User %s" % change[1]
   471     def expand(name):
   433     print "# Node ID %s" % hg.hex(node)
   472         expansions = {
   434     print "# Parent  %s" % hg.hex(prev)
   473             '%': lambda: '%',
   435     print
   474             'H': lambda: hg.hex(node),
       
   475             'N': lambda: str(total),
       
   476             'R': lambda: str(repo.changelog.rev(node)),
       
   477             'b': lambda: os.path.basename(repo.root),
       
   478             'h': lambda: hg.short(node),
       
   479             'n': lambda: str(seqno).zfill(len(str(total))),
       
   480             'r': lambda: str(repo.changelog.rev(node)).zfill(revwidth),
       
   481             }
       
   482         newname = []
       
   483         namelen = len(name)
       
   484         i = 0
       
   485         while i < namelen:
       
   486             c = name[i]
       
   487             if c == '%':
       
   488                 i += 1
       
   489                 c = name[i]
       
   490                 c = expansions[c]()
       
   491             newname.append(c)
       
   492             i += 1
       
   493         return ''.join(newname)
       
   494 
       
   495     if opts['output'] and opts['output'] != '-':
       
   496         try:
       
   497             fp = open(expand(opts['output']), 'w')
       
   498         except KeyError, inst:
       
   499             ui.warn("error: invalid format spec '%%%s' in output file name\n" %
       
   500                     inst.args[0])
       
   501             sys.exit(1)
       
   502     else:
       
   503         fp = sys.stdout
       
   504 
       
   505     print >> fp, "# HG changeset patch"
       
   506     print >> fp, "# User %s" % change[1]
       
   507     print >> fp, "# Node ID %s" % hg.hex(node)
       
   508     print >> fp, "# Parent  %s" % hg.hex(prev)
       
   509     print >> fp
   436     if other != hg.nullid:
   510     if other != hg.nullid:
   437         print "# Parent  %s" % hg.hex(other)
   511         print >> fp, "# Parent  %s" % hg.hex(other)
   438     print change[4].rstrip()
   512     print >> fp, change[4].rstrip()
   439     print
   513     print >> fp
   440 
   514 
   441     dodiff(ui, repo, None, prev, node)
   515     dodiff(fp, ui, repo, None, prev, node)
       
   516 
       
   517 def export(ui, repo, *changesets, **opts):
       
   518     """dump the header and diffs for one or more changesets"""
       
   519     seqno = 0
       
   520     revs = list(revrange(ui, repo, changesets))
       
   521     total = len(revs)
       
   522     revwidth = max(len(revs[0]), len(revs[-1]))
       
   523     for cset in revs:
       
   524         seqno += 1
       
   525         doexport(ui, repo, cset, seqno, total, revwidth, opts)
   442 
   526 
   443 def forget(ui, repo, file, *files):
   527 def forget(ui, repo, file, *files):
   444     """don't add the specified files on the next commit"""
   528     """don't add the specified files on the next commit"""
   445     repo.forget(relpath(repo, (file,) + files))
   529     repo.forget(relpath(repo, (file,) + files))
   446 
   530 
   583     cg = other.changegroup(fetch)
   667     cg = other.changegroup(fetch)
   584     r = repo.addchangegroup(cg)
   668     r = repo.addchangegroup(cg)
   585     if cg and not r:
   669     if cg and not r:
   586         if opts['update']:
   670         if opts['update']:
   587             return update(ui, repo)
   671             return update(ui, repo)
   588 	else:
   672         else:
   589             ui.status("(run 'hg update' to get a working copy)\n")
   673             ui.status("(run 'hg update' to get a working copy)\n")
   590 
   674 
   591     return r
   675     return r
   592 
   676 
   593 def push(ui, repo, dest="default-push"):
   677 def push(ui, repo, dest="default-push"):
   677 
   761 
   678 def tag(ui, repo, name, rev = None, **opts):
   762 def tag(ui, repo, name, rev = None, **opts):
   679     """add a tag for the current tip or a given revision"""
   763     """add a tag for the current tip or a given revision"""
   680 
   764 
   681     if name == "tip":
   765     if name == "tip":
   682 	ui.warn("abort: 'tip' is a reserved name!\n")
   766         ui.warn("abort: 'tip' is a reserved name!\n")
   683 	return -1
   767         return -1
       
   768     if name.find(revrangesep) >= 0:
       
   769         ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep)
       
   770         return -1
   684 
   771 
   685     (c, a, d, u) = repo.changes(None, None)
   772     (c, a, d, u) = repo.changes(None, None)
   686     for x in (c, a, d, u):
   773     for x in (c, a, d, u):
   687 	if ".hgtags" in x:
   774         if ".hgtags" in x:
   688 	    ui.warn("abort: working copy of .hgtags is changed!\n")
   775             ui.warn("abort: working copy of .hgtags is changed!\n")
   689             ui.status("(please commit .hgtags manually)\n")
   776             ui.status("(please commit .hgtags manually)\n")
   690 	    return -1
   777             return -1
   691 
   778 
   692     if rev:
   779     if rev:
   693         r = hg.hex(repo.lookup(rev))
   780         r = hg.hex(repo.lookup(rev))
   694     else:
   781     else:
   695         r = hg.hex(repo.changelog.tip())
   782         r = hg.hex(repo.changelog.tip())
   771     "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
   858     "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
   772     "debugindex": (debugindex, [], 'debugindex <file>'),
   859     "debugindex": (debugindex, [], 'debugindex <file>'),
   773     "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
   860     "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
   774     "diff": (diff, [('r', 'rev', [], 'revision')],
   861     "diff": (diff, [('r', 'rev', [], 'revision')],
   775              'hg diff [-r A] [-r B] [files]'),
   862              'hg diff [-r A] [-r B] [files]'),
   776     "export": (export, [], "hg export <changeset>"),
   863     "export": (export, [('o', 'output', "", 'output to file')],
       
   864                "hg export [-o file] <changeset> ..."),
   777     "forget": (forget, [], "hg forget [files]"),
   865     "forget": (forget, [], "hg forget [files]"),
   778     "heads": (heads, [], 'hg heads'),
   866     "heads": (heads, [], 'hg heads'),
   779     "help": (help, [], 'hg help [command]'),
   867     "help": (help, [], 'hg help [command]'),
   780     "identify|id": (identify, [], 'hg identify'),
   868     "identify|id": (identify, [], 'hg identify'),
   781     "import|patch": (import_,
   869     "import|patch": (import_,
   788                     'hg log [-r A] [-r B] [file]'),
   876                     'hg log [-r A] [-r B] [file]'),
   789     "manifest": (manifest, [], 'hg manifest [rev]'),
   877     "manifest": (manifest, [], 'hg manifest [rev]'),
   790     "parents": (parents, [], 'hg parents [node]'),
   878     "parents": (parents, [], 'hg parents [node]'),
   791     "pull": (pull,
   879     "pull": (pull,
   792                   [('u', 'update', None, 'update working directory')],
   880                   [('u', 'update', None, 'update working directory')],
   793 		  'hg pull [options] [source]'),
   881                   'hg pull [options] [source]'),
   794     "push": (push, [], 'hg push <destination>'),
   882     "push": (push, [], 'hg push <destination>'),
   795     "rawcommit": (rawcommit,
   883     "rawcommit": (rawcommit,
   796                   [('p', 'parent', [], 'parent'),
   884                   [('p', 'parent', [], 'parent'),
   797                    ('d', 'date', "", 'data'),
   885                    ('d', 'date', "", 'data'),
   798                    ('u', 'user', "", 'user'),
   886                    ('u', 'user', "", 'user'),
   941         u.debug(inst, "\n")
  1029         u.debug(inst, "\n")
   942         u.warn("%s: invalid arguments\n" % i[0].__name__)
  1030         u.warn("%s: invalid arguments\n" % i[0].__name__)
   943         help(u, cmd)
  1031         help(u, cmd)
   944 
  1032 
   945     sys.exit(-1)
  1033     sys.exit(-1)
   946