comparison mercurial/filelog.py @ 1089:142b5d5ec9cc

Break apart hg.py - move the various parts of hg.py into their own files - create node.py to store node manipulation functions
author mpm@selenic.com
date Sat, 27 Aug 2005 14:21:25 -0700
parents mercurial/hg.py@05dc7aba22eb
children 0cdd73b0767c
comparison
equal deleted inserted replaced
1088:39b916b1d8e4 1089:142b5d5ec9cc
1 # filelog.py - file history class for mercurial
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
7
8 import os
9 from revlog import *
10 from demandload import *
11 demandload(globals(), "bdiff")
12
13 class filelog(revlog):
14 def __init__(self, opener, path):
15 revlog.__init__(self, opener,
16 os.path.join("data", self.encodedir(path + ".i")),
17 os.path.join("data", self.encodedir(path + ".d")))
18
19 # This avoids a collision between a file named foo and a dir named
20 # foo.i or foo.d
21 def encodedir(self, path):
22 return (path
23 .replace(".hg/", ".hg.hg/")
24 .replace(".i/", ".i.hg/")
25 .replace(".d/", ".d.hg/"))
26
27 def decodedir(self, path):
28 return (path
29 .replace(".d.hg/", ".d/")
30 .replace(".i.hg/", ".i/")
31 .replace(".hg.hg/", ".hg/"))
32
33 def read(self, node):
34 t = self.revision(node)
35 if not t.startswith('\1\n'):
36 return t
37 s = t.find('\1\n', 2)
38 return t[s+2:]
39
40 def readmeta(self, node):
41 t = self.revision(node)
42 if not t.startswith('\1\n'):
43 return t
44 s = t.find('\1\n', 2)
45 mt = t[2:s]
46 for l in mt.splitlines():
47 k, v = l.split(": ", 1)
48 m[k] = v
49 return m
50
51 def add(self, text, meta, transaction, link, p1=None, p2=None):
52 if meta or text.startswith('\1\n'):
53 mt = ""
54 if meta:
55 mt = [ "%s: %s\n" % (k, v) for k,v in meta.items() ]
56 text = "\1\n" + "".join(mt) + "\1\n" + text
57 return self.addrevision(text, transaction, link, p1, p2)
58
59 def annotate(self, node):
60
61 def decorate(text, rev):
62 return ([rev] * len(text.splitlines()), text)
63
64 def pair(parent, child):
65 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
66 child[0][b1:b2] = parent[0][a1:a2]
67 return child
68
69 # find all ancestors
70 needed = {node:1}
71 visit = [node]
72 while visit:
73 n = visit.pop(0)
74 for p in self.parents(n):
75 if p not in needed:
76 needed[p] = 1
77 visit.append(p)
78 else:
79 # count how many times we'll use this
80 needed[p] += 1
81
82 # sort by revision which is a topological order
83 visit = [ (self.rev(n), n) for n in needed.keys() ]
84 visit.sort()
85 hist = {}
86
87 for r,n in visit:
88 curr = decorate(self.read(n), self.linkrev(n))
89 for p in self.parents(n):
90 if p != nullid:
91 curr = pair(hist[p], curr)
92 # trim the history of unneeded revs
93 needed[p] -= 1
94 if not needed[p]:
95 del hist[p]
96 hist[n] = curr
97
98 return zip(hist[n][0], hist[n][1].splitlines(1))