contrib/hgit
changeset 349 b2293093b89e
parent 280 a69c3b2957d1
parent 334 290574209284
child 350 b4e0e20646bb
equal deleted inserted replaced
348:442eb02cf870 349:b2293093b89e
    10 import time, sys, signal
    10 import time, sys, signal
    11 from mercurial import hg, mdiff, fancyopts, commands, ui
    11 from mercurial import hg, mdiff, fancyopts, commands, ui
    12     
    12     
    13 def difftree(args, repo):
    13 def difftree(args, repo):
    14     def __difftree(repo, files = None, node1 = None, node2 = None):
    14     def __difftree(repo, files = None, node1 = None, node2 = None):
    15 	def date(c):
    15         def date(c):
    16 	    return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
    16             return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
    17 
    17 
    18 	if node2:
    18         if node2:
    19 	    change = repo.changelog.read(node2)
    19             change = repo.changelog.read(node2)
    20 	    mmap2 = repo.manifest.read(change[0])
    20             mmap2 = repo.manifest.read(change[0])
    21 	    (c, a, d) = repo.diffrevs(node1, node2)
    21             (c, a, d) = repo.diffrevs(node1, node2)
    22 	    def read(f): return repo.file(f).read(mmap2[f])
    22             def read(f): return repo.file(f).read(mmap2[f])
    23 	    date2 = date(change)
    23             date2 = date(change)
    24 	else:
    24         else:
    25 	    date2 = time.asctime()
    25             date2 = time.asctime()
    26 	    (c, a, d, u) = repo.diffdir(repo.root, node1)
    26             (c, a, d, u) = repo.diffdir(repo.root, node1)
    27 	    if not node1:
    27             if not node1:
    28 		node1 = repo.dirstate.parents()[0]
    28                 node1 = repo.dirstate.parents()[0]
    29 	    def read(f): return file(os.path.join(repo.root, f)).read()
    29             def read(f): return file(os.path.join(repo.root, f)).read()
    30 
    30 
    31 	change = repo.changelog.read(node1)
    31         change = repo.changelog.read(node1)
    32 	mmap = repo.manifest.read(change[0])
    32         mmap = repo.manifest.read(change[0])
    33 	date1 = date(change)
    33         date1 = date(change)
    34 	empty = "0" * 40;
    34         empty = "0" * 40;
    35 
    35 
    36 	if files:
    36         if files:
    37 	    c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
    37             c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
    38 
    38 
    39 	for f in c:
    39         for f in c:
    40 	    # TODO get file permissions
    40             # TODO get file permissions
    41 	    print ":100664 100664 %s %s %s %s" % (hg.hex(mmap[f]), 
    41             print ":100664 100664 %s %s %s %s" % (hg.hex(mmap[f]), 
    42 	                                              hg.hex(mmap2[f]), f, f)
    42                                                       hg.hex(mmap2[f]), f, f)
    43 	for f in a:
    43         for f in a:
    44 	    print ":000000 100664 %s %s %s %s" % (empty, hg.hex(mmap2[f]), f, f)
    44             print ":000000 100664 %s %s %s %s" % (empty, hg.hex(mmap2[f]), f, f)
    45 	for f in d:
    45         for f in d:
    46 	    print ":100664 000000 %s %s %s %s" % (hg.hex(mmap[f]), empty, f, f)
    46             print ":100664 000000 %s %s %s %s" % (hg.hex(mmap[f]), empty, f, f)
    47     ##
    47     ##
    48 
    48 
    49     revs = []
    49     revs = []
    50     if args:
    50     if args:
    51 	doptions = {}
    51         doptions = {}
    52 	opts = [('p', 'patch', None, 'patch'),
    52         opts = [('p', 'patch', None, 'patch'),
    53 		('r', 'recursive', None, 'recursive')]
    53                 ('r', 'recursive', None, 'recursive')]
    54 	args = fancyopts.fancyopts(args, opts, doptions,
    54         args = fancyopts.fancyopts(args, opts, doptions,
    55                                    'hg diff-tree [options] sha1 sha1')
    55                                    'hg diff-tree [options] sha1 sha1')
    56 
    56 
    57     if len(args) < 2:
    57     if len(args) < 2:
    58 	help()
    58         help()
    59         sys.exit(1)
    59         sys.exit(1)
    60     revs.append(repo.lookup(args[0]))
    60     revs.append(repo.lookup(args[0]))
    61     revs.append(repo.lookup(args[1]))
    61     revs.append(repo.lookup(args[1]))
    62     args = args[2:]
    62     args = args[2:]
    63     if doptions['patch']:
    63     if doptions['patch']:
    64 	commands.dodiff(repo, args, *revs)
    64         commands.dodiff(repo, args, *revs)
    65     else:
    65     else:
    66 	__difftree(repo, args, *revs)
    66         __difftree(repo, args, *revs)
    67 
    67 
    68 def catcommit(repo, n, prefix):
    68 def catcommit(repo, n, prefix):
    69     nlprefix = '\n' + prefix;
    69     nlprefix = '\n' + prefix;
    70     changes = repo.changelog.read(n)
    70     changes = repo.changelog.read(n)
    71     (p1, p2) = repo.changelog.parents(n)
    71     (p1, p2) = repo.changelog.parents(n)
    78     date = int(float(date_ar[0]))
    78     date = int(float(date_ar[0]))
    79     print "%sauthor <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
    79     print "%sauthor <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
    80     print "%scommitter <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
    80     print "%scommitter <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
    81     print prefix
    81     print prefix
    82     if prefix != "":
    82     if prefix != "":
    83 	print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
    83         print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
    84     else:
    84     else:
    85 	print changes[4]
    85         print changes[4]
    86 
    86 
    87 def catfile(args, ui, repo):
    87 def catfile(args, ui, repo):
    88     doptions = {}
    88     doptions = {}
    89     opts = [('s', 'stdin', None, 'stdin')]
    89     opts = [('s', 'stdin', None, 'stdin')]
    90     args = fancyopts.fancyopts(args, opts, doptions,
    90     args = fancyopts.fancyopts(args, opts, doptions,
    91 			       'hg cat-file type sha1')
    91                                'hg cat-file type sha1')
    92 
    92 
    93     # in stdin mode, every line except the commit is prefixed with two
    93     # in stdin mode, every line except the commit is prefixed with two
    94     # spaces.  This way the our caller can find the commit without magic
    94     # spaces.  This way the our caller can find the commit without magic
    95     # strings
    95     # strings
    96     #
    96     #
    97     prefix = ""
    97     prefix = ""
    98     if doptions['stdin']:
    98     if doptions['stdin']:
    99 	try:
    99         try:
   100 	    (type, r) = raw_input().split(' ');
   100             (type, r) = raw_input().split(' ');
   101 	    prefix = "  "
   101             prefix = "  "
   102 	except EOFError:
   102         except EOFError:
   103 	    return
   103             return
   104 
   104 
   105     else:
   105     else:
   106 	if len(args) < 2:
   106         if len(args) < 2:
   107 	    help()
   107             help()
   108 	    sys.exit(1)
   108             sys.exit(1)
   109         type = args[0]
   109         type = args[0]
   110 	r = args[1]
   110         r = args[1]
   111 
   111 
   112     while r:
   112     while r:
   113 	if type != "commit":
   113         if type != "commit":
   114 	    sys.stderr.write("aborting hg cat-file only understands commits\n")
   114             sys.stderr.write("aborting hg cat-file only understands commits\n")
   115 	    sys.exit(1);
   115             sys.exit(1);
   116 	n = repo.changelog.lookup(r)
   116         n = repo.changelog.lookup(r)
   117 	catcommit(repo, n, prefix)
   117         catcommit(repo, n, prefix)
   118 	if doptions['stdin']:
   118         if doptions['stdin']:
   119 	    try:
   119             try:
   120 		(type, r) = raw_input().split(' ');
   120                 (type, r) = raw_input().split(' ');
   121 	    except EOFError:
   121             except EOFError:
   122 		break
   122                 break
   123 	else:
   123         else:
   124 	    break
   124             break
   125 
   125 
   126 # git rev-tree is a confusing thing.  You can supply a number of
   126 # git rev-tree is a confusing thing.  You can supply a number of
   127 # commit sha1s on the command line, and it walks the commit history
   127 # commit sha1s on the command line, and it walks the commit history
   128 # telling you which commits are reachable from the supplied ones via
   128 # telling you which commits are reachable from the supplied ones via
   129 # a bitmask based on arg position.
   129 # a bitmask based on arg position.
   130 # you can specify a commit to stop at by starting the sha1 with ^
   130 # you can specify a commit to stop at by starting the sha1 with ^
   131 def revtree(args, repo):
   131 def revtree(args, repo):
   132     # calculate and return the reachability bitmask for sha
   132     # calculate and return the reachability bitmask for sha
   133     def is_reachable(ar, reachable, sha):
   133     def is_reachable(ar, reachable, sha):
   134 	if len(ar) == 0:
   134         if len(ar) == 0:
   135 	    return 1
   135             return 1
   136 	mask = 0
   136         mask = 0
   137 	for i in range(len(ar)):
   137         for i in range(len(ar)):
   138 	    if sha in reachable[i]:
   138             if sha in reachable[i]:
   139 	        mask |= 1 << i
   139                 mask |= 1 << i
   140 
   140 
   141 	return mask
   141         return mask
   142 
   142 
   143     reachable = []
   143     reachable = []
   144     stop_sha1 = []
   144     stop_sha1 = []
   145     want_sha1 = []
   145     want_sha1 = []
   146 
   146 
   147     # figure out which commits they are asking for and which ones they
   147     # figure out which commits they are asking for and which ones they
   148     # want us to stop on
   148     # want us to stop on
   149     for i in range(len(args)):
   149     for i in range(len(args)):
   150         if args[i].count('^'):
   150         if args[i].count('^'):
   151 	    s = args[i].split('^')[1]
   151             s = args[i].split('^')[1]
   152 	    stop_sha1.append(repo.changelog.lookup(s))
   152             stop_sha1.append(repo.changelog.lookup(s))
   153 	    want_sha1.append(s)
   153             want_sha1.append(s)
   154 	elif args[i] != 'HEAD':
   154         elif args[i] != 'HEAD':
   155 	    want_sha1.append(args[i])
   155             want_sha1.append(args[i])
   156     # calculate the graph for the supplied commits
   156     # calculate the graph for the supplied commits
   157     for i in range(len(want_sha1)):
   157     for i in range(len(want_sha1)):
   158 	reachable.append({});
   158         reachable.append({});
   159 	n = repo.changelog.lookup(want_sha1[i]);
   159         n = repo.changelog.lookup(want_sha1[i]);
   160 	visit = [n];
   160         visit = [n];
   161 	reachable[i][n] = 1
   161         reachable[i][n] = 1
   162 	while visit:
   162         while visit:
   163 	    n = visit.pop(0)
   163             n = visit.pop(0)
   164 	    if n in stop_sha1:
   164             if n in stop_sha1:
   165 		break
   165                 break
   166 	    for p in repo.changelog.parents(n):
   166             for p in repo.changelog.parents(n):
   167 		if p not in reachable[i]:
   167                 if p not in reachable[i]:
   168 		    reachable[i][p] = 1
   168                     reachable[i][p] = 1
   169 		    visit.append(p)
   169                     visit.append(p)
   170 		if p in stop_sha1:
   170                 if p in stop_sha1:
   171 		    break
   171                     break
   172     # walk the repository looking for commits that are in our
   172     # walk the repository looking for commits that are in our
   173     # reachability graph
   173     # reachability graph
   174     for i in range(repo.changelog.count()):
   174     for i in range(repo.changelog.count()):
   175 	n = repo.changelog.node(i)
   175         n = repo.changelog.node(i)
   176 	mask = is_reachable(want_sha1, reachable, n)
   176         mask = is_reachable(want_sha1, reachable, n)
   177 	if mask:
   177         if mask:
   178 	    changes = repo.changelog.read(n)
   178             changes = repo.changelog.read(n)
   179 	    (p1, p2) = repo.changelog.parents(n)
   179             (p1, p2) = repo.changelog.parents(n)
   180 	    (h, h1, h2) = map(hg.hex, (n, p1, p2))
   180             (h, h1, h2) = map(hg.hex, (n, p1, p2))
   181 	    (i1, i2) = map(repo.changelog.rev, (p1, p2))
   181             (i1, i2) = map(repo.changelog.rev, (p1, p2))
   182 
   182 
   183 	    date = changes[2].split(' ')[0]
   183             date = changes[2].split(' ')[0]
   184 	    print "%s %s:%s" % (date, h, mask),
   184             print "%s %s:%s" % (date, h, mask),
   185 	    mask = is_reachable(want_sha1, reachable, p1)
   185             mask = is_reachable(want_sha1, reachable, p1)
   186 	    if i1 != -1 and mask > 0:
   186             if i1 != -1 and mask > 0:
   187 		print "%s:%s " % (h1, mask),
   187                 print "%s:%s " % (h1, mask),
   188 	    mask = is_reachable(want_sha1, reachable, p2)
   188             mask = is_reachable(want_sha1, reachable, p2)
   189 	    if i2 != -1 and mask > 0:
   189             if i2 != -1 and mask > 0:
   190 		print "%s:%s " % (h2, mask),
   190                 print "%s:%s " % (h2, mask),
   191 	    print ""
   191             print ""
   192 
   192 
   193 # git rev-list tries to order things by date, and has the ability to stop
   193 # git rev-list tries to order things by date, and has the ability to stop
   194 # at a given commit without walking the whole repo.  TODO add the stop
   194 # at a given commit without walking the whole repo.  TODO add the stop
   195 # parameter
   195 # parameter
   196 def revlist(args, repo):
   196 def revlist(args, repo):
   197     doptions = {}
   197     doptions = {}
   198     opts = [('c', 'commit', None, 'commit')]
   198     opts = [('c', 'commit', None, 'commit')]
   199     args = fancyopts.fancyopts(args, opts, doptions,
   199     args = fancyopts.fancyopts(args, opts, doptions,
   200 			       'hg rev-list')
   200                                'hg rev-list')
   201     for i in range(repo.changelog.count()):
   201     for i in range(repo.changelog.count()):
   202 	n = repo.changelog.node(i)
   202         n = repo.changelog.node(i)
   203 	print hg.hex(n)
   203         print hg.hex(n)
   204 	if doptions['commit']:
   204         if doptions['commit']:
   205 	    catcommit(repo, n, '  ')
   205             catcommit(repo, n, '  ')
   206 
   206 
   207 def catchterm(*args):
   207 def catchterm(*args):
   208     raise SignalInterrupt
   208     raise SignalInterrupt
   209 
   209 
   210 def help():
   210 def help():