Mercurial > hg
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)) |