Mercurial > hgsubversion
annotate hgsubversion/maps.py @ 1550:67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
The `fromsvn()` revset implementation could cause weakref error when using
sqliterevmap like:
File "hgsubversion/util.py", line 357, in <lambda>
return subset.filter(lambda r: tonode(r) in hashes)
File "hgsubversion/maps.py", line 542, in __contains__
return self.get(key) != None
File "hgsubversion/maps.py", line 533, in get
for row in self.revmap._query(
ReferenceError: weakly-referenced object no longer exists
Basically the seemingly harmless assignment could break surprisingly:
# dangerous: `hashes` does not have a reference of `meta.revmap` and may
# become unavailable after `meta`, `revmap` being released by refcount.
hashes = meta.revmap.hashes()
The above syntax is nice to support while avoiding cycles is also nice.
This patch removes `revmap._hashes` so the revmap no longer owns a reference
of a `ReverseRevMap` object so the `ReverseRevMap` object no longer needs to
use weakref for `self.revmap`.
This could actually be caught by `comprehensive/test_sqlite_revmap.py`.
I was not careful enough verifying the "fromsvn()" patch.
| author | Jun Wu <quark@fb.com> |
|---|---|
| date | Thu, 21 Dec 2017 17:39:52 -0800 |
| parents | 09476d758b59 |
| children | cff81f35b31e |
| rev | line source |
|---|---|
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
1 ''' Module for self-contained maps. ''' |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
2 |
| 1467 | 3 import collections |
| 4 import contextlib | |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
5 import errno |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
6 import os |
|
1394
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
7 import re |
| 1467 | 8 import sqlite3 |
| 9 import sys | |
| 10 import weakref | |
|
1439
ab15749252b0
TagMap: stop automagically running 'hg svn rebuildmeta'
Augie Fackler <raf@durin42.com>
parents:
1438
diff
changeset
|
11 from mercurial import error |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
12 from mercurial import util as hgutil |
|
1253
c54214bb6c4e
maps: avoid O(n) property lookups on the node module
Siddharth Agarwal <sid0@fb.com>
parents:
1252
diff
changeset
|
13 from mercurial.node import bin, hex, nullid |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
14 |
|
1374
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
15 import subprocess |
|
829
5061640fe5bc
revmap: load/save _youngest using new load_string and save_string API
Yonggang Luo <luoyonggang@gmail.com>
parents:
826
diff
changeset
|
16 import util |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
17 |
|
1383
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
18 class BaseMap(dict): |
|
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
19 '''A base class for the different type of mappings: author, branch, and |
|
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
20 tags.''' |
|
1441
e79ff1a85938
BaseMap: no longer take a meta as an argument
Augie Fackler <raf@durin42.com>
parents:
1440
diff
changeset
|
21 def __init__(self, ui, filepath): |
|
1383
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
22 super(BaseMap, self).__init__() |
|
1441
e79ff1a85938
BaseMap: no longer take a meta as an argument
Augie Fackler <raf@durin42.com>
parents:
1440
diff
changeset
|
23 self._ui = ui |
|
1383
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
24 |
|
1394
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
25 self._commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*') |
|
1401
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
26 self.syntaxes = ('re', 'glob') |
|
1394
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
27 |
|
1441
e79ff1a85938
BaseMap: no longer take a meta as an argument
Augie Fackler <raf@durin42.com>
parents:
1440
diff
changeset
|
28 self._filepath = filepath |
|
e79ff1a85938
BaseMap: no longer take a meta as an argument
Augie Fackler <raf@durin42.com>
parents:
1440
diff
changeset
|
29 self.load(filepath) |
|
1383
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
30 |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
31 # Append mappings specified from the commandline. A little |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
32 # magic here: our name in the config mapping is the same as |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
33 # the class name lowercased. |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
34 clmap = util.configpath(self._ui, self.mapname()) |
|
1383
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
35 if clmap: |
|
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
36 self.load(clmap) |
|
73c76f99ca08
maps: add a basemap class
Sean Farley <sean.michael.farley@gmail.com>
parents:
1382
diff
changeset
|
37 |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
38 @classmethod |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
39 def mapname(cls): |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
40 return cls.__name__.lower() |
|
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
41 |
|
1395
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
42 def _findkey(self, key): |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
43 '''Takes a string and finds the first corresponding key that matches |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
44 via regex''' |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
45 if not key: |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
46 return None |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
47 |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
48 # compile a new regex key if we're given a string; can't use |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
49 # hgutil.compilere since we need regex.sub |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
50 k = key |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
51 if isinstance(key, str): |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
52 k = re.compile(re.escape(key)) |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
53 |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
54 # preference goes to matching the exact pattern, i.e. 'foo' should |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
55 # first match 'foo' before trying regexes |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
56 for regex in self: |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
57 if regex.pattern == k.pattern: |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
58 return regex |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
59 |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
60 # if key isn't a string, then we are done; nothing matches |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
61 if not isinstance(key, str): |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
62 return None |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
63 |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
64 # now we test the regex; the above loop will be faster and is |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
65 # equivalent to not having regexes (i.e. just doing string compares) |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
66 for regex in self: |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
67 if regex.search(key): |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
68 return regex |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
69 return None |
|
53184be1b1fd
maps: add _findkey method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1394
diff
changeset
|
70 |
|
1396
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
71 def get(self, key, default=None): |
|
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
72 '''Similar to dict.get, except we use our own matcher, _findkey.''' |
|
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
73 if self._findkey(key): |
|
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
74 return self[key] |
|
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
75 return default |
|
77594c88d91f
maps: add custom get method
Sean Farley <sean.michael.farley@gmail.com>
parents:
1395
diff
changeset
|
76 |
|
1397
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
77 def __getitem__(self, key): |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
78 '''Similar to dict.get, except we use our own matcher, _findkey. If the key is |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
79 a string, then we can use our regex matching to map its value. |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
80 ''' |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
81 k = self._findkey(key) |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
82 val = super(BaseMap, self).__getitem__(k) |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
83 |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
84 # if key is a string then we can transform it using our regex, else we |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
85 # don't have enough information, so we just return the val |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
86 if isinstance(key, str): |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
87 val = k.sub(val, key) |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
88 |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
89 return val |
|
304fdb9810a6
maps: add custom __getitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1396
diff
changeset
|
90 |
|
1398
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
91 def __setitem__(self, key, value): |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
92 '''Similar to dict.__setitem__, except we compile the string into a regex, if |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
93 need be. |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
94 ''' |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
95 # try to find the regex already in the map |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
96 k = self._findkey(key) |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
97 # if we found one, then use it |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
98 if k: |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
99 key = k |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
100 # else make a new regex |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
101 if isinstance(key, str): |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
102 key = re.compile(re.escape(key)) |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
103 super(BaseMap, self).__setitem__(key, value) |
|
75745298d99d
maps: add custom __setitem__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1397
diff
changeset
|
104 |
|
1399
3b96075bffa7
maps: add custom __contains__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1398
diff
changeset
|
105 def __contains__(self, key): |
|
3b96075bffa7
maps: add custom __contains__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1398
diff
changeset
|
106 '''Similar to dict.get, except we use our own matcher, _findkey.''' |
|
3b96075bffa7
maps: add custom __contains__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1398
diff
changeset
|
107 return self._findkey(key) is not None |
|
3b96075bffa7
maps: add custom __contains__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1398
diff
changeset
|
108 |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
109 def load(self, path): |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
110 '''Load mappings from a file at the specified path.''' |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
111 path = os.path.expandvars(path) |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
112 if not os.path.exists(path): |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
113 return |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
114 |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
115 writing = False |
|
1431
066c08918060
BaseMap: record filename on self._filename
Augie Fackler <raf@durin42.com>
parents:
1430
diff
changeset
|
116 mapfile = self._filepath |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
117 if path != mapfile: |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
118 writing = open(mapfile, 'a') |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
119 |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
120 self._ui.debug('reading %s from %s\n' % (self.mapname() , path)) |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
121 f = open(path, 'r') |
|
1401
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
122 syntax = '' |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
123 for number, line in enumerate(f): |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
124 |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
125 if writing: |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
126 writing.write(line) |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
127 |
|
1394
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
128 # strip out comments |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
129 if "#" in line: |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
130 # remove comments prefixed by an even number of escapes |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
131 line = self._commentre.sub(r'\1', line) |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
132 # fixup properly escaped comments that survived the above |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
133 line = line.replace("\\#", "#") |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
134 line = line.rstrip() |
|
c4055968f030
maps: use regex for better comment handling
Sean Farley <sean.michael.farley@gmail.com>
parents:
1393
diff
changeset
|
135 if not line: |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
136 continue |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
137 |
|
1401
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
138 if line.startswith('syntax:'): |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
139 s = line[7:].strip() |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
140 syntax = '' |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
141 if s in self.syntaxes: |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
142 syntax = s |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
143 continue |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
144 pat = syntax |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
145 for s in self.syntaxes: |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
146 if line.startswith(s + ':'): |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
147 pat = s |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
148 line = line[len(s) + 1:] |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
149 break |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
150 |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
151 # split on the first '=' |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
152 try: |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
153 src, dst = line.split('=', 1) |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
154 except (IndexError, ValueError): |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
155 msg = 'ignoring line %i in %s %s: %s\n' |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
156 self._ui.status(msg % (number, self.mapname(), path, |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
157 line.rstrip())) |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
158 continue |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
159 |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
160 src = src.strip() |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
161 dst = dst.strip() |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
162 |
|
1401
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
163 if pat != 're': |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
164 src = re.escape(src) |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
165 if pat == 'glob': |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
166 src = src.replace('\\*', '.*') |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
167 src = re.compile(src) |
|
70cb6ba038fa
maps: add ability to parse a regex or glob
Sean Farley <sean.michael.farley@gmail.com>
parents:
1400
diff
changeset
|
168 |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
169 if src not in self: |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
170 self._ui.debug('adding %s to %s\n' % (src, self.mapname())) |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
171 elif dst != self[src]: |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
172 msg = 'overriding %s: "%s" to "%s" (%s)\n' |
|
1440
4d3a51e82147
BaseMap: extract filename attribute magic into a classmethod
Augie Fackler <raf@durin42.com>
parents:
1439
diff
changeset
|
173 self._ui.status(msg % (self.mapname(), self[src], dst, src)) |
|
1384
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
174 self[src] = dst |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
175 |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
176 f.close() |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
177 if writing: |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
178 writing.close() |
|
2d1d05e6e46c
maps: add a load method to base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1383
diff
changeset
|
179 |
|
1385
9139d9295a36
maps: make author map inherit from base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1384
diff
changeset
|
180 class AuthorMap(BaseMap): |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
181 '''A mapping from Subversion-style authors to Mercurial-style |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
182 authors, and back. The data is stored persistently on disk. |
|
322
05cd4a5138bf
Move some .warn() calls to noisy levels instead.
Augie Fackler <durin42@gmail.com>
parents:
310
diff
changeset
|
183 |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
184 If the 'hgsubversion.defaultauthors' configuration option is set to false, |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
185 attempting to obtain an unknown author will fail with an Abort. |
|
1188
38dd8721fb0d
maps: remove trailing whitespace
Sean Farley <sean.michael.farley@gmail.com>
parents:
1187
diff
changeset
|
186 |
|
1097
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
187 If the 'hgsubversion.caseignoreauthors' configuration option is set to true, |
|
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
188 the userid from Subversion is always compared lowercase. |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
189 ''' |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
190 |
|
1442
a0ba38def79b
AuthorMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1441
diff
changeset
|
191 def __init__(self, ui, filepath, defaulthost, caseignoreauthors, |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
192 mapauthorscmd, defaultauthors): |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
193 '''Initialise a new AuthorMap. |
|
322
05cd4a5138bf
Move some .warn() calls to noisy levels instead.
Augie Fackler <durin42@gmail.com>
parents:
310
diff
changeset
|
194 |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
195 The ui argument is used to print diagnostic messages. |
|
322
05cd4a5138bf
Move some .warn() calls to noisy levels instead.
Augie Fackler <durin42@gmail.com>
parents:
310
diff
changeset
|
196 |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
197 The path argument is the location of the backing store, |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
198 typically .hg/svn/authors. |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
199 ''' |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
200 if defaulthost: |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
201 self.defaulthost = '@%s' % defaulthost.lstrip('@') |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
202 else: |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
203 self.defaulthost = '' |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
204 self._caseignoreauthors = caseignoreauthors |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
205 self._mapauthorscmd = mapauthorscmd |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
206 self._defaulthost = defaulthost |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
207 self._defaultauthors = defaultauthors |
|
1194
49791c40a8a5
maps: change authormap to initialize with an svnmeta object
Sean Farley <sean.michael.farley@gmail.com>
parents:
1193
diff
changeset
|
208 |
|
1442
a0ba38def79b
AuthorMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1441
diff
changeset
|
209 super(AuthorMap, self).__init__(ui, filepath) |
|
1193
a55339d35066
maps: load commandline authormap in __init__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1188
diff
changeset
|
210 |
|
1400
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
211 def _lowercase(self, key): |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
212 '''Determine whether or not to lowercase a str or regex using the |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
213 meta.caseignoreauthors.''' |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
214 k = key |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
215 if self._caseignoreauthors: |
|
1400
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
216 if isinstance(key, str): |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
217 k = key.lower() |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
218 else: |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
219 k = re.compile(key.pattern.lower()) |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
220 return k |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
221 |
|
1379
367e65989b41
maps: add custom __setitem__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1375
diff
changeset
|
222 def __setitem__(self, key, value): |
|
367e65989b41
maps: add custom __setitem__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1375
diff
changeset
|
223 '''Similar to dict.__setitem__, except we check caseignoreauthors to |
|
367e65989b41
maps: add custom __setitem__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1375
diff
changeset
|
224 use lowercase string or not |
|
367e65989b41
maps: add custom __setitem__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1375
diff
changeset
|
225 ''' |
|
1400
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
226 super(AuthorMap, self).__setitem__(self._lowercase(key), value) |
|
1379
367e65989b41
maps: add custom __setitem__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1375
diff
changeset
|
227 |
|
1380
332ad9ea579b
maps: add custom __contains__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1379
diff
changeset
|
228 def __contains__(self, key): |
|
332ad9ea579b
maps: add custom __contains__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1379
diff
changeset
|
229 '''Similar to dict.__contains__, except we check caseignoreauthors to |
|
332ad9ea579b
maps: add custom __contains__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1379
diff
changeset
|
230 use lowercase string or not |
|
332ad9ea579b
maps: add custom __contains__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1379
diff
changeset
|
231 ''' |
|
1400
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
232 return super(AuthorMap, self).__contains__(self._lowercase(key)) |
|
1380
332ad9ea579b
maps: add custom __contains__ to author map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1379
diff
changeset
|
233 |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
234 def __getitem__(self, author): |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
235 ''' Similar to dict.__getitem__, except in case of an unknown author. |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
236 In such cases, a new value is generated and added to the dictionary |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
237 as well as the backing store. ''' |
|
735
c2b9e08ecf10
maps: map a missing author to '(no author)'
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
729
diff
changeset
|
238 if author is None: |
|
c2b9e08ecf10
maps: map a missing author to '(no author)'
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
729
diff
changeset
|
239 author = '(no author)' |
|
1097
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
240 |
|
1400
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
241 if not isinstance(author, str): |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
242 return super(AuthorMap, self).__getitem__(author) |
|
3e264851f879
maps: protect author map functions from regexes
Sean Farley <sean.michael.farley@gmail.com>
parents:
1399
diff
changeset
|
243 |
|
1196
878372849175
maps: use meta.caseignoreauthors intead of accessing ui directly
Sean Farley <sean.michael.farley@gmail.com>
parents:
1195
diff
changeset
|
244 search_author = author |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
245 if self._caseignoreauthors: |
|
1097
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
246 search_author = author.lower() |
|
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
247 |
|
1374
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
248 result = None |
|
1097
e015cd34168d
authormap: allow case-insensitive authormaps for easier conversions
maugustin
parents:
976
diff
changeset
|
249 if search_author in self: |
|
1382
d996850ac4e8
maps: call super directly instead of self.super
Sean Farley <sean.michael.farley@gmail.com>
parents:
1381
diff
changeset
|
250 result = super(AuthorMap, self).__getitem__(search_author) |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
251 elif self._mapauthorscmd: |
|
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
252 cmd = self._mapauthorscmd % author |
|
1375
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
253 process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
254 output, err = process.communicate() |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
255 retcode = process.poll() |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
256 if retcode: |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
257 msg = 'map author command "%s" exited with error' |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
258 raise hgutil.Abort(msg % cmd) |
|
abc87a62ff51
maps: remove python2.7ism from dynamic author mapping
Mateusz Kwapich <mitrandir@fb.com>
parents:
1374
diff
changeset
|
259 self[author] = result = output.strip() |
|
1374
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
260 if not result: |
|
1429
3a723188051e
AuthorMap: make local implementation concerns stop using self.meta
Augie Fackler <raf@durin42.com>
parents:
1428
diff
changeset
|
261 if self._defaultauthors: |
|
1374
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
262 self[author] = result = '%s%s' % (author, self.defaulthost) |
|
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
263 msg = 'substituting author "%s" for default "%s"\n' |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
264 self._ui.debug(msg % (author, result)) |
|
1374
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
265 else: |
|
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
266 msg = 'author %s has no entry in the author map!' |
|
a17d8874a099
Added dynamic author mapping.
Jerome M. BERGER <jeberger@free.fr>
parents:
1356
diff
changeset
|
267 raise hgutil.Abort(msg % author) |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
268 self._ui.debug('mapping author "%s" to "%s"\n' % (author, result)) |
|
307
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
269 return result |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
270 |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
271 def reverselookup(self, author): |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
272 for svnauthor, hgauthor in self.iteritems(): |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
273 if author == hgauthor: |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
274 return svnauthor |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
275 else: |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
276 # Mercurial incorrectly splits at e.g. '.', so we roll our own. |
|
1d48d9a34c19
Put authormap into a separate file, and make it much better too.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
diff
changeset
|
277 return author.rsplit('@', 1)[0] |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
278 |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
279 |
|
728
cfefeefad199
rename TagMap to Tags, to free up the TagMap name
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
725
diff
changeset
|
280 class Tags(dict): |
|
519
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
281 """Map tags to converted node identifier. |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
282 |
| 729 | 283 tag names are non-empty strings. Tags are saved in a file |
| 284 called tagmap, for backwards compatibility reasons. | |
|
519
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
285 """ |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
286 VERSION = 2 |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
287 |
|
1445
5dbc6356a0d3
Tags: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1444
diff
changeset
|
288 def __init__(self, ui, filepath, endrev=None): |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
289 dict.__init__(self) |
|
1445
5dbc6356a0d3
Tags: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1444
diff
changeset
|
290 self._filepath = filepath |
|
5dbc6356a0d3
Tags: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1444
diff
changeset
|
291 self._ui = ui |
| 725 | 292 self.endrev = endrev |
|
1432
a2ef2c1e3644
TagMap: record filepath explicitly
Augie Fackler <raf@durin42.com>
parents:
1431
diff
changeset
|
293 if os.path.isfile(self._filepath): |
|
1187
30b2139c3931
maps: change tags init to accept svnmeta not a repo
Sean Farley <sean.michael.farley@gmail.com>
parents:
1186
diff
changeset
|
294 self._load() |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
295 else: |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
296 self._write() |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
297 |
|
1187
30b2139c3931
maps: change tags init to accept svnmeta not a repo
Sean Farley <sean.michael.farley@gmail.com>
parents:
1186
diff
changeset
|
298 def _load(self): |
|
1432
a2ef2c1e3644
TagMap: record filepath explicitly
Augie Fackler <raf@durin42.com>
parents:
1431
diff
changeset
|
299 f = open(self._filepath) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
300 ver = int(f.readline()) |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
301 if ver < self.VERSION: |
|
1439
ab15749252b0
TagMap: stop automagically running 'hg svn rebuildmeta'
Augie Fackler <raf@durin42.com>
parents:
1438
diff
changeset
|
302 raise error.Abort( |
|
ab15749252b0
TagMap: stop automagically running 'hg svn rebuildmeta'
Augie Fackler <raf@durin42.com>
parents:
1438
diff
changeset
|
303 'tag map outdated, please run `hg svn rebuildmeta`') |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
304 elif ver != self.VERSION: |
|
891
83cc6e9e8425
kill all 'print' statements in the extension proper
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
889
diff
changeset
|
305 raise hgutil.Abort('tagmap too new -- please upgrade') |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
306 for l in f: |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
307 ha, revision, tag = l.split(' ', 2) |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
308 revision = int(revision) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
309 tag = tag[:-1] |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
310 if self.endrev is not None and revision > self.endrev: |
|
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
311 break |
|
519
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
312 if not tag: |
|
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
313 continue |
|
1253
c54214bb6c4e
maps: avoid O(n) property lookups on the node module
Siddharth Agarwal <sid0@fb.com>
parents:
1252
diff
changeset
|
314 dict.__setitem__(self, tag, bin(ha)) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
315 f.close() |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
316 |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
317 def _write(self): |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
318 assert self.endrev is None |
|
1432
a2ef2c1e3644
TagMap: record filepath explicitly
Augie Fackler <raf@durin42.com>
parents:
1431
diff
changeset
|
319 f = open(self._filepath, 'w') |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
320 f.write('%s\n' % self.VERSION) |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
321 f.close() |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
322 |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
323 def update(self, other): |
| 725 | 324 for k, v in other.iteritems(): |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
325 self[k] = v |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
326 |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
327 def __contains__(self, tag): |
|
593
eb16630bceb1
maps: fix a % formatting bug
Augie Fackler <durin42@gmail.com>
parents:
579
diff
changeset
|
328 return (tag and dict.__contains__(self, tag) |
|
1253
c54214bb6c4e
maps: avoid O(n) property lookups on the node module
Siddharth Agarwal <sid0@fb.com>
parents:
1252
diff
changeset
|
329 and dict.__getitem__(self, tag) != nullid) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
330 |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
331 def __getitem__(self, tag): |
|
519
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
332 if tag and tag in self: |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
333 return dict.__getitem__(self, tag) |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
334 raise KeyError() |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
335 |
|
453
bb612e625be6
tags: handle copyfrom old versions of tags more correctly
Augie Fackler <durin42@gmail.com>
parents:
448
diff
changeset
|
336 def __setitem__(self, tag, info): |
|
519
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
337 if not tag: |
|
247110c633f7
maps: TagMap tags are non-empty strings
Patrick Mezard <pmezard@gmail.com>
parents:
460
diff
changeset
|
338 raise hgutil.Abort('tag cannot be empty') |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
339 ha, revision = info |
|
1432
a2ef2c1e3644
TagMap: record filepath explicitly
Augie Fackler <raf@durin42.com>
parents:
1431
diff
changeset
|
340 f = open(self._filepath, 'a') |
|
1253
c54214bb6c4e
maps: avoid O(n) property lookups on the node module
Siddharth Agarwal <sid0@fb.com>
parents:
1252
diff
changeset
|
341 f.write('%s %s %s\n' % (hex(ha), revision, tag)) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
342 f.close() |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
343 dict.__setitem__(self, tag, ha) |
|
448
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
344 |
|
fbc7cf4fd701
tags: reinstate a tag map file in a better way
Augie Fackler <durin42@gmail.com>
parents:
430
diff
changeset
|
345 |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
346 class RevMap(dict): |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
347 |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
348 VERSION = 1 |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
349 |
|
1455
8cfe074cd463
maps: use util.fileproperty for RevMap.lastpulled
Jun Wu <quark@fb.com>
parents:
1449
diff
changeset
|
350 lastpulled = util.fileproperty('_lastpulled', lambda x: x._lastpulled_file, |
|
8cfe074cd463
maps: use util.fileproperty for RevMap.lastpulled
Jun Wu <quark@fb.com>
parents:
1449
diff
changeset
|
351 default=0, deserializer=int) |
|
8cfe074cd463
maps: use util.fileproperty for RevMap.lastpulled
Jun Wu <quark@fb.com>
parents:
1449
diff
changeset
|
352 |
|
1446
2eba84031a78
RevMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1445
diff
changeset
|
353 def __init__(self, revmap_path, lastpulled_path): |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
354 dict.__init__(self) |
|
1446
2eba84031a78
RevMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1445
diff
changeset
|
355 self._filepath = revmap_path |
|
2eba84031a78
RevMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1445
diff
changeset
|
356 self._lastpulled_file = lastpulled_path |
|
1294
9a722b5246df
maps: cache hashes() for the revmap
Mateusz Kwapich <mitrandir@fb.com>
parents:
1254
diff
changeset
|
357 self._hashes = None |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
358 # disable iteration to have a consistent interface with SqliteRevMap |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
359 # it's less about performance since RevMap needs iteration internally |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
360 self._allowiter = False |
|
1183
09b20039192c
maps: change revmap init to accept svnmeta not a repo
Sean Farley <sean.michael.farley@gmail.com>
parents:
1182
diff
changeset
|
361 |
|
1434
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
362 self.firstpulled = 0 |
|
1430
48beb467b2e5
RevMap: use self._filepath instead of using meta
Augie Fackler <raf@durin42.com>
parents:
1429
diff
changeset
|
363 if os.path.isfile(self._filepath): |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
364 self._load() |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
365 else: |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
366 self._write() |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
367 |
|
415
b17b2969861c
svnmeta: move revmap methods, make last_known_revision() more efficient
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
409
diff
changeset
|
368 def hashes(self): |
|
1294
9a722b5246df
maps: cache hashes() for the revmap
Mateusz Kwapich <mitrandir@fb.com>
parents:
1254
diff
changeset
|
369 if self._hashes is None: |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
370 self._hashes = dict((v, k) for (k, v) in self._origiteritems()) |
|
1294
9a722b5246df
maps: cache hashes() for the revmap
Mateusz Kwapich <mitrandir@fb.com>
parents:
1254
diff
changeset
|
371 return self._hashes |
|
415
b17b2969861c
svnmeta: move revmap methods, make last_known_revision() more efficient
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
409
diff
changeset
|
372 |
|
1472
cf79525f507c
maps: change branchedits to accept revnum directly
Jun Wu <quark@fb.com>
parents:
1470
diff
changeset
|
373 def branchedits(self, branch, revnum): |
|
cf79525f507c
maps: change branchedits to accept revnum directly
Jun Wu <quark@fb.com>
parents:
1470
diff
changeset
|
374 check = lambda x: x[0][1] == branch and x[0][0] < revnum |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
375 return sorted(filter(check, self._origiteritems()), reverse=True) |
|
415
b17b2969861c
svnmeta: move revmap methods, make last_known_revision() more efficient
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
409
diff
changeset
|
376 |
|
1422
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
377 def branchmaxrevnum(self, branch, maxrevnum): |
|
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
378 result = 0 |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
379 for num, br in self._origiterkeys(): |
|
1422
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
380 if br == branch and num <= maxrevnum and num > result: |
|
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
381 result = num |
|
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
382 return result |
|
372afb75f465
maps: add the "branchmaxrevnum" method to RevMap
Jun Wu <quark@fb.com>
parents:
1421
diff
changeset
|
383 |
|
1419
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
384 @property |
|
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
385 def lasthash(self): |
|
1421
0094f222c5dc
maps: make readmapfile of RevMap a private instance method
Jun Wu <quark@fb.com>
parents:
1419
diff
changeset
|
386 lines = list(self._readmapfile()) |
|
1419
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
387 if not lines: |
|
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
388 return None |
|
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
389 return bin(lines[-1].split(' ', 2)[1]) |
|
2e4145e452cd
maps: add "lasthash" property to RevMap
Jun Wu <quark@fb.com>
parents:
1414
diff
changeset
|
390 |
|
1413
951a87f2f2bd
maps: add the "revhashes" method to RevMap
Jun Wu <quark@fb.com>
parents:
1412
diff
changeset
|
391 def revhashes(self, revnum): |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
392 for key, value in self._origiteritems(): |
|
1413
951a87f2f2bd
maps: add the "revhashes" method to RevMap
Jun Wu <quark@fb.com>
parents:
1412
diff
changeset
|
393 if key[0] == revnum: |
|
951a87f2f2bd
maps: add the "revhashes" method to RevMap
Jun Wu <quark@fb.com>
parents:
1412
diff
changeset
|
394 yield value |
|
951a87f2f2bd
maps: add the "revhashes" method to RevMap
Jun Wu <quark@fb.com>
parents:
1412
diff
changeset
|
395 |
|
1411
025e849d22f0
maps: add the "clear" method to RevMap
Jun Wu <quark@fb.com>
parents:
1401
diff
changeset
|
396 def clear(self): |
|
025e849d22f0
maps: add the "clear" method to RevMap
Jun Wu <quark@fb.com>
parents:
1401
diff
changeset
|
397 self._write() |
|
025e849d22f0
maps: add the "clear" method to RevMap
Jun Wu <quark@fb.com>
parents:
1401
diff
changeset
|
398 dict.clear(self) |
|
025e849d22f0
maps: add the "clear" method to RevMap
Jun Wu <quark@fb.com>
parents:
1401
diff
changeset
|
399 self._hashes = None |
|
025e849d22f0
maps: add the "clear" method to RevMap
Jun Wu <quark@fb.com>
parents:
1401
diff
changeset
|
400 |
|
1434
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
401 def batchset(self, items, lastpulled): |
|
1412
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
402 '''Set items in batches |
|
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
403 |
|
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
404 items is an array of (rev num, branch, binary hash) |
|
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
405 |
|
1424
a794cbc174a9
maps: document RevMap.batchset will not update internal state
Jun Wu <quark@fb.com>
parents:
1422
diff
changeset
|
406 For performance reason, internal in-memory state is not updated. |
|
a794cbc174a9
maps: document RevMap.batchset will not update internal state
Jun Wu <quark@fb.com>
parents:
1422
diff
changeset
|
407 To get an up-to-date RevMap, reconstruct the object. |
|
1412
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
408 ''' |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
409 with open(self._filepath, 'a') as f: |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
410 f.write(''.join('%s %s %s\n' % (revnum, hex(binhash), br or '') |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
411 for revnum, br, binhash in items)) |
|
1455
8cfe074cd463
maps: use util.fileproperty for RevMap.lastpulled
Jun Wu <quark@fb.com>
parents:
1449
diff
changeset
|
412 self.lastpulled = lastpulled |
|
1412
7e98352a37db
maps: add the "batchset" method to RevMap
Jun Wu <quark@fb.com>
parents:
1411
diff
changeset
|
413 |
|
1421
0094f222c5dc
maps: make readmapfile of RevMap a private instance method
Jun Wu <quark@fb.com>
parents:
1419
diff
changeset
|
414 def _readmapfile(self): |
|
1430
48beb467b2e5
RevMap: use self._filepath instead of using meta
Augie Fackler <raf@durin42.com>
parents:
1429
diff
changeset
|
415 path = self._filepath |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
416 try: |
|
1182
8f9619a67565
maps: change readmapfile to take a path instead of repo
Sean Farley <sean.michael.farley@gmail.com>
parents:
1144
diff
changeset
|
417 f = open(path) |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
418 except IOError, err: |
|
1421
0094f222c5dc
maps: make readmapfile of RevMap a private instance method
Jun Wu <quark@fb.com>
parents:
1419
diff
changeset
|
419 if err.errno != errno.ENOENT: |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
420 raise |
|
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
421 return iter([]) |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
422 ver = int(f.readline()) |
|
1469
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
423 if ver == SqliteRevMap.VERSION: |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
424 revmap = SqliteRevMap(self._filepath, self._lastpulled_file) |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
425 tmppath = '%s.tmp' % self._filepath |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
426 revmap.exportrevmapv1(tmppath) |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
427 os.rename(tmppath, self._filepath) |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
428 hgutil.unlinkpath(revmap._dbpath) |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
429 hgutil.unlinkpath(revmap._rowcountpath, ignoremissing=True) |
|
1469
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
430 return self._readmapfile() |
|
1421
0094f222c5dc
maps: make readmapfile of RevMap a private instance method
Jun Wu <quark@fb.com>
parents:
1419
diff
changeset
|
431 if ver != self.VERSION: |
|
891
83cc6e9e8425
kill all 'print' statements in the extension proper
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
889
diff
changeset
|
432 raise hgutil.Abort('revmap too new -- please upgrade') |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
433 return f |
|
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
434 |
|
1251
46cec117dda2
maps.RevMap: disable GC while loading the revmap
Siddharth Agarwal <sid0@fb.com>
parents:
1217
diff
changeset
|
435 @util.gcdisable |
|
889
7a98fbadcae9
revsets: huge speedups for fromsvn and svnrev
Bryan O'Sullivan <bryano@fb.com>
parents:
847
diff
changeset
|
436 def _load(self): |
|
1434
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
437 lastpulled = self.lastpulled |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
438 firstpulled = self.firstpulled |
|
1254
d07ccad28b1a
maps.RevMap: avoid O(revs) property lookups on dict
Siddharth Agarwal <sid0@fb.com>
parents:
1253
diff
changeset
|
439 setitem = dict.__setitem__ |
|
1421
0094f222c5dc
maps: make readmapfile of RevMap a private instance method
Jun Wu <quark@fb.com>
parents:
1419
diff
changeset
|
440 for l in self._readmapfile(): |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
441 revnum, ha, branch = l.split(' ', 2) |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
442 if branch == '\n': |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
443 branch = None |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
444 else: |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
445 branch = branch[:-1] |
|
415
b17b2969861c
svnmeta: move revmap methods, make last_known_revision() more efficient
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
409
diff
changeset
|
446 revnum = int(revnum) |
|
1252
a321afbc3479
maps.RevMap: while loading, read lastpulled and firstpulled once
Siddharth Agarwal <sid0@fb.com>
parents:
1251
diff
changeset
|
447 if revnum > lastpulled or not lastpulled: |
|
a321afbc3479
maps.RevMap: while loading, read lastpulled and firstpulled once
Siddharth Agarwal <sid0@fb.com>
parents:
1251
diff
changeset
|
448 lastpulled = revnum |
|
a321afbc3479
maps.RevMap: while loading, read lastpulled and firstpulled once
Siddharth Agarwal <sid0@fb.com>
parents:
1251
diff
changeset
|
449 if revnum < firstpulled or not firstpulled: |
|
a321afbc3479
maps.RevMap: while loading, read lastpulled and firstpulled once
Siddharth Agarwal <sid0@fb.com>
parents:
1251
diff
changeset
|
450 firstpulled = revnum |
|
1254
d07ccad28b1a
maps.RevMap: avoid O(revs) property lookups on dict
Siddharth Agarwal <sid0@fb.com>
parents:
1253
diff
changeset
|
451 setitem(self, (revnum, branch), bin(ha)) |
|
1434
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
452 if self.lastpulled != lastpulled: |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
453 self.lastpulled = lastpulled |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
454 self.firstpulled = firstpulled |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
455 |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
456 def _write(self): |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
457 with open(self._filepath, 'w') as f: |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
458 f.write('%s\n' % self.VERSION) |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
459 |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
460 def __setitem__(self, key, ha): |
|
408
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
461 revnum, branch = key |
|
f137231f9d30
extract the revmap support into a separate dict-like class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
360
diff
changeset
|
462 b = branch or '' |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
463 with open(self._filepath, 'a') as f: |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
464 f.write(str(revnum) + ' ' + hex(ha) + ' ' + b + '\n') |
|
1434
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
465 if revnum > self.lastpulled or not self.lastpulled: |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
466 self.lastpulled = revnum |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
467 if revnum < self.firstpulled or not self.firstpulled: |
|
0a6b3da6d34c
RevMap: move lastpulled from SVNMeta down into RevMap
Augie Fackler <raf@durin42.com>
parents:
1432
diff
changeset
|
468 self.firstpulled = revnum |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
469 dict.__setitem__(self, (revnum, branch), ha) |
|
1294
9a722b5246df
maps: cache hashes() for the revmap
Mateusz Kwapich <mitrandir@fb.com>
parents:
1254
diff
changeset
|
470 if self._hashes is not None: |
|
9a722b5246df
maps: cache hashes() for the revmap
Mateusz Kwapich <mitrandir@fb.com>
parents:
1254
diff
changeset
|
471 self._hashes[ha] = (revnum, branch) |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
472 |
|
1468
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
473 @classmethod |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
474 def _wrapitermethods(cls): |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
475 def wrap(orig): |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
476 def wrapper(self, *args, **kwds): |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
477 if not self._allowiter: |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
478 raise NotImplementedError( |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
479 'Iteration methods on RevMap are disabled ' + |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
480 'to avoid performance issues on SqliteRevMap') |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
481 return orig(self, *args, **kwds) |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
482 return wrapper |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
483 methodre = re.compile(r'^_*(?:iter|view)?(?:keys|items|values)?_*$') |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
484 for name in filter(methodre.match, dir(cls)): |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
485 orig = getattr(cls, name) |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
486 setattr(cls, '_orig%s' % name, orig) |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
487 setattr(cls, name, wrap(orig)) |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
488 |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
489 RevMap._wrapitermethods() |
|
b98ff95b5861
maps: disable iterating methods of RevMap
Jun Wu <quark@fb.com>
parents:
1467
diff
changeset
|
490 |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
491 |
| 1467 | 492 class SqliteRevMap(collections.MutableMapping): |
| 493 """RevMap backed by sqlite3. | |
| 494 | |
| 495 It tries to address performance issues for a very large rev map. | |
| 496 As such iteration is unavailable for both the map itself and the | |
| 497 reverse map (self.hashes). | |
| 498 | |
| 499 It migrates from the old RevMap upon first use. Then it will bump the | |
| 500 version of revmap so RevMap no longer works. The real database is a | |
| 501 separated file which has a ".db" suffix. | |
| 502 """ | |
| 503 | |
| 504 VERSION = 2 | |
| 505 | |
| 506 TABLESCHEMA = [ | |
| 507 '''CREATE TABLE IF NOT EXISTS revmap ( | |
| 508 rev INTEGER NOT NULL, | |
| 509 branch TEXT NOT NULL DEFAULT '', | |
| 510 hash BLOB NOT NULL)''', | |
| 511 ] | |
| 512 | |
| 513 INDEXSCHEMA = [ | |
| 514 'CREATE UNIQUE INDEX IF NOT EXISTS revbranch ON revmap (rev,branch);', | |
| 515 'CREATE INDEX IF NOT EXISTS hash ON revmap (hash);', | |
| 516 ] | |
| 517 | |
| 518 # "bytes" in Python 2 will get truncated at '\0' when storing as sqlite | |
| 519 # blobs. "buffer" does not have this issue. Python 3 does not have "buffer" | |
| 520 # but "bytes" won't get truncated. | |
| 521 sqlblobtype = bytes if sys.version_info >= (3, 0) else buffer | |
| 522 | |
| 523 class ReverseRevMap(object): | |
| 524 # collections.Mapping is not suitable since we don't want 2/3 of | |
| 525 # its required interfaces: __iter__, __len__. | |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
526 def __init__(self, revmap, cache): |
|
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
527 self.revmap = revmap |
|
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
528 self._cache = cache |
| 1467 | 529 |
| 530 def get(self, key, default=None): | |
| 531 if key not in self._cache: | |
| 532 result = None | |
| 533 for row in self.revmap._query( | |
| 534 'SELECT rev, branch FROM revmap WHERE hash=?', | |
| 535 (SqliteRevMap.sqlblobtype(key),)): | |
| 536 result = (row[0], row[1] or None) | |
| 537 break | |
| 538 self._cache[key] = result | |
| 539 return self._cache[key] or default | |
| 540 | |
| 541 def __contains__(self, key): | |
| 542 return self.get(key) != None | |
| 543 | |
| 544 def __getitem__(self, key): | |
| 545 dummy = self._cache | |
| 546 item = self.get(key, dummy) | |
| 547 if item == dummy: | |
| 548 raise KeyError(key) | |
| 549 else: | |
| 550 return item | |
| 551 | |
| 552 def keys(self): | |
| 553 for row in self.revmap._query('SELECT hash FROM revmap'): | |
| 554 yield bytes(row[0]) | |
| 555 | |
| 556 lastpulled = util.fileproperty('_lastpulled', lambda x: x._lastpulledpath, | |
| 557 default=0, deserializer=int) | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
558 rowcount = util.fileproperty('_rowcount', lambda x: x._rowcountpath, |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
559 default=0, deserializer=int) |
| 1467 | 560 |
|
1478
797c7b58a735
maps: add a config option to tweak sqlite
Jun Wu <quark@fb.com>
parents:
1477
diff
changeset
|
561 def __init__(self, revmap_path, lastpulled_path, sqlitepragmas=None): |
| 1467 | 562 self._filepath = revmap_path |
| 563 self._dbpath = revmap_path + '.db' | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
564 self._rowcountpath = self._dbpath + '.rowcount' |
| 1467 | 565 self._lastpulledpath = lastpulled_path |
| 566 | |
| 567 self._db = None | |
|
1478
797c7b58a735
maps: add a config option to tweak sqlite
Jun Wu <quark@fb.com>
parents:
1477
diff
changeset
|
568 self._sqlitepragmas = sqlitepragmas |
| 1467 | 569 self.firstpulled = 0 |
|
1476
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
570 self._updatefirstlastpulled() |
| 1467 | 571 # __iter__ is expensive and thus disabled by default |
| 572 # it should only be enabled for testing | |
| 573 self._allowiter = False | |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
574 # used by self.hashes(), {hash: (rev, branch)} |
|
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
575 self._hashescache = {} |
| 1467 | 576 |
| 577 def hashes(self): | |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
578 return self.ReverseRevMap(self, self._hashescache) |
| 1467 | 579 |
|
1472
cf79525f507c
maps: change branchedits to accept revnum directly
Jun Wu <quark@fb.com>
parents:
1470
diff
changeset
|
580 def branchedits(self, branch, revnum): |
| 1467 | 581 return [((r[0], r[1] or None), bytes(r[2])) for r in |
| 582 self._query('SELECT rev, branch, hash FROM revmap ' + | |
| 583 'WHERE rev < ? AND branch = ? ' + | |
| 584 'ORDER BY rev DESC, branch DESC', | |
|
1472
cf79525f507c
maps: change branchedits to accept revnum directly
Jun Wu <quark@fb.com>
parents:
1470
diff
changeset
|
585 (revnum, branch or ''))] |
| 1467 | 586 |
| 587 def branchmaxrevnum(self, branch, maxrev): | |
| 588 for row in self._query('SELECT rev FROM revmap ' + | |
| 589 'WHERE rev <= ? AND branch = ? ' + | |
| 590 'ORDER By rev DESC LIMIT 1', | |
| 591 (maxrev, branch or '')): | |
| 592 return row[0] | |
| 593 return 0 | |
| 594 | |
| 595 @property | |
| 596 def lasthash(self): | |
| 597 for row in self._query('SELECT hash FROM revmap ORDER BY rev DESC'): | |
| 598 return bytes(row[0]) | |
| 599 return None | |
| 600 | |
| 601 def revhashes(self, revnum): | |
| 602 for row in self._query('SELECT hash FROM revmap WHERE rev = ?', | |
| 603 (revnum,)): | |
| 604 yield bytes(row[0]) | |
| 605 | |
| 606 def clear(self): | |
| 607 hgutil.unlinkpath(self._filepath, ignoremissing=True) | |
| 608 hgutil.unlinkpath(self._dbpath, ignoremissing=True) | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
609 hgutil.unlinkpath(self._rowcountpath, ignoremissing=True) |
| 1467 | 610 self._db = None |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
611 self._hashescache = {} |
| 1467 | 612 self._firstpull = None |
| 613 self._lastpull = None | |
| 614 | |
| 615 def batchset(self, items, lastpulled): | |
| 616 with self._transaction(): | |
| 617 self._insert(items) | |
| 618 self.lastpulled = lastpulled | |
| 619 | |
| 620 def __getitem__(self, key): | |
| 621 for row in self._querybykey('SELECT hash', key): | |
| 622 return bytes(row[0]) | |
| 623 raise KeyError(key) | |
| 624 | |
| 625 def __iter__(self): | |
| 626 if not self._allowiter: | |
| 627 raise NotImplementedError( | |
| 628 'SqliteRevMap.__iter__ is not implemented intentionally ' + | |
| 629 'to avoid performance issues') | |
| 630 # collect result to avoid nested transaction issues | |
| 631 rows = [] | |
| 632 for row in self._query('SELECT rev, branch FROM revmap'): | |
| 633 rows.append((row[0], row[1] or None)) | |
| 634 return iter(rows) | |
| 635 | |
| 636 def __len__(self): | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
637 # rowcount is faster than "SELECT COUNT(1)". the latter is not O(1) |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
638 return self.rowcount |
| 1467 | 639 |
| 640 def __setitem__(self, key, binha): | |
| 641 revnum, branch = key | |
| 642 with self._transaction(): | |
| 643 self._insert([(revnum, branch, binha)]) | |
| 644 if revnum < self.firstpulled or not self.firstpulled: | |
| 645 self.firstpulled = revnum | |
| 646 if revnum > self.lastpulled or not self.lastpulled: | |
| 647 self.lastpulled = revnum | |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
648 if self._hashescache: |
|
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
649 self._hashescache[binha] = key |
| 1467 | 650 |
| 651 def __delitem__(self, key): | |
| 652 for row in self._querybykey('DELETE', key): | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
653 if self.rowcount > 0: |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
654 self.rowcount -= 1 |
| 1467 | 655 return |
|
1550
67b28d657f62
sqliterevmap: break ".hashes()" cycle in a safer way
Jun Wu <quark@fb.com>
parents:
1518
diff
changeset
|
656 # For performance reason, self._hashescache is not updated |
| 1467 | 657 raise KeyError(key) |
| 658 | |
| 659 @contextlib.contextmanager | |
| 660 def _transaction(self, mode='IMMEDIATE'): | |
| 661 if self._db is None: | |
| 662 self._opendb() | |
| 663 with self._db as db: | |
|
1490
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
664 # wait indefinitely for database lock |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
665 while True: |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
666 try: |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
667 db.execute('BEGIN %s' % mode) |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
668 break |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
669 except sqlite3.OperationalError as ex: |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
670 if str(ex) != 'database is locked': |
|
bc73b80baf98
SqliteRevMap: wait indefinitely for database lock
Jun Wu <quark@fb.com>
parents:
1478
diff
changeset
|
671 raise |
| 1467 | 672 yield db |
| 673 | |
| 674 def _query(self, sql, params=()): | |
| 675 with self._transaction() as db: | |
| 676 cur = db.execute(sql, params) | |
| 677 try: | |
| 678 for row in cur: | |
| 679 yield row | |
| 680 finally: | |
| 681 cur.close() | |
| 682 | |
| 683 def _querybykey(self, prefix, key): | |
| 684 revnum, branch = key | |
| 685 return self._query( | |
| 686 '%s FROM revmap WHERE rev=? AND branch=?' | |
| 687 % prefix, (revnum, branch or '')) | |
| 688 | |
| 689 def _insert(self, rows): | |
| 690 # convert to a safe type so '\0' does not truncate the blob | |
| 691 if rows and type(rows[0][-1]) is not self.sqlblobtype: | |
| 692 rows = [(r, b, self.sqlblobtype(h)) for r, b, h in rows] | |
| 693 self._db.executemany( | |
| 694 'INSERT OR REPLACE INTO revmap (rev, branch, hash) ' + | |
| 695 'VALUES (?, ?, ?)', rows) | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
696 # If REPLACE happens, rowcount can be wrong. But it is only used to |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
697 # calculate how many revisions pulled, and during pull we don't |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
698 # replace rows. So it is fine. |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
699 self.rowcount += len(rows) |
| 1467 | 700 |
| 701 def _opendb(self): | |
| 702 '''Open the database and make sure the table is created on demand.''' | |
| 703 version = None | |
| 704 try: | |
| 705 version = int(open(self._filepath).read(2)) | |
| 706 except (ValueError, IOError): | |
| 707 pass | |
| 708 if version and version not in [RevMap.VERSION, self.VERSION]: | |
| 709 raise error.Abort('revmap too new -- please upgrade') | |
| 710 | |
| 711 if self._db: | |
| 712 self._db.close() | |
| 713 | |
| 714 # if version mismatch, the database is considered invalid | |
| 715 if version != self.VERSION: | |
| 716 hgutil.unlinkpath(self._dbpath, ignoremissing=True) | |
| 717 | |
| 718 self._db = sqlite3.connect(self._dbpath) | |
| 719 self._db.text_factory = bytes | |
| 720 | |
|
1470
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
721 # cache size affects random accessing (e.g. index building) |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
722 # performance greatly. default is 2MB (2000 KB), we want to have |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
723 # a big enough cache that can hold the entire map. |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
724 cachesize = 2000 |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
725 for path, ratio in [(self._filepath, 1.7), (self._dbpath, 1)]: |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
726 if os.path.exists(path): |
|
b6e2bc962536
maps: increase sqlite cache size automatically
Jun Wu <quark@fb.com>
parents:
1469
diff
changeset
|
727 cachesize += os.stat(path).st_size * ratio // 1000 |
|
1478
797c7b58a735
maps: add a config option to tweak sqlite
Jun Wu <quark@fb.com>
parents:
1477
diff
changeset
|
728 |
| 1467 | 729 # disable auto-commit. everything is inside a transaction |
| 730 self._db.isolation_level = 'DEFERRED' | |
| 731 | |
| 732 with self._transaction('EXCLUSIVE'): | |
|
1518
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
733 self._db.execute('PRAGMA cache_size=%d' % (-cachesize)) |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
734 |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
735 # PRAGMA statements provided by the user |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
736 for pragma in (self._sqlitepragmas or []): |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
737 # drop malicious ones |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
738 if re.match(r'\A\w+=\w+\Z', pragma): |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
739 self._db.execute('PRAGMA %s' % pragma) |
|
09476d758b59
maps: handle sqlite lock error triggered by PRAGMA statements
Jun Wu <quark@fb.com>
parents:
1490
diff
changeset
|
740 |
| 1467 | 741 map(self._db.execute, self.TABLESCHEMA) |
| 742 if version == RevMap.VERSION: | |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
743 self.rowcount = 0 |
| 1467 | 744 self._importrevmapv1() |
|
1475
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
745 elif not self.rowcount: |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
746 self.rowcount = self._db.execute( |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
747 'SELECT COUNT(1) FROM revmap').fetchone()[0] |
|
ea4d6142c6d9
maps: do not ask sqlite for row count
Jun Wu <quark@fb.com>
parents:
1472
diff
changeset
|
748 |
| 1467 | 749 # "bulk insert; then create index" is about 2.4x as fast as |
| 750 # "create index; then bulk insert" on a large repo | |
| 751 map(self._db.execute, self.INDEXSCHEMA) | |
| 752 | |
| 753 # write a dummy rev map file with just the revision number | |
| 754 if version != self.VERSION: | |
| 755 f = open(self._filepath, 'w') | |
| 756 f.write('%s\n' % self.VERSION) | |
| 757 f.close() | |
| 758 | |
|
1476
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
759 def _updatefirstlastpulled(self): |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
760 sql = 'SELECT rev FROM revmap ORDER BY rev %s LIMIT 1' |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
761 for row in self._query(sql % 'ASC'): |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
762 self.firstpulled = row[0] |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
763 for row in self._query(sql % 'DESC'): |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
764 if row[0] > self.lastpulled: |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
765 self.lastpulled = row[0] |
|
581f72f9478b
maps: do not ask sqlite for min(rev), max(rev) together
Jun Wu <quark@fb.com>
parents:
1475
diff
changeset
|
766 |
| 1467 | 767 @util.gcdisable |
| 768 def _importrevmapv1(self): | |
| 769 with open(self._filepath, 'r') as f: | |
| 770 # 1st line is version | |
| 771 assert(int(f.readline())) == RevMap.VERSION | |
| 772 data = {} | |
| 773 for line in f: | |
| 774 revnum, ha, branch = line[:-1].split(' ', 2) | |
| 775 # ignore malicious lines | |
| 776 if len(ha) != 40: | |
| 777 continue | |
| 778 data[revnum, branch or None] = bin(ha) | |
| 779 self._insert([(r, b, h) for (r, b), h in data.iteritems()]) | |
| 780 | |
|
1469
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
781 @util.gcdisable |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
782 def exportrevmapv1(self, path): |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
783 with open(path, 'w') as f: |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
784 f.write('%s\n' % RevMap.VERSION) |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
785 for row in self._query('SELECT rev, branch, hash FROM revmap'): |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
786 rev, br, ha = row |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
787 f.write('%s %s %s\n' % (rev, hex(ha), br)) |
|
7bb2c6ca4d24
maps: implement migration from SqliteRevMap to RevMap
Jun Wu <quark@fb.com>
parents:
1468
diff
changeset
|
788 |
| 1467 | 789 |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
790 class FileMap(object): |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
791 |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
792 VERSION = 1 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
793 |
|
1447
a6fa4f3aa826
FileMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1446
diff
changeset
|
794 def __init__(self, ui, filepath): |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
795 '''Initialise a new FileMap. |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
796 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
797 The ui argument is used to print diagnostic messages. |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
798 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
799 The path argument is the location of the backing store, |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
800 typically .hg/svn/filemap. |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
801 ''' |
|
1447
a6fa4f3aa826
FileMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1446
diff
changeset
|
802 self._filename = filepath |
|
a6fa4f3aa826
FileMap: no longer take a meta
Augie Fackler <raf@durin42.com>
parents:
1446
diff
changeset
|
803 self._ui = ui |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
804 self.include = {} |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
805 self.exclude = {} |
|
1437
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
806 if os.path.isfile(self._filename): |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
807 self._load() |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
808 else: |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
809 self._write() |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
810 |
|
1214
2c793092862b
maps: load commandline filemap in __init__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1213
diff
changeset
|
811 # append file mapping specified from the commandline |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
812 clmap = util.configpath(self._ui, 'filemap') |
|
1214
2c793092862b
maps: load commandline filemap in __init__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1213
diff
changeset
|
813 if clmap: |
|
2c793092862b
maps: load commandline filemap in __init__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1213
diff
changeset
|
814 self.load(clmap) |
|
2c793092862b
maps: load commandline filemap in __init__
Sean Farley <sean.michael.farley@gmail.com>
parents:
1213
diff
changeset
|
815 |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
816 def _rpairs(self, name): |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
817 e = len(name) |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
818 while e != -1: |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
819 yield name[:e], name[e+1:] |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
820 e = name.rfind('/', 0, e) |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
821 yield '.', name |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
822 |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
823 def check(self, m, path): |
|
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
824 m = getattr(self, m) |
|
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
825 for pre, _suf in self._rpairs(path): |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
826 if pre in m: |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
827 return m[pre] |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
828 return -1 |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
829 |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
830 def __contains__(self, path): |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
831 if not len(path): |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
832 return True |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
833 if len(self.include): |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
834 inc = self.check('include', path) |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
835 elif not len(self.exclude): |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
836 return True |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
837 else: |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
838 inc = 0 |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
839 if len(self.exclude): |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
840 exc = self.check('exclude', path) |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
841 else: |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
842 exc = -1 |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
843 # respect rule order: newer rules override older |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
844 return inc > exc |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
845 |
|
822
033b86e0f56d
stupid/filemap: disable this since it doesn't currently work
Augie Fackler <durin42@gmail.com>
parents:
821
diff
changeset
|
846 # Needed so empty filemaps are false |
|
033b86e0f56d
stupid/filemap: disable this since it doesn't currently work
Augie Fackler <durin42@gmail.com>
parents:
821
diff
changeset
|
847 def __len__(self): |
|
033b86e0f56d
stupid/filemap: disable this since it doesn't currently work
Augie Fackler <durin42@gmail.com>
parents:
821
diff
changeset
|
848 return len(self.include) + len(self.exclude) |
|
033b86e0f56d
stupid/filemap: disable this since it doesn't currently work
Augie Fackler <durin42@gmail.com>
parents:
821
diff
changeset
|
849 |
|
826
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
850 def add(self, fn, m, path): |
|
8794302f3614
maps: s/hash/ha/ and s/map/m/ to avoid hiding Python builtins
Yonggang Luo <luoyonggang@gmail.com>
parents:
822
diff
changeset
|
851 mapping = getattr(self, m) |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
852 if path in mapping: |
|
593
eb16630bceb1
maps: fix a % formatting bug
Augie Fackler <durin42@gmail.com>
parents:
579
diff
changeset
|
853 msg = 'duplicate %s entry in %s: "%s"\n' |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
854 self._ui.status(msg % (m, fn, path)) |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
855 return |
|
956
24fbba02cb8f
maps: fix filemap loading --verbose message
Patrick Mezard <patrick@mezard.eu>
parents:
891
diff
changeset
|
856 bits = m.rstrip('e'), path |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
857 self._ui.debug('%sing %s\n' % bits) |
|
847
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
858 # respect rule order |
|
0de18c5c2e35
Respect filemap rule order (rules that come first are overridden by rules that come later)
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
846
diff
changeset
|
859 mapping[path] = len(self) |
|
1437
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
860 if fn != self._filename: |
|
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
861 with open(self._filename, 'a') as f: |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
862 f.write(m + ' ' + path + '\n') |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
863 |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
864 def load(self, fn): |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
865 self._ui.debug('reading file map from %s\n' % fn) |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
866 with open(fn, 'r') as f: |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
867 self.load_fd(f, fn) |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
868 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
869 def load_fd(self, f, fn): |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
870 for line in f: |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
871 if line.strip() == '' or line.strip()[0] == '#': |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
872 continue |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
873 try: |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
874 cmd, path = line.split(' ', 1) |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
875 cmd = cmd.strip() |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
876 path = path.strip() |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
877 if cmd in ('include', 'exclude'): |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
878 self.add(fn, cmd, path) |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
879 continue |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
880 self._ui.warn('unknown filemap command %s\n' % cmd) |
|
409
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
881 except IndexError: |
|
d4615986e1db
extract the filemap support into a separate class
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
408
diff
changeset
|
882 msg = 'ignoring bad line in filemap %s: %s\n' |
|
1428
da272633997f
maps: store a direct reference to ui
Augie Fackler <raf@durin42.com>
parents:
1427
diff
changeset
|
883 self._ui.warn(msg % (fn, line.rstrip())) |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
884 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
885 def _load(self): |
|
1437
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
886 self._ui.debug('reading in-repo file map from %s\n' % self._filename) |
|
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
887 with open(self._filename) as f: |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
888 ver = int(f.readline()) |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
889 if ver != self.VERSION: |
|
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
890 raise hgutil.Abort('filemap too new -- please upgrade') |
|
1437
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
891 self.load_fd(f, self._filename) |
|
846
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
892 |
|
7ca3d1b08d67
Save filemap into .hg/svn/filemap just like other maps
Vitaliy Filippov <vitalif@yourcmc.ru>
parents:
829
diff
changeset
|
893 def _write(self): |
|
1437
43df01d36f22
FileMap: store filename locally
Augie Fackler <raf@durin42.com>
parents:
1435
diff
changeset
|
894 with open(self._filename, 'w') as f: |
|
1435
18a961672a72
maps: switch many file opens to using the with statement
Augie Fackler <raf@durin42.com>
parents:
1434
diff
changeset
|
895 f.write('%s\n' % self.VERSION) |
|
574
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
896 |
|
1388
130ced9e371d
maps: make branch map inherit from base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1387
diff
changeset
|
897 class BranchMap(BaseMap): |
|
574
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
898 '''Facility for controlled renaming of branch names. Example: |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
899 |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
900 oldname = newname |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
901 other = default |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
902 |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
903 All changes on the oldname branch will now be on the newname branch; all |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
904 changes on other will now be on default (have no branch name set). |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
905 ''' |
|
8e025a6f0db4
add basic branchmap functionality, to rename branches
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
573
diff
changeset
|
906 |
|
1391
7a866bca15de
maps: make tag map inherit from base map
Sean Farley <sean.michael.farley@gmail.com>
parents:
1390
diff
changeset
|
907 class TagMap(BaseMap): |
| 729 | 908 '''Facility for controlled renaming of tags. Example: |
| 909 | |
| 910 oldname = newname | |
| 911 other = | |
| 912 | |
|
809
ab372e38fb6c
maps: clean up whitespace
Augie Fackler <durin42@gmail.com>
parents:
742
diff
changeset
|
913 The oldname tag from SVN will be represented as newname in the hg tags; |
|
ab372e38fb6c
maps: clean up whitespace
Augie Fackler <durin42@gmail.com>
parents:
742
diff
changeset
|
914 the other tag will not be reflected in the hg repository. |
| 729 | 915 ''' |
