##// END OF EJS Templates
minor optimization: save some string trash
twaldmann@thinkmo.de -
r1540:8ca9f5b1 default
parent child Browse files
Show More
@@ -1,107 +1,107
1 # filelog.py - file history class for mercurial
1 # filelog.py - file history class for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os
8 import os
9 from revlog import *
9 from revlog import *
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "bdiff")
11 demandload(globals(), "bdiff")
12
12
13 class filelog(revlog):
13 class filelog(revlog):
14 def __init__(self, opener, path):
14 def __init__(self, opener, path):
15 revlog.__init__(self, opener,
15 revlog.__init__(self, opener,
16 os.path.join("data", self.encodedir(path + ".i")),
16 os.path.join("data", self.encodedir(path + ".i")),
17 os.path.join("data", self.encodedir(path + ".d")))
17 os.path.join("data", self.encodedir(path + ".d")))
18
18
19 # This avoids a collision between a file named foo and a dir named
19 # This avoids a collision between a file named foo and a dir named
20 # foo.i or foo.d
20 # foo.i or foo.d
21 def encodedir(self, path):
21 def encodedir(self, path):
22 return (path
22 return (path
23 .replace(".hg/", ".hg.hg/")
23 .replace(".hg/", ".hg.hg/")
24 .replace(".i/", ".i.hg/")
24 .replace(".i/", ".i.hg/")
25 .replace(".d/", ".d.hg/"))
25 .replace(".d/", ".d.hg/"))
26
26
27 def decodedir(self, path):
27 def decodedir(self, path):
28 return (path
28 return (path
29 .replace(".d.hg/", ".d/")
29 .replace(".d.hg/", ".d/")
30 .replace(".i.hg/", ".i/")
30 .replace(".i.hg/", ".i/")
31 .replace(".hg.hg/", ".hg/"))
31 .replace(".hg.hg/", ".hg/"))
32
32
33 def read(self, node):
33 def read(self, node):
34 t = self.revision(node)
34 t = self.revision(node)
35 if not t.startswith('\1\n'):
35 if not t.startswith('\1\n'):
36 return t
36 return t
37 s = t.find('\1\n', 2)
37 s = t.find('\1\n', 2)
38 return t[s+2:]
38 return t[s+2:]
39
39
40 def readmeta(self, node):
40 def readmeta(self, node):
41 t = self.revision(node)
41 t = self.revision(node)
42 if not t.startswith('\1\n'):
42 if not t.startswith('\1\n'):
43 return {}
43 return {}
44 s = t.find('\1\n', 2)
44 s = t.find('\1\n', 2)
45 mt = t[2:s]
45 mt = t[2:s]
46 m = {}
46 m = {}
47 for l in mt.splitlines():
47 for l in mt.splitlines():
48 k, v = l.split(": ", 1)
48 k, v = l.split(": ", 1)
49 m[k] = v
49 m[k] = v
50 return m
50 return m
51
51
52 def add(self, text, meta, transaction, link, p1=None, p2=None):
52 def add(self, text, meta, transaction, link, p1=None, p2=None):
53 if meta or text.startswith('\1\n'):
53 if meta or text.startswith('\1\n'):
54 mt = ""
54 mt = ""
55 if meta:
55 if meta:
56 mt = [ "%s: %s\n" % (k, v) for k,v in meta.items() ]
56 mt = [ "%s: %s\n" % (k, v) for k,v in meta.items() ]
57 text = "\1\n" + "".join(mt) + "\1\n" + text
57 text = "\1\n%s\1\n%s" % ("".join(mt), text)
58 return self.addrevision(text, transaction, link, p1, p2)
58 return self.addrevision(text, transaction, link, p1, p2)
59
59
60 def renamed(self, node):
60 def renamed(self, node):
61 if 0 and self.parents(node)[0] != nullid:
61 if 0 and self.parents(node)[0] != nullid:
62 return False
62 return False
63 m = self.readmeta(node)
63 m = self.readmeta(node)
64 if m and m.has_key("copy"):
64 if m and m.has_key("copy"):
65 return (m["copy"], bin(m["copyrev"]))
65 return (m["copy"], bin(m["copyrev"]))
66 return False
66 return False
67
67
68 def annotate(self, node):
68 def annotate(self, node):
69
69
70 def decorate(text, rev):
70 def decorate(text, rev):
71 return ([rev] * len(text.splitlines()), text)
71 return ([rev] * len(text.splitlines()), text)
72
72
73 def pair(parent, child):
73 def pair(parent, child):
74 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
74 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
75 child[0][b1:b2] = parent[0][a1:a2]
75 child[0][b1:b2] = parent[0][a1:a2]
76 return child
76 return child
77
77
78 # find all ancestors
78 # find all ancestors
79 needed = {node:1}
79 needed = {node:1}
80 visit = [node]
80 visit = [node]
81 while visit:
81 while visit:
82 n = visit.pop(0)
82 n = visit.pop(0)
83 for p in self.parents(n):
83 for p in self.parents(n):
84 if p not in needed:
84 if p not in needed:
85 needed[p] = 1
85 needed[p] = 1
86 visit.append(p)
86 visit.append(p)
87 else:
87 else:
88 # count how many times we'll use this
88 # count how many times we'll use this
89 needed[p] += 1
89 needed[p] += 1
90
90
91 # sort by revision which is a topological order
91 # sort by revision which is a topological order
92 visit = [ (self.rev(n), n) for n in needed.keys() ]
92 visit = [ (self.rev(n), n) for n in needed.keys() ]
93 visit.sort()
93 visit.sort()
94 hist = {}
94 hist = {}
95
95
96 for r,n in visit:
96 for r,n in visit:
97 curr = decorate(self.read(n), self.linkrev(n))
97 curr = decorate(self.read(n), self.linkrev(n))
98 for p in self.parents(n):
98 for p in self.parents(n):
99 if p != nullid:
99 if p != nullid:
100 curr = pair(hist[p], curr)
100 curr = pair(hist[p], curr)
101 # trim the history of unneeded revs
101 # trim the history of unneeded revs
102 needed[p] -= 1
102 needed[p] -= 1
103 if not needed[p]:
103 if not needed[p]:
104 del hist[p]
104 del hist[p]
105 hist[n] = curr
105 hist[n] = curr
106
106
107 return zip(hist[n][0], hist[n][1].splitlines(1))
107 return zip(hist[n][0], hist[n][1].splitlines(1))
@@ -1,62 +1,62
1 # mdiff.py - diff and patch routines for mercurial
1 # mdiff.py - diff and patch routines for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import difflib, struct, bdiff, util, mpatch
8 import difflib, struct, bdiff, util, mpatch
9
9
10 def unidiff(a, ad, b, bd, fn, r=None, text=False):
10 def unidiff(a, ad, b, bd, fn, r=None, text=False):
11
11
12 if not a and not b: return ""
12 if not a and not b: return ""
13 epoch = util.datestr((0, 0))
13 epoch = util.datestr((0, 0))
14
14
15 if not text and (util.binary(a) or util.binary(b)):
15 if not text and (util.binary(a) or util.binary(b)):
16 l = ['Binary file %s has changed\n' % fn]
16 l = ['Binary file %s has changed\n' % fn]
17 elif a == None:
17 elif a == None:
18 b = b.splitlines(1)
18 b = b.splitlines(1)
19 l1 = "--- %s\t%s\n" % ("/dev/null", epoch)
19 l1 = "--- %s\t%s\n" % ("/dev/null", epoch)
20 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
20 l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
21 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
21 l3 = "@@ -0,0 +1,%d @@\n" % len(b)
22 l = [l1, l2, l3] + ["+" + e for e in b]
22 l = [l1, l2, l3] + ["+" + e for e in b]
23 elif b == None:
23 elif b == None:
24 a = a.splitlines(1)
24 a = a.splitlines(1)
25 l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
25 l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
26 l2 = "+++ %s\t%s\n" % ("/dev/null", epoch)
26 l2 = "+++ %s\t%s\n" % ("/dev/null", epoch)
27 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
27 l3 = "@@ -1,%d +0,0 @@\n" % len(a)
28 l = [l1, l2, l3] + ["-" + e for e in a]
28 l = [l1, l2, l3] + ["-" + e for e in a]
29 else:
29 else:
30 a = a.splitlines(1)
30 a = a.splitlines(1)
31 b = b.splitlines(1)
31 b = b.splitlines(1)
32 l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn))
32 l = list(difflib.unified_diff(a, b, "a/" + fn, "b/" + fn))
33 if not l: return ""
33 if not l: return ""
34 # difflib uses a space, rather than a tab
34 # difflib uses a space, rather than a tab
35 l[0] = l[0][:-2] + "\t" + ad + "\n"
35 l[0] = "%s\t%s\n" % (l[0][:-2], ad)
36 l[1] = l[1][:-2] + "\t" + bd + "\n"
36 l[1] = "%s\t%s\n" % (l[1][:-2], bd)
37
37
38 for ln in xrange(len(l)):
38 for ln in xrange(len(l)):
39 if l[ln][-1] != '\n':
39 if l[ln][-1] != '\n':
40 l[ln] += "\n\ No newline at end of file\n"
40 l[ln] += "\n\ No newline at end of file\n"
41
41
42 if r:
42 if r:
43 l.insert(0, "diff %s %s\n" %
43 l.insert(0, "diff %s %s\n" %
44 (' '.join(["-r %s" % rev for rev in r]), fn))
44 (' '.join(["-r %s" % rev for rev in r]), fn))
45
45
46 return "".join(l)
46 return "".join(l)
47
47
48 def patchtext(bin):
48 def patchtext(bin):
49 pos = 0
49 pos = 0
50 t = []
50 t = []
51 while pos < len(bin):
51 while pos < len(bin):
52 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
52 p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
53 pos += 12
53 pos += 12
54 t.append(bin[pos:pos + l])
54 t.append(bin[pos:pos + l])
55 pos += l
55 pos += l
56 return "".join(t)
56 return "".join(t)
57
57
58 def patch(a, bin):
58 def patch(a, bin):
59 return mpatch.patches(a, [bin])
59 return mpatch.patches(a, [bin])
60
60
61 patches = mpatch.patches
61 patches = mpatch.patches
62 textdiff = bdiff.bdiff
62 textdiff = bdiff.bdiff
General Comments 0
You need to be logged in to leave comments. Login now