Show More
@@ -0,0 +1,115 b'' | |||||
|
1 | # demandimport.py - global demand-loading of modules for Mercurial | |||
|
2 | # | |||
|
3 | # Copyright 2006 Matt Mackall <mpm@selenic.com> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms | |||
|
6 | # of the GNU General Public License, incorporated herein by reference. | |||
|
7 | ||||
|
8 | ''' | |||
|
9 | demandimport - automatic demandloading of modules | |||
|
10 | ||||
|
11 | To enable this module, do: | |||
|
12 | ||||
|
13 | import demandimport; demandimport.enable() | |||
|
14 | ||||
|
15 | Imports of the following forms will be demand-loaded: | |||
|
16 | ||||
|
17 | import a, b.c | |||
|
18 | import a.b as c | |||
|
19 | from a import b,c # a will be loaded immediately | |||
|
20 | ||||
|
21 | These imports will not be delayed: | |||
|
22 | ||||
|
23 | from a import * | |||
|
24 | b = __import__(a) | |||
|
25 | ''' | |||
|
26 | ||||
|
27 | _origimport = __import__ | |||
|
28 | ||||
|
29 | class _demandmod(object): | |||
|
30 | """module demand-loader and proxy""" | |||
|
31 | def __init__(self, name, globals, locals): | |||
|
32 | if '.' in name: | |||
|
33 | head, rest = name.split('.', 1) | |||
|
34 | after = [rest] | |||
|
35 | else: | |||
|
36 | head = name | |||
|
37 | after = [] | |||
|
38 | object.__setattr__(self, "_data", (head, globals, locals, after)) | |||
|
39 | object.__setattr__(self, "_module", None) | |||
|
40 | def _extend(self, name): | |||
|
41 | """add to the list of submodules to load""" | |||
|
42 | self._data[3].append(name) | |||
|
43 | def _load(self): | |||
|
44 | if not self._module: | |||
|
45 | head, globals, locals, after = self._data | |||
|
46 | mod = _origimport(head, globals, locals) | |||
|
47 | # load submodules | |||
|
48 | def subload(mod, p): | |||
|
49 | h, t = p, None | |||
|
50 | if '.' in p: | |||
|
51 | h, t = p.split('.', 1) | |||
|
52 | if not hasattr(mod, h): | |||
|
53 | setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__)) | |||
|
54 | elif t: | |||
|
55 | subload(getattr(mod, h), t) | |||
|
56 | ||||
|
57 | for x in after: | |||
|
58 | subload(mod, x) | |||
|
59 | ||||
|
60 | # are we in the locals dictionary still? | |||
|
61 | if locals and locals.get(head) == self: | |||
|
62 | locals[head] = mod | |||
|
63 | object.__setattr__(self, "_module", mod) | |||
|
64 | def __repr__(self): | |||
|
65 | return "<unloaded module '%s'>" % self._data[0] | |||
|
66 | def __call__(self, *args, **kwargs): | |||
|
67 | raise TypeError("'unloaded module' object is not callable") | |||
|
68 | def __getattribute__(self, attr): | |||
|
69 | if attr in ('_data', '_extend', '_load', '_module'): | |||
|
70 | return object.__getattribute__(self, attr) | |||
|
71 | self._load() | |||
|
72 | return getattr(self._module, attr) | |||
|
73 | def __setattr__(self, attr, val): | |||
|
74 | self._load() | |||
|
75 | setattr(self._module, attr, val) | |||
|
76 | ||||
|
77 | def _demandimport(name, globals=None, locals=None, fromlist=None): | |||
|
78 | if not locals or name in ignore or fromlist == ('*',): | |||
|
79 | # these cases we can't really delay | |||
|
80 | return _origimport(name, globals, locals, fromlist) | |||
|
81 | elif not fromlist: | |||
|
82 | # import a [as b] | |||
|
83 | if '.' in name: # a.b | |||
|
84 | base, rest = name.split('.', 1) | |||
|
85 | # email.__init__ loading email.mime | |||
|
86 | if globals and globals.get('__name__', None) == base: | |||
|
87 | return _origimport(name, globals, locals, fromlist) | |||
|
88 | # if a is already demand-loaded, add b to its submodule list | |||
|
89 | if base in locals: | |||
|
90 | if isinstance(locals[base], _demandmod): | |||
|
91 | locals[base]._extend(rest) | |||
|
92 | return locals[base] | |||
|
93 | return _demandmod(name, globals, locals) | |||
|
94 | else: | |||
|
95 | # from a import b,c,d | |||
|
96 | mod = _origimport(name, globals, locals) | |||
|
97 | # recurse down the module chain | |||
|
98 | for comp in name.split('.')[1:]: | |||
|
99 | mod = getattr(mod, comp) | |||
|
100 | for x in fromlist: | |||
|
101 | # set requested submodules for demand load | |||
|
102 | if not(hasattr(mod, x)): | |||
|
103 | setattr(mod, x, _demandmod(x, mod.__dict__, mod.__dict__)) | |||
|
104 | return mod | |||
|
105 | ||||
|
106 | ignore = ['_hashlib', 'fcntl', 'win32com.gen_py'] | |||
|
107 | ||||
|
108 | def enable(): | |||
|
109 | "enable global demand-loading of modules" | |||
|
110 | __builtins__["__import__"] = _demandimport | |||
|
111 | ||||
|
112 | def disable(): | |||
|
113 | "disable global demand-loading of modules" | |||
|
114 | __builtins__["__import__"] = _origimport | |||
|
115 |
@@ -0,0 +1,13 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | hg init test | |||
|
4 | cd test | |||
|
5 | mkdir da | |||
|
6 | echo foo > da/foo | |||
|
7 | echo foo > foo | |||
|
8 | hg ci -Ambase -d '0 0' | |||
|
9 | hg serve -p 20060 -d --pid-file=hg.pid | |||
|
10 | echo % manifest | |||
|
11 | ("$TESTDIR/get-with-headers.py" localhost:20060 '/file/tip/?style=raw') | |||
|
12 | ("$TESTDIR/get-with-headers.py" localhost:20060 '/file/tip/da?style=raw') | |||
|
13 | kill `cat hg.pid` |
@@ -0,0 +1,16 b'' | |||||
|
1 | adding da/foo | |||
|
2 | adding foo | |||
|
3 | % manifest | |||
|
4 | 200 Script output follows | |||
|
5 | ||||
|
6 | ||||
|
7 | drwxr-xr-x da | |||
|
8 | -rw-r--r-- 4 foo | |||
|
9 | ||||
|
10 | ||||
|
11 | 200 Script output follows | |||
|
12 | ||||
|
13 | ||||
|
14 | -rw-r--r-- 4 foo | |||
|
15 | ||||
|
16 |
@@ -67,10 +67,10 b' dist-notests:\tdoc MANIFEST' | |||||
67 | TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py -q sdist |
|
67 | TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py -q sdist | |
68 |
|
68 | |||
69 | tests: |
|
69 | tests: | |
70 | cd tests && $(PYTHON) run-tests.py |
|
70 | cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) | |
71 |
|
71 | |||
72 | test-%: |
|
72 | test-%: | |
73 | cd tests && $(PYTHON) run-tests.py $@ |
|
73 | cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) $@ | |
74 |
|
74 | |||
75 |
|
75 | |||
76 | .PHONY: help all local build doc clean install install-bin install-doc \ |
|
76 | .PHONY: help all local build doc clean install install-bin install-doc \ |
@@ -1,99 +1,10 b'' | |||||
1 | MERCURIAL QUICK-START |
|
1 | Basic install: | |
2 |
|
||||
3 | Setting up Mercurial: |
|
|||
4 |
|
||||
5 | Note: some distributions fails to include bits of distutils by |
|
|||
6 | default, you'll need python-dev to install. You'll also need a C |
|
|||
7 | compiler and a 3-way merge tool like merge, tkdiff, or kdiff3. |
|
|||
8 |
|
||||
9 | First, unpack the source: |
|
|||
10 |
|
||||
11 | $ tar xvzf mercurial-<ver>.tar.gz |
|
|||
12 | $ cd mercurial-<ver> |
|
|||
13 |
|
||||
14 | When installing, change python to python2.3 or python2.4 if 2.2 is the |
|
|||
15 | default on your system. |
|
|||
16 |
|
||||
17 | To install system-wide: |
|
|||
18 |
|
||||
19 | $ python setup.py install --force |
|
|||
20 |
|
||||
21 | To install in your home directory (~/bin and ~/lib, actually), run: |
|
|||
22 |
|
||||
23 | $ python setup.py install --home=${HOME} --force |
|
|||
24 | $ export PYTHONPATH=${HOME}/lib/python # (or lib64/ on some systems) |
|
|||
25 | $ export PATH=${HOME}/bin:$PATH # add these to your .bashrc |
|
|||
26 |
|
||||
27 | And finally: |
|
|||
28 |
|
||||
29 | $ hg debuginstall # run some basic tests |
|
|||
30 | $ hg # show help |
|
|||
31 |
|
||||
32 | If you get complaints about missing modules, you probably haven't set |
|
|||
33 | PYTHONPATH correctly. |
|
|||
34 |
|
||||
35 | Setting up a Mercurial project: |
|
|||
36 |
|
||||
37 | $ hg init project # creates project directory |
|
|||
38 | $ cd project |
|
|||
39 | # copy files in, edit them |
|
|||
40 | $ hg add # add all unknown files |
|
|||
41 | $ hg commit # commit all changes, edit changelog entry |
|
|||
42 |
|
||||
43 | Mercurial will look for a file named .hgignore in the root of your |
|
|||
44 | repository which contains a set of regular expressions to ignore in |
|
|||
45 | file paths. |
|
|||
46 |
|
||||
47 | Branching and merging: |
|
|||
48 |
|
2 | |||
49 | $ hg clone project project-work # create a new branch |
|
3 | $ make # see install targets | |
50 | $ cd project-work |
|
4 | $ make install # do a system-wide install | |
51 | $ <make changes> |
|
5 | $ hg debuginstall # sanity-check setup | |
52 | $ hg commit |
|
6 | $ hg # see help | |
53 | $ cd ../project |
|
|||
54 | $ hg pull ../project-work # pull changesets from project-work |
|
|||
55 | $ hg merge # merge the new tip from project-work into |
|
|||
56 | # our working directory |
|
|||
57 | $ hg commit # commit the result of the merge |
|
|||
58 |
|
||||
59 | Importing patches: |
|
|||
60 |
|
||||
61 | Simple: |
|
|||
62 | $ patch < ../p/foo.patch |
|
|||
63 | $ hg commit -A |
|
|||
64 |
|
||||
65 | Fast: |
|
|||
66 | $ cat ../p/patchlist | xargs hg import -p1 -b ../p |
|
|||
67 |
|
||||
68 | Exporting a patch: |
|
|||
69 |
|
||||
70 | (make changes) |
|
|||
71 | $ hg commit |
|
|||
72 | $ hg export tip > foo.patch # export latest change |
|
|||
73 |
|
7 | |||
74 | Network support: |
|
8 | See http://www.selenic.com/mercurial/ for detailed installation | |
75 |
|
9 | instructions, platform-specific notes, and Mercurial user information. | ||
76 | # pull from the primary Mercurial repo |
|
|||
77 | foo$ hg clone http://selenic.com/hg/ |
|
|||
78 | foo$ cd hg |
|
|||
79 |
|
||||
80 | # make your current repo available via http://server:8000/ |
|
|||
81 | foo$ hg serve |
|
|||
82 |
|
||||
83 | # pushing and pulling changes to/from a remote repo with SSH |
|
|||
84 | foo$ hg push ssh://user@example.com/my/repository |
|
|||
85 | foo$ hg pull ssh://user@example.com//home/somebody/his/repository |
|
|||
86 |
|
10 | |||
87 | # merge changes from a remote machine (e.g. running 'hg serve') |
|
|||
88 | bar$ hg pull http://foo:8000/ |
|
|||
89 | bar$ hg merge # merge changes into your working directory |
|
|||
90 | bar$ hg commit # commit merge in to your local repository |
|
|||
91 |
|
||||
92 | # Set up a CGI server on your webserver |
|
|||
93 | foo$ cp hgweb.cgi ~/public_html/hg/index.cgi |
|
|||
94 | foo$ emacs ~/public_html/hg/index.cgi # adjust the defaults |
|
|||
95 |
|
||||
96 | For more info: |
|
|||
97 |
|
||||
98 | Documentation in doc/ |
|
|||
99 | Mercurial website at http://selenic.com/mercurial |
|
@@ -145,6 +145,7 b' shopt -s extglob' | |||||
145 | # global options |
|
145 | # global options | |
146 | case "$prev" in |
|
146 | case "$prev" in | |
147 | -R|--repository) |
|
147 | -R|--repository) | |
|
148 | _hg_paths | |||
148 | _hg_repos |
|
149 | _hg_repos | |
149 | return |
|
150 | return | |
150 | ;; |
|
151 | ;; | |
@@ -477,3 +478,25 b' complete -o bashdefault -o default -F _h' | |||||
477 | { |
|
478 | { | |
478 | _hg_tags |
|
479 | _hg_tags | |
479 | } |
|
480 | } | |
|
481 | ||||
|
482 | ||||
|
483 | # transplant | |||
|
484 | _hg_cmd_transplant() | |||
|
485 | { | |||
|
486 | case "$prev" in | |||
|
487 | -s|--source) | |||
|
488 | _hg_paths | |||
|
489 | _hg_repos | |||
|
490 | return | |||
|
491 | ;; | |||
|
492 | --filter) | |||
|
493 | # standard filename completion | |||
|
494 | return | |||
|
495 | ;; | |||
|
496 | esac | |||
|
497 | ||||
|
498 | # all other transplant options values and command parameters are revisions | |||
|
499 | _hg_tags | |||
|
500 | return | |||
|
501 | } | |||
|
502 |
@@ -11,10 +11,9 b'' | |||||
11 | # |
|
11 | # | |
12 | # <alias email> <actual email> |
|
12 | # <alias email> <actual email> | |
13 |
|
13 | |||
14 | from mercurial.demandload import * |
|
14 | import sys | |
15 | from mercurial.i18n import gettext as _ |
|
15 | from mercurial.i18n import gettext as _ | |
16 | demandload(globals(), 'time sys signal os') |
|
16 | from mercurial import hg, mdiff, cmdutil, ui, util, templater, node | |
17 | demandload(globals(), 'mercurial:hg,mdiff,fancyopts,cmdutil,ui,util,templater,node') |
|
|||
18 |
|
17 | |||
19 | def __gather(ui, repo, node1, node2): |
|
18 | def __gather(ui, repo, node1, node2): | |
20 | def dirtywork(f, mmap1, mmap2): |
|
19 | def dirtywork(f, mmap1, mmap2): |
@@ -3,29 +3,49 b'' | |||||
3 | # This is a generalized framework for converting between SCM |
|
3 | # This is a generalized framework for converting between SCM | |
4 | # repository formats. |
|
4 | # repository formats. | |
5 | # |
|
5 | # | |
6 | # In its current form, it's hardcoded to convert incrementally between |
|
|||
7 | # git and Mercurial. |
|
|||
8 | # |
|
|||
9 | # To use, run: |
|
6 | # To use, run: | |
10 | # |
|
7 | # | |
11 |
# convert-repo < |
|
8 | # convert-repo <source> [<dest> [<mapfile>]] | |
12 | # |
|
9 | # | |
13 | # (don't forget to create the <hg-dir> repository beforehand) |
|
10 | # Currently accepted source formats: git, cvs | |
|
11 | # Currently accepted destination formats: hg | |||
14 | # |
|
12 | # | |
15 | # The <mapfile> is a simple text file that maps a git commit hash to |
|
13 | # If destination isn't given, a new Mercurial repo named <src>-hg will | |
16 | # the hash in Mercurial for that version, like so: |
|
14 | # be created. If <mapfile> isn't given, it will be put in a default | |
|
15 | # location (<dest>/.hg/shamap by default) | |||
17 | # |
|
16 | # | |
18 | # <git hash> <mercurial hash> |
|
17 | # The <mapfile> is a simple text file that maps each source commit ID to | |
|
18 | # the destination ID for that revision, like so: | |||
|
19 | # | |||
|
20 | # <source ID> <destination ID> | |||
19 | # |
|
21 | # | |
20 | # If the file doesn't exist, it's automatically created. It's updated |
|
22 | # If the file doesn't exist, it's automatically created. It's updated | |
21 | # on each commit copied, so convert-repo can be interrupted and can |
|
23 | # on each commit copied, so convert-repo can be interrupted and can | |
22 | # be run repeatedly to copy new commits. |
|
24 | # be run repeatedly to copy new commits. | |
23 |
|
25 | |||
24 | import sys, os, zlib, sha, time |
|
26 | import sys, os, zlib, sha, time, re, locale | |
25 |
|
||||
26 | os.environ["HGENCODING"] = "utf-8" |
|
27 | os.environ["HGENCODING"] = "utf-8" | |
|
28 | from mercurial import hg, ui, util, fancyopts | |||
27 |
|
29 | |||
28 | from mercurial import hg, ui, util |
|
30 | class Abort(Exception): pass | |
|
31 | class NoRepo(Exception): pass | |||
|
32 | ||||
|
33 | class commit: | |||
|
34 | def __init__(self, **parts): | |||
|
35 | for x in "author date desc parents".split(): | |||
|
36 | if not x in parts: | |||
|
37 | abort("commit missing field %s\n" % x) | |||
|
38 | self.__dict__.update(parts) | |||
|
39 | ||||
|
40 | quiet = 0 | |||
|
41 | def status(msg): | |||
|
42 | if not quiet: sys.stdout.write(str(msg)) | |||
|
43 | ||||
|
44 | def warn(msg): | |||
|
45 | sys.stderr.write(str(msg)) | |||
|
46 | ||||
|
47 | def abort(msg): | |||
|
48 | raise Abort(msg) | |||
29 |
|
49 | |||
30 | def recode(s): |
|
50 | def recode(s): | |
31 | try: |
|
51 | try: | |
@@ -36,9 +56,210 b' def recode(s):' | |||||
36 | except: |
|
56 | except: | |
37 | return s.decode("utf-8", "replace").encode("utf-8") |
|
57 | return s.decode("utf-8", "replace").encode("utf-8") | |
38 |
|
58 | |||
|
59 | # CVS conversion code inspired by hg-cvs-import and git-cvsimport | |||
|
60 | class convert_cvs: | |||
|
61 | def __init__(self, path): | |||
|
62 | self.path = path | |||
|
63 | cvs = os.path.join(path, "CVS") | |||
|
64 | if not os.path.exists(cvs): | |||
|
65 | raise NoRepo("couldn't open CVS repo %s" % path) | |||
|
66 | ||||
|
67 | self.changeset = {} | |||
|
68 | self.files = {} | |||
|
69 | self.tags = {} | |||
|
70 | self.lastbranch = {} | |||
|
71 | self.parent = {} | |||
|
72 | self.socket = None | |||
|
73 | self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1] | |||
|
74 | self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1] | |||
|
75 | self.encoding = locale.getpreferredencoding() | |||
|
76 | self._parse() | |||
|
77 | self._connect() | |||
|
78 | ||||
|
79 | def _parse(self): | |||
|
80 | if self.changeset: | |||
|
81 | return | |||
|
82 | ||||
|
83 | d = os.getcwd() | |||
|
84 | try: | |||
|
85 | os.chdir(self.path) | |||
|
86 | id = None | |||
|
87 | state = 0 | |||
|
88 | for l in os.popen("cvsps -A"): | |||
|
89 | if state == 0: # header | |||
|
90 | if l.startswith("PatchSet"): | |||
|
91 | id = l[9:-2] | |||
|
92 | elif l.startswith("Date"): | |||
|
93 | date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"]) | |||
|
94 | date = util.datestr(date) | |||
|
95 | elif l.startswith("Branch"): | |||
|
96 | branch = l[8:-1] | |||
|
97 | self.parent[id] = self.lastbranch.get(branch,'bad') | |||
|
98 | self.lastbranch[branch] = id | |||
|
99 | elif l.startswith("Ancestor branch"): | |||
|
100 | ancestor = l[17:-1] | |||
|
101 | self.parent[id] = self.lastbranch[ancestor] | |||
|
102 | elif l.startswith("Author"): | |||
|
103 | author = self.recode(l[8:-1]) | |||
|
104 | elif l.startswith("Tag: "): | |||
|
105 | t = l[5:-1] | |||
|
106 | if t != "(none) ": | |||
|
107 | self.tags[t] = id | |||
|
108 | elif l.startswith("Log:"): | |||
|
109 | state = 1 | |||
|
110 | log = "" | |||
|
111 | elif state == 1: # log | |||
|
112 | if l == "Members: \n": | |||
|
113 | files = {} | |||
|
114 | log = self.recode(log[:-1]) | |||
|
115 | if log.isspace(): | |||
|
116 | log = "*** empty log message ***\n" | |||
|
117 | state = 2 | |||
|
118 | else: | |||
|
119 | log += l | |||
|
120 | elif state == 2: | |||
|
121 | if l == "\n": # | |||
|
122 | state = 0 | |||
|
123 | p = [self.parent[id]] | |||
|
124 | if id == "1": | |||
|
125 | p = [] | |||
|
126 | c = commit(author=author, date=date, parents=p, | |||
|
127 | desc=log, branch=branch) | |||
|
128 | self.changeset[id] = c | |||
|
129 | self.files[id] = files | |||
|
130 | else: | |||
|
131 | file,rev = l[1:-2].rsplit(':',1) | |||
|
132 | rev = rev.split("->")[1] | |||
|
133 | files[file] = rev | |||
|
134 | ||||
|
135 | self.heads = self.lastbranch.values() | |||
|
136 | finally: | |||
|
137 | os.chdir(d) | |||
|
138 | ||||
|
139 | def _connect(self): | |||
|
140 | root = self.cvsroot | |||
|
141 | local = False | |||
|
142 | user, host = None, None | |||
|
143 | cmd = ['cvs', 'server'] | |||
|
144 | ||||
|
145 | status("connecting to %s\n" % root) | |||
|
146 | ||||
|
147 | # only non-pserver for now | |||
|
148 | if root.startswith(":pserver"): | |||
|
149 | abort("can't handle pserver mode yet: %s\n" % root) | |||
|
150 | ||||
|
151 | if root.startswith(":local:"): | |||
|
152 | local = True | |||
|
153 | root = root[7:] | |||
|
154 | else: | |||
|
155 | # :ext:user@host/home/user/path/to/cvsroot | |||
|
156 | if root.startswith(":ext:"): | |||
|
157 | root = root[5:] | |||
|
158 | m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root) | |||
|
159 | if not m: | |||
|
160 | local = True | |||
|
161 | else: | |||
|
162 | local = False | |||
|
163 | user, host, root = m.group(1), m.group(2), m.group(3) | |||
|
164 | ||||
|
165 | if not local: | |||
|
166 | rsh = os.environ.get("CVS_RSH" or "rsh") | |||
|
167 | if user: | |||
|
168 | cmd = [rsh, '-l', user, host] + cmd | |||
|
169 | else: | |||
|
170 | cmd = [rsh, host] + cmd | |||
|
171 | ||||
|
172 | self.writep, self.readp = os.popen2(cmd) | |||
|
173 | self.realroot = root | |||
|
174 | ||||
|
175 | self.writep.write("Root %s\n" % root) | |||
|
176 | self.writep.write("Valid-responses ok error Valid-requests Mode" | |||
|
177 | " M Mbinary E Checked-in Created Updated" | |||
|
178 | " Merged Removed\n") | |||
|
179 | self.writep.write("valid-requests\n") | |||
|
180 | self.writep.flush() | |||
|
181 | r = self.readp.readline() | |||
|
182 | if not r.startswith("Valid-requests"): | |||
|
183 | abort("server sucks\n") | |||
|
184 | if "UseUnchanged" in r: | |||
|
185 | self.writep.write("UseUnchanged\n") | |||
|
186 | self.writep.flush() | |||
|
187 | r = self.readp.readline() | |||
|
188 | ||||
|
189 | def getheads(self): | |||
|
190 | return self.heads | |||
|
191 | ||||
|
192 | def _getfile(self, name, rev): | |||
|
193 | if rev.endswith("(DEAD)"): | |||
|
194 | raise IOError | |||
|
195 | ||||
|
196 | args = ("-N -P -kk -r %s --" % rev).split() | |||
|
197 | args.append(os.path.join(self.cvsrepo, name)) | |||
|
198 | for x in args: | |||
|
199 | self.writep.write("Argument %s\n" % x) | |||
|
200 | self.writep.write("Directory .\n%s\nco\n" % self.realroot) | |||
|
201 | self.writep.flush() | |||
|
202 | ||||
|
203 | data = "" | |||
|
204 | while 1: | |||
|
205 | line = self.readp.readline() | |||
|
206 | if line.startswith("Created ") or line.startswith("Updated "): | |||
|
207 | self.readp.readline() # path | |||
|
208 | self.readp.readline() # entries | |||
|
209 | mode = self.readp.readline()[:-1] | |||
|
210 | count = int(self.readp.readline()[:-1]) | |||
|
211 | data = self.readp.read(count) | |||
|
212 | elif line.startswith(" "): | |||
|
213 | data += line[1:] | |||
|
214 | elif line.startswith("M "): | |||
|
215 | pass | |||
|
216 | elif line.startswith("Mbinary "): | |||
|
217 | count = int(self.readp.readline()[:-1]) | |||
|
218 | data = self.readp.read(count) | |||
|
219 | else: | |||
|
220 | if line == "ok\n": | |||
|
221 | return (data, "x" in mode) | |||
|
222 | elif line.startswith("E "): | |||
|
223 | warn("cvs server: %s\n" % line[2:]) | |||
|
224 | elif line.startswith("Remove"): | |||
|
225 | l = self.readp.readline() | |||
|
226 | l = self.readp.readline() | |||
|
227 | if l != "ok\n": | |||
|
228 | abort("unknown CVS response: %s\n" % l) | |||
|
229 | else: | |||
|
230 | abort("unknown CVS response: %s\n" % line) | |||
|
231 | ||||
|
232 | def getfile(self, file, rev): | |||
|
233 | data, mode = self._getfile(file, rev) | |||
|
234 | self.modecache[(file, rev)] = mode | |||
|
235 | return data | |||
|
236 | ||||
|
237 | def getmode(self, file, rev): | |||
|
238 | return self.modecache[(file, rev)] | |||
|
239 | ||||
|
240 | def getchanges(self, rev): | |||
|
241 | self.modecache = {} | |||
|
242 | files = self.files[rev] | |||
|
243 | cl = files.items() | |||
|
244 | cl.sort() | |||
|
245 | return cl | |||
|
246 | ||||
|
247 | def recode(self, text): | |||
|
248 | return text.decode(self.encoding, "replace").encode("utf-8") | |||
|
249 | ||||
|
250 | def getcommit(self, rev): | |||
|
251 | return self.changeset[rev] | |||
|
252 | ||||
|
253 | def gettags(self): | |||
|
254 | return self.tags | |||
|
255 | ||||
39 | class convert_git: |
|
256 | class convert_git: | |
40 | def __init__(self, path): |
|
257 | def __init__(self, path): | |
|
258 | if os.path.isdir(path + "/.git"): | |||
|
259 | path += "/.git" | |||
41 | self.path = path |
|
260 | self.path = path | |
|
261 | if not os.path.exists(path + "/HEAD"): | |||
|
262 | raise NoRepo("couldn't open GIT repo %s" % path) | |||
42 |
|
263 | |||
43 | def getheads(self): |
|
264 | def getheads(self): | |
44 | fh = os.popen("GIT_DIR=%s git-rev-parse --verify HEAD" % self.path) |
|
265 | fh = os.popen("GIT_DIR=%s git-rev-parse --verify HEAD" % self.path) | |
@@ -52,7 +273,11 b' class convert_git:' | |||||
52 | def getfile(self, name, rev): |
|
273 | def getfile(self, name, rev): | |
53 | return self.catfile(rev, "blob") |
|
274 | return self.catfile(rev, "blob") | |
54 |
|
275 | |||
|
276 | def getmode(self, name, rev): | |||
|
277 | return self.modecache[(name, rev)] | |||
|
278 | ||||
55 | def getchanges(self, version): |
|
279 | def getchanges(self, version): | |
|
280 | self.modecache = {} | |||
56 | fh = os.popen("GIT_DIR=%s git-diff-tree --root -m -r %s" % (self.path, version)) |
|
281 | fh = os.popen("GIT_DIR=%s git-diff-tree --root -m -r %s" % (self.path, version)) | |
57 | changes = [] |
|
282 | changes = [] | |
58 | for l in fh: |
|
283 | for l in fh: | |
@@ -61,7 +286,8 b' class convert_git:' | |||||
61 | m = m.split() |
|
286 | m = m.split() | |
62 | h = m[3] |
|
287 | h = m[3] | |
63 | p = (m[1] == "100755") |
|
288 | p = (m[1] == "100755") | |
64 | changes.append((f, h, p)) |
|
289 | self.modecache[(f, h)] = p | |
|
290 | changes.append((f, h)) | |||
65 | return changes |
|
291 | return changes | |
66 |
|
292 | |||
67 | def getcommit(self, version): |
|
293 | def getcommit(self, version): | |
@@ -92,7 +318,9 b' class convert_git:' | |||||
92 | tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] |
|
318 | tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] | |
93 | tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) |
|
319 | tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) | |
94 | date = tm + " " + str(tz) |
|
320 | date = tm + " " + str(tz) | |
95 | return (parents, author, date, message) |
|
321 | ||
|
322 | c = commit(parents=parents, date=date, author=author, desc=message) | |||
|
323 | return c | |||
96 |
|
324 | |||
97 | def gettags(self): |
|
325 | def gettags(self): | |
98 | tags = {} |
|
326 | tags = {} | |
@@ -110,19 +338,23 b' class convert_mercurial:' | |||||
110 | def __init__(self, path): |
|
338 | def __init__(self, path): | |
111 | self.path = path |
|
339 | self.path = path | |
112 | u = ui.ui() |
|
340 | u = ui.ui() | |
113 | self.repo = hg.repository(u, path) |
|
341 | try: | |
|
342 | self.repo = hg.repository(u, path) | |||
|
343 | except: | |||
|
344 | raise NoRepo("could open hg repo %s" % path) | |||
|
345 | ||||
|
346 | def mapfile(self): | |||
|
347 | return os.path.join(self.path, ".hg", "shamap") | |||
114 |
|
348 | |||
115 | def getheads(self): |
|
349 | def getheads(self): | |
116 | h = self.repo.changelog.heads() |
|
350 | h = self.repo.changelog.heads() | |
117 | return [ hg.hex(x) for x in h ] |
|
351 | return [ hg.hex(x) for x in h ] | |
118 |
|
352 | |||
119 | def putfile(self, f, e, data): |
|
353 | def putfile(self, f, e, data): | |
120 |
self.repo.w |
|
354 | self.repo.wwrite(f, data, e and 'x' or '') | |
121 | if self.repo.dirstate.state(f) == '?': |
|
355 | if self.repo.dirstate.state(f) == '?': | |
122 | self.repo.dirstate.update([f], "a") |
|
356 | self.repo.dirstate.update([f], "a") | |
123 |
|
357 | |||
124 | util.set_exec(self.repo.wjoin(f), e) |
|
|||
125 |
|
||||
126 | def delfile(self, f): |
|
358 | def delfile(self, f): | |
127 | try: |
|
359 | try: | |
128 | os.unlink(self.repo.wjoin(f)) |
|
360 | os.unlink(self.repo.wjoin(f)) | |
@@ -130,7 +362,7 b' class convert_mercurial:' | |||||
130 | except: |
|
362 | except: | |
131 | pass |
|
363 | pass | |
132 |
|
364 | |||
133 |
def putcommit(self, files, parents, |
|
365 | def putcommit(self, files, parents, commit): | |
134 | seen = {} |
|
366 | seen = {} | |
135 | pl = [] |
|
367 | pl = [] | |
136 | for p in parents: |
|
368 | for p in parents: | |
@@ -143,11 +375,18 b' class convert_mercurial:' | |||||
143 | if len(parents) < 2: parents.append("0" * 40) |
|
375 | if len(parents) < 2: parents.append("0" * 40) | |
144 | p2 = parents.pop(0) |
|
376 | p2 = parents.pop(0) | |
145 |
|
377 | |||
|
378 | text = commit.desc | |||
|
379 | extra = {} | |||
|
380 | try: | |||
|
381 | extra["branch"] = commit.branch | |||
|
382 | except AttributeError: | |||
|
383 | pass | |||
|
384 | ||||
146 | while parents: |
|
385 | while parents: | |
147 | p1 = p2 |
|
386 | p1 = p2 | |
148 | p2 = parents.pop(0) |
|
387 | p2 = parents.pop(0) | |
149 |
self.repo.rawcommit(files, text, author, |
|
388 | a = self.repo.rawcommit(files, text, commit.author, commit.date, | |
150 | hg.bin(p1), hg.bin(p2)) |
|
389 | hg.bin(p1), hg.bin(p2), extra=extra) | |
151 | text = "(octopus merge fixup)\n" |
|
390 | text = "(octopus merge fixup)\n" | |
152 | p2 = hg.hex(self.repo.changelog.tip()) |
|
391 | p2 = hg.hex(self.repo.changelog.tip()) | |
153 |
|
392 | |||
@@ -170,7 +409,7 b' class convert_mercurial:' | |||||
170 | newlines.sort() |
|
409 | newlines.sort() | |
171 |
|
410 | |||
172 | if newlines != oldlines: |
|
411 | if newlines != oldlines: | |
173 |
|
|
412 | status("updating tags\n") | |
174 | f = self.repo.wfile(".hgtags", "w") |
|
413 | f = self.repo.wfile(".hgtags", "w") | |
175 | f.write("".join(newlines)) |
|
414 | f.write("".join(newlines)) | |
176 | f.close() |
|
415 | f.close() | |
@@ -180,11 +419,25 b' class convert_mercurial:' | |||||
180 | date, self.repo.changelog.tip(), hg.nullid) |
|
419 | date, self.repo.changelog.tip(), hg.nullid) | |
181 | return hg.hex(self.repo.changelog.tip()) |
|
420 | return hg.hex(self.repo.changelog.tip()) | |
182 |
|
421 | |||
|
422 | converters = [convert_cvs, convert_git, convert_mercurial] | |||
|
423 | ||||
|
424 | def converter(path): | |||
|
425 | if not os.path.isdir(path): | |||
|
426 | abort("%s: not a directory\n" % path) | |||
|
427 | for c in converters: | |||
|
428 | try: | |||
|
429 | return c(path) | |||
|
430 | except NoRepo: | |||
|
431 | pass | |||
|
432 | abort("%s: unknown repository type\n" % path) | |||
|
433 | ||||
183 | class convert: |
|
434 | class convert: | |
184 | def __init__(self, source, dest, mapfile): |
|
435 | def __init__(self, source, dest, mapfile, opts): | |
|
436 | ||||
185 | self.source = source |
|
437 | self.source = source | |
186 | self.dest = dest |
|
438 | self.dest = dest | |
187 | self.mapfile = mapfile |
|
439 | self.mapfile = mapfile | |
|
440 | self.opts = opts | |||
188 | self.commitcache = {} |
|
441 | self.commitcache = {} | |
189 |
|
442 | |||
190 | self.map = {} |
|
443 | self.map = {} | |
@@ -204,7 +457,7 b' class convert:' | |||||
204 | if n in known or n in self.map: continue |
|
457 | if n in known or n in self.map: continue | |
205 | known[n] = 1 |
|
458 | known[n] = 1 | |
206 | self.commitcache[n] = self.source.getcommit(n) |
|
459 | self.commitcache[n] = self.source.getcommit(n) | |
207 |
cp = self.commitcache[n] |
|
460 | cp = self.commitcache[n].parents | |
208 | for p in cp: |
|
461 | for p in cp: | |
209 | parents.setdefault(n, []).append(p) |
|
462 | parents.setdefault(n, []).append(p) | |
210 | visit.append(p) |
|
463 | visit.append(p) | |
@@ -247,42 +500,60 b' class convert:' | |||||
247 | if not dep: |
|
500 | if not dep: | |
248 | # all n's parents are in the list |
|
501 | # all n's parents are in the list | |
249 | removed[n] = 1 |
|
502 | removed[n] = 1 | |
250 |
|
|
503 | if n not in self.map: | |
|
504 | s.append(n) | |||
251 | if n in children: |
|
505 | if n in children: | |
252 | for c in children[n]: |
|
506 | for c in children[n]: | |
253 | visit.insert(0, c) |
|
507 | visit.insert(0, c) | |
254 |
|
508 | |||
|
509 | if opts.get('datesort'): | |||
|
510 | depth = {} | |||
|
511 | for n in s: | |||
|
512 | depth[n] = 0 | |||
|
513 | pl = [p for p in self.commitcache[n].parents if p not in self.map] | |||
|
514 | if pl: | |||
|
515 | depth[n] = max([depth[p] for p in pl]) + 1 | |||
|
516 | ||||
|
517 | s = [(depth[n], self.commitcache[n].date, n) for n in s] | |||
|
518 | s.sort() | |||
|
519 | s = [e[2] for e in s] | |||
|
520 | ||||
255 | return s |
|
521 | return s | |
256 |
|
522 | |||
257 | def copy(self, rev): |
|
523 | def copy(self, rev): | |
258 |
|
|
524 | c = self.commitcache[rev] | |
259 | files = self.source.getchanges(rev) |
|
525 | files = self.source.getchanges(rev) | |
260 |
|
526 | |||
261 |
for f,v |
|
527 | for f,v in files: | |
262 | try: |
|
528 | try: | |
263 | data = self.source.getfile(f, v) |
|
529 | data = self.source.getfile(f, v) | |
264 | except IOError, inst: |
|
530 | except IOError, inst: | |
265 | self.dest.delfile(f) |
|
531 | self.dest.delfile(f) | |
266 | else: |
|
532 | else: | |
|
533 | e = self.source.getmode(f, v) | |||
267 | self.dest.putfile(f, e, data) |
|
534 | self.dest.putfile(f, e, data) | |
268 |
|
535 | |||
269 | r = [self.map[v] for v in p] |
|
536 | r = [self.map[v] for v in c.parents] | |
270 |
f = [f for f,v |
|
537 | f = [f for f,v in files] | |
271 |
self.map[rev] = self.dest.putcommit(f, r, |
|
538 | self.map[rev] = self.dest.putcommit(f, r, c) | |
272 | file(self.mapfile, "a").write("%s %s\n" % (rev, self.map[rev])) |
|
539 | file(self.mapfile, "a").write("%s %s\n" % (rev, self.map[rev])) | |
273 |
|
540 | |||
274 | def convert(self): |
|
541 | def convert(self): | |
|
542 | status("scanning source...\n") | |||
275 | heads = self.source.getheads() |
|
543 | heads = self.source.getheads() | |
276 | parents = self.walktree(heads) |
|
544 | parents = self.walktree(heads) | |
|
545 | status("sorting...\n") | |||
277 | t = self.toposort(parents) |
|
546 | t = self.toposort(parents) | |
278 | t = [n for n in t if n not in self.map] |
|
|||
279 | num = len(t) |
|
547 | num = len(t) | |
280 | c = None |
|
548 | c = None | |
281 |
|
549 | |||
|
550 | status("converting...\n") | |||
282 | for c in t: |
|
551 | for c in t: | |
283 | num -= 1 |
|
552 | num -= 1 | |
284 |
desc = self.commitcache[c] |
|
553 | desc = self.commitcache[c].desc | |
285 |
|
|
554 | if "\n" in desc: | |
|
555 | desc = desc.splitlines()[0] | |||
|
556 | status("%d %s\n" % (num, desc)) | |||
286 | self.copy(c) |
|
557 | self.copy(c) | |
287 |
|
558 | |||
288 | tags = self.source.gettags() |
|
559 | tags = self.source.gettags() | |
@@ -299,9 +570,41 b' class convert:' | |||||
299 | if nrev: |
|
570 | if nrev: | |
300 | file(self.mapfile, "a").write("%s %s\n" % (c, nrev)) |
|
571 | file(self.mapfile, "a").write("%s %s\n" % (c, nrev)) | |
301 |
|
572 | |||
302 | gitpath, hgpath, mapfile = sys.argv[1:] |
|
573 | def command(src, dest=None, mapfile=None, **opts): | |
303 | if os.path.isdir(gitpath + "/.git"): |
|
574 | srcc = converter(src) | |
304 | gitpath += "/.git" |
|
575 | if not hasattr(srcc, "getcommit"): | |
|
576 | abort("%s: can't read from this repo type\n" % src) | |||
|
577 | ||||
|
578 | if not dest: | |||
|
579 | dest = src + "-hg" | |||
|
580 | status("assuming destination %s\n" % dest) | |||
|
581 | if not os.path.isdir(dest): | |||
|
582 | status("creating repository %s\n" % dest) | |||
|
583 | os.system("hg init " + dest) | |||
|
584 | destc = converter(dest) | |||
|
585 | if not hasattr(destc, "putcommit"): | |||
|
586 | abort("%s: can't write to this repo type\n" % src) | |||
305 |
|
587 | |||
306 | c = convert(convert_git(gitpath), convert_mercurial(hgpath), mapfile) |
|
588 | if not mapfile: | |
307 | c.convert() |
|
589 | try: | |
|
590 | mapfile = destc.mapfile() | |||
|
591 | except: | |||
|
592 | mapfile = os.path.join(destc, "map") | |||
|
593 | ||||
|
594 | c = convert(srcc, destc, mapfile, opts) | |||
|
595 | c.convert() | |||
|
596 | ||||
|
597 | options = [('q', 'quiet', None, 'suppress output'), | |||
|
598 | ('', 'datesort', None, 'try to sort changesets by date')] | |||
|
599 | opts = {} | |||
|
600 | args = fancyopts.fancyopts(sys.argv[1:], options, opts) | |||
|
601 | ||||
|
602 | if opts['quiet']: | |||
|
603 | quiet = 1 | |||
|
604 | ||||
|
605 | try: | |||
|
606 | command(*args, **opts) | |||
|
607 | except Abort, inst: | |||
|
608 | warn(inst) | |||
|
609 | except KeyboardInterrupt: | |||
|
610 | status("interrupted\n") |
@@ -43,7 +43,9 b' proc getcommits {rargs} {' | |||||
43 | } |
|
43 | } | |
44 | if [catch { |
|
44 | if [catch { | |
45 | set parse_args [concat --default HEAD $revargs] |
|
45 | set parse_args [concat --default HEAD $revargs] | |
46 |
set parse |
|
46 | set parse_temp [eval exec hg debug-rev-parse $parse_args] | |
|
47 | regsub -all "\r\n" $parse_temp "\n" parse_temp | |||
|
48 | set parsed_args [split $parse_temp "\n"] | |||
47 | } err] { |
|
49 | } err] { | |
48 | # if git-rev-parse failed for some reason... |
|
50 | # if git-rev-parse failed for some reason... | |
49 | if {$rargs == {}} { |
|
51 | if {$rargs == {}} { | |
@@ -108,6 +110,7 b' to allow selection of commits to be disp' | |||||
108 | set leftover {} |
|
110 | set leftover {} | |
109 | } |
|
111 | } | |
110 | set start [expr {$i + 1}] |
|
112 | set start [expr {$i + 1}] | |
|
113 | regsub -all "\r\n" $cmit "\n" cmit | |||
111 | set j [string first "\n" $cmit] |
|
114 | set j [string first "\n" $cmit] | |
112 | set ok 0 |
|
115 | set ok 0 | |
113 | if {$j >= 0} { |
|
116 | if {$j >= 0} { | |
@@ -209,6 +212,7 b' proc parsecommit {id contents listed old' | |||||
209 | incr ncleft($p) |
|
212 | incr ncleft($p) | |
210 | } |
|
213 | } | |
211 | } |
|
214 | } | |
|
215 | regsub -all "\r\n" $contents "\n" contents | |||
212 | foreach line [split $contents "\n"] { |
|
216 | foreach line [split $contents "\n"] { | |
213 | if {$inhdr} { |
|
217 | if {$inhdr} { | |
214 | set line [split $line] |
|
218 | set line [split $line] | |
@@ -257,7 +261,8 b' proc readrefs {} {' | |||||
257 | global tagids idtags headids idheads tagcontents |
|
261 | global tagids idtags headids idheads tagcontents | |
258 |
|
262 | |||
259 | set tags [exec hg tags] |
|
263 | set tags [exec hg tags] | |
260 | set lines [split $tags '\n'] |
|
264 | regsub -all "\r\n" $tags "\n" tags | |
|
265 | set lines [split $tags "\n"] | |||
261 | foreach f $lines { |
|
266 | foreach f $lines { | |
262 | set f [regexp -all -inline {\S+} $f] |
|
267 | set f [regexp -all -inline {\S+} $f] | |
263 | set direct [lindex $f 0] |
|
268 | set direct [lindex $f 0] | |
@@ -2856,6 +2861,7 b' proc getblobdiffline {bdf ids} {' | |||||
2856 | if {$ids != $diffids || $bdf != $blobdifffd($ids)} { |
|
2861 | if {$ids != $diffids || $bdf != $blobdifffd($ids)} { | |
2857 | return |
|
2862 | return | |
2858 | } |
|
2863 | } | |
|
2864 | regsub -all "\r" $line "" line | |||
2859 | $ctext conf -state normal |
|
2865 | $ctext conf -state normal | |
2860 | if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} { |
|
2866 | if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} { | |
2861 | # start of a new file |
|
2867 | # start of a new file | |
@@ -2914,7 +2920,7 b' proc getblobdiffline {bdf ids} {' | |||||
2914 | } elseif {$diffinhdr || $x == "\\"} { |
|
2920 | } elseif {$diffinhdr || $x == "\\"} { | |
2915 | # e.g. "\ No newline at end of file" |
|
2921 | # e.g. "\ No newline at end of file" | |
2916 | $ctext insert end "$line\n" filesep |
|
2922 | $ctext insert end "$line\n" filesep | |
2917 | } else { |
|
2923 | } elseif {$line != ""} { | |
2918 | # Something else we don't recognize |
|
2924 | # Something else we don't recognize | |
2919 | if {$curdifftag != "Comments"} { |
|
2925 | if {$curdifftag != "Comments"} { | |
2920 | $ctext insert end "\n" |
|
2926 | $ctext insert end "\n" |
@@ -7,6 +7,5 b'' | |||||
7 | # This software may be used and distributed according to the terms |
|
7 | # This software may be used and distributed according to the terms | |
8 | # of the GNU General Public License, incorporated herein by reference. |
|
8 | # of the GNU General Public License, incorporated herein by reference. | |
9 |
|
9 | |||
10 |
|
|
10 | import mercurial.commands | |
11 |
|
11 | mercurial.commands.run() | ||
12 | commands.run() |
|
@@ -45,10 +45,10 b'' | |||||
45 | # glob pattern = user4, user5 |
|
45 | # glob pattern = user4, user5 | |
46 | # ** = user6 |
|
46 | # ** = user6 | |
47 |
|
47 | |||
48 |
from mercurial. |
|
48 | from mercurial.i18n import _ | |
49 | from mercurial.i18n import gettext as _ |
|
|||
50 | from mercurial.node import * |
|
49 | from mercurial.node import * | |
51 | demandload(globals(), 'getpass mercurial:util') |
|
50 | from mercurial import util | |
|
51 | import getpass | |||
52 |
|
52 | |||
53 | class checker(object): |
|
53 | class checker(object): | |
54 | '''acl checker.''' |
|
54 | '''acl checker.''' | |
@@ -91,7 +91,7 b' class checker(object):' | |||||
91 |
|
91 | |||
92 | def check(self, node): |
|
92 | def check(self, node): | |
93 | '''return if access allowed, raise exception if not.''' |
|
93 | '''return if access allowed, raise exception if not.''' | |
94 |
files = self.repo.change |
|
94 | files = self.repo.changectx(node).files() | |
95 | if self.deniable: |
|
95 | if self.deniable: | |
96 | for f in files: |
|
96 | for f in files: | |
97 | if self.deny(f): |
|
97 | if self.deny(f): |
@@ -52,10 +52,10 b'' | |||||
52 | # [usermap] |
|
52 | # [usermap] | |
53 | # committer_email = bugzilla_user_name |
|
53 | # committer_email = bugzilla_user_name | |
54 |
|
54 | |||
55 |
from mercurial. |
|
55 | from mercurial.i18n import _ | |
56 | from mercurial.i18n import gettext as _ |
|
|||
57 | from mercurial.node import * |
|
56 | from mercurial.node import * | |
58 | demandload(globals(), 'mercurial:cmdutil,templater,util os re time') |
|
57 | from mercurial import cmdutil, templater, util | |
|
58 | import os, re, time | |||
59 |
|
59 | |||
60 | MySQLdb = None |
|
60 | MySQLdb = None | |
61 |
|
61 | |||
@@ -222,7 +222,7 b' class bugzilla(object):' | |||||
222 | _bug_re = None |
|
222 | _bug_re = None | |
223 | _split_re = None |
|
223 | _split_re = None | |
224 |
|
224 | |||
225 |
def find_bug_ids(self, |
|
225 | def find_bug_ids(self, ctx): | |
226 | '''find valid bug ids that are referred to in changeset |
|
226 | '''find valid bug ids that are referred to in changeset | |
227 | comments and that do not already have references to this |
|
227 | comments and that do not already have references to this | |
228 | changeset.''' |
|
228 | changeset.''' | |
@@ -235,7 +235,7 b' class bugzilla(object):' | |||||
235 | start = 0 |
|
235 | start = 0 | |
236 | ids = {} |
|
236 | ids = {} | |
237 | while True: |
|
237 | while True: | |
238 | m = bugzilla._bug_re.search(desc, start) |
|
238 | m = bugzilla._bug_re.search(ctx.description(), start) | |
239 | if not m: |
|
239 | if not m: | |
240 | break |
|
240 | break | |
241 | start = m.end() |
|
241 | start = m.end() | |
@@ -246,10 +246,10 b' class bugzilla(object):' | |||||
246 | if ids: |
|
246 | if ids: | |
247 | ids = self.filter_real_bug_ids(ids) |
|
247 | ids = self.filter_real_bug_ids(ids) | |
248 | if ids: |
|
248 | if ids: | |
249 | ids = self.filter_unknown_bug_ids(node, ids) |
|
249 | ids = self.filter_unknown_bug_ids(ctx.node(), ids) | |
250 | return ids |
|
250 | return ids | |
251 |
|
251 | |||
252 |
def update(self, bugid, |
|
252 | def update(self, bugid, ctx): | |
253 | '''update bugzilla bug with reference to changeset.''' |
|
253 | '''update bugzilla bug with reference to changeset.''' | |
254 |
|
254 | |||
255 | def webroot(root): |
|
255 | def webroot(root): | |
@@ -268,7 +268,7 b' class bugzilla(object):' | |||||
268 | mapfile = self.ui.config('bugzilla', 'style') |
|
268 | mapfile = self.ui.config('bugzilla', 'style') | |
269 | tmpl = self.ui.config('bugzilla', 'template') |
|
269 | tmpl = self.ui.config('bugzilla', 'template') | |
270 | t = cmdutil.changeset_templater(self.ui, self.repo, |
|
270 | t = cmdutil.changeset_templater(self.ui, self.repo, | |
271 |
False |
|
271 | False, mapfile, False) | |
272 | if not mapfile and not tmpl: |
|
272 | if not mapfile and not tmpl: | |
273 | tmpl = _('changeset {node|short} in repo {root} refers ' |
|
273 | tmpl = _('changeset {node|short} in repo {root} refers ' | |
274 | 'to bug {bug}.\ndetails:\n\t{desc|tabindent}') |
|
274 | 'to bug {bug}.\ndetails:\n\t{desc|tabindent}') | |
@@ -276,13 +276,13 b' class bugzilla(object):' | |||||
276 | tmpl = templater.parsestring(tmpl, quoted=False) |
|
276 | tmpl = templater.parsestring(tmpl, quoted=False) | |
277 | t.use_template(tmpl) |
|
277 | t.use_template(tmpl) | |
278 | self.ui.pushbuffer() |
|
278 | self.ui.pushbuffer() | |
279 | t.show(changenode=node, changes=changes, |
|
279 | t.show(changenode=ctx.node(), changes=ctx.changeset(), | |
280 | bug=str(bugid), |
|
280 | bug=str(bugid), | |
281 | hgweb=self.ui.config('web', 'baseurl'), |
|
281 | hgweb=self.ui.config('web', 'baseurl'), | |
282 | root=self.repo.root, |
|
282 | root=self.repo.root, | |
283 | webroot=webroot(self.repo.root)) |
|
283 | webroot=webroot(self.repo.root)) | |
284 | data = self.ui.popbuffer() |
|
284 | data = self.ui.popbuffer() | |
285 |
self.add_comment(bugid, data, templater.email(c |
|
285 | self.add_comment(bugid, data, templater.email(ctx.user())) | |
286 |
|
286 | |||
287 | def hook(ui, repo, hooktype, node=None, **kwargs): |
|
287 | def hook(ui, repo, hooktype, node=None, **kwargs): | |
288 | '''add comment to bugzilla for each changeset that refers to a |
|
288 | '''add comment to bugzilla for each changeset that refers to a | |
@@ -300,12 +300,11 b' def hook(ui, repo, hooktype, node=None, ' | |||||
300 | hooktype) |
|
300 | hooktype) | |
301 | try: |
|
301 | try: | |
302 | bz = bugzilla(ui, repo) |
|
302 | bz = bugzilla(ui, repo) | |
303 | bin_node = bin(node) |
|
303 | ctx = repo.changctx(node) | |
304 | changes = repo.changelog.read(bin_node) |
|
304 | ids = bz.find_bug_ids(ctx) | |
305 | ids = bz.find_bug_ids(bin_node, changes[4]) |
|
|||
306 | if ids: |
|
305 | if ids: | |
307 | for id in ids: |
|
306 | for id in ids: | |
308 |
bz.update(id, |
|
307 | bz.update(id, ctx) | |
309 | bz.notify(ids) |
|
308 | bz.notify(ids) | |
310 | except MySQLdb.MySQLError, err: |
|
309 | except MySQLdb.MySQLError, err: | |
311 | raise util.Abort(_('database error: %s') % err[1]) |
|
310 | raise util.Abort(_('database error: %s') % err[1]) |
@@ -48,16 +48,15 b'' | |||||
48 | # needed files, so running the external diff program will actually be |
|
48 | # needed files, so running the external diff program will actually be | |
49 | # pretty fast (at least faster than having to compare the entire tree). |
|
49 | # pretty fast (at least faster than having to compare the entire tree). | |
50 |
|
50 | |||
51 |
from mercurial. |
|
51 | from mercurial.i18n import _ | |
52 | from mercurial.i18n import gettext as _ |
|
|||
53 | from mercurial.node import * |
|
52 | from mercurial.node import * | |
54 | demandload(globals(), 'mercurial:cmdutil,util os shutil tempfile') |
|
53 | from mercurial import cmdutil, util | |
|
54 | import os, shutil, tempfile | |||
55 |
|
55 | |||
56 | def dodiff(ui, repo, diffcmd, diffopts, pats, opts): |
|
56 | def dodiff(ui, repo, diffcmd, diffopts, pats, opts): | |
57 | def snapshot_node(files, node): |
|
57 | def snapshot_node(files, node): | |
58 | '''snapshot files as of some revision''' |
|
58 | '''snapshot files as of some revision''' | |
59 |
|
|
59 | mf = repo.changectx(node).manifest() | |
60 | mf = repo.manifest.read(changes[0]) |
|
|||
61 | dirname = '%s.%s' % (os.path.basename(repo.root), short(node)) |
|
60 | dirname = '%s.%s' % (os.path.basename(repo.root), short(node)) | |
62 | base = os.path.join(tmproot, dirname) |
|
61 | base = os.path.join(tmproot, dirname) | |
63 | os.mkdir(base) |
|
62 | os.mkdir(base) | |
@@ -74,7 +73,8 b' def dodiff(ui, repo, diffcmd, diffopts, ' | |||||
74 | destdir = os.path.dirname(dest) |
|
73 | destdir = os.path.dirname(dest) | |
75 | if not os.path.isdir(destdir): |
|
74 | if not os.path.isdir(destdir): | |
76 | os.makedirs(destdir) |
|
75 | os.makedirs(destdir) | |
77 |
repo.wwrite(wfn, repo.file(fn).read(mf[fn] |
|
76 | data = repo.wwritedata(wfn, repo.file(wfn).read(mf[wfn])) | |
|
77 | open(dest, 'w').write(data) | |||
78 | return dirname |
|
78 | return dirname | |
79 |
|
79 | |||
80 | def snapshot_wdir(files): |
|
80 | def snapshot_wdir(files): |
@@ -5,10 +5,9 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 |
from mercurial. |
|
8 | from mercurial.i18n import _ | |
9 | from mercurial.i18n import gettext as _ |
|
|||
10 | from mercurial.node import * |
|
9 | from mercurial.node import * | |
11 |
|
|
10 | from mercurial import commands, hg, node, util | |
12 |
|
11 | |||
13 | def fetch(ui, repo, source='default', **opts): |
|
12 | def fetch(ui, repo, source='default', **opts): | |
14 | '''Pull changes from a remote repository, merge new changes if needed. |
|
13 | '''Pull changes from a remote repository, merge new changes if needed. |
@@ -8,7 +8,7 b'' | |||||
8 | import os, tempfile, binascii |
|
8 | import os, tempfile, binascii | |
9 | from mercurial import util |
|
9 | from mercurial import util | |
10 | from mercurial import node as hgnode |
|
10 | from mercurial import node as hgnode | |
11 |
from mercurial.i18n import |
|
11 | from mercurial.i18n import _ | |
12 |
|
12 | |||
13 | class gpg: |
|
13 | class gpg: | |
14 | def __init__(self, path, key=None): |
|
14 | def __init__(self, path, key=None): |
@@ -6,9 +6,9 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 |
from mercurial.i18n import |
|
9 | from mercurial.i18n import _ | |
10 | from mercurial.demandload import demandload |
|
10 | from mercurial import hg, util, commands, cmdutil | |
11 | demandload(globals(), "os sys sets mercurial:hg,util,commands,cmdutil") |
|
11 | import os, sys, sets | |
12 |
|
12 | |||
13 | versionstr = "0.0.3" |
|
13 | versionstr = "0.0.3" | |
14 |
|
14 |
@@ -5,26 +5,18 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from mercurial.demandload import * |
|
8 | import sys, os | |
9 | demandload(globals(), 'time sys signal os') |
|
9 | from mercurial import hg, fancyopts, commands, ui, util, patch, revlog | |
10 | demandload(globals(), 'mercurial:hg,fancyopts,commands,ui,util,patch,revlog') |
|
|||
11 |
|
10 | |||
12 | def difftree(ui, repo, node1=None, node2=None, *files, **opts): |
|
11 | def difftree(ui, repo, node1=None, node2=None, *files, **opts): | |
13 | """diff trees from two commits""" |
|
12 | """diff trees from two commits""" | |
14 | def __difftree(repo, node1, node2, files=[]): |
|
13 | def __difftree(repo, node1, node2, files=[]): | |
15 | if node2: |
|
14 | assert node2 is not None | |
16 |
|
|
15 | mmap = repo.changectx(node1).manifest() | |
17 |
|
|
16 | mmap2 = repo.changectx(node2).manifest() | |
18 |
|
|
17 | status = repo.status(node1, node2, files=files)[:5] | |
19 |
|
|
18 | modified, added, removed, deleted, unknown = status | |
20 | else: |
|
|||
21 | status = repo.status(node1, files=files)[:5] |
|
|||
22 | modified, added, removed, deleted, unknown = status |
|
|||
23 | if not node1: |
|
|||
24 | node1 = repo.dirstate.parents()[0] |
|
|||
25 |
|
19 | |||
26 | change = repo.changelog.read(node1) |
|
|||
27 | mmap = repo.manifest.read(change[0]) |
|
|||
28 | empty = hg.short(hg.nullid) |
|
20 | empty = hg.short(hg.nullid) | |
29 |
|
21 | |||
30 | for f in modified: |
|
22 | for f in modified: | |
@@ -70,32 +62,30 b' def difftree(ui, repo, node1=None, node2' | |||||
70 | if not opts['stdin']: |
|
62 | if not opts['stdin']: | |
71 | break |
|
63 | break | |
72 |
|
64 | |||
73 |
def catcommit(repo, n, prefix, c |
|
65 | def catcommit(repo, n, prefix, ctx=None): | |
74 | nlprefix = '\n' + prefix; |
|
66 | nlprefix = '\n' + prefix; | |
75 | (p1, p2) = repo.changelog.parents(n) |
|
67 | if ctx is None: | |
76 | (h, h1, h2) = map(hg.short, (n, p1, p2)) |
|
68 | ctx = repo.changectx(n) | |
77 | (i1, i2) = map(repo.changelog.rev, (p1, p2)) |
|
69 | (p1, p2) = ctx.parents() | |
78 | if not changes: |
|
70 | print "tree %s" % (hg.short(ctx.changeset()[0])) # use ctx.node() instead ?? | |
79 | changes = repo.changelog.read(n) |
|
71 | if p1: print "parent %s" % (hg.short(p1.node())) | |
80 |
print " |
|
72 | if p2: print "parent %s" % (hg.short(p2.node())) | |
81 | if i1 != hg.nullrev: print "parent %s" % (h1) |
|
73 | date = ctx.date() | |
82 | if i2 != hg.nullrev: print "parent %s" % (h2) |
|
74 | description = ctx.description() | |
83 | date_ar = changes[2] |
|
75 | lines = description.splitlines() | |
84 | date = int(float(date_ar[0])) |
|
|||
85 | lines = changes[4].splitlines() |
|
|||
86 | if lines and lines[-1].startswith('committer:'): |
|
76 | if lines and lines[-1].startswith('committer:'): | |
87 | committer = lines[-1].split(': ')[1].rstrip() |
|
77 | committer = lines[-1].split(': ')[1].rstrip() | |
88 | else: |
|
78 | else: | |
89 |
committer = c |
|
79 | committer = ctx.user() | |
90 |
|
80 | |||
91 |
print "author %s %s %s" % (c |
|
81 | print "author %s %s %s" % (ctx.user(), int(date[0]), date[1]) | |
92 |
print "committer %s %s %s" % (committer, date, date |
|
82 | print "committer %s %s %s" % (committer, int(date[0]), date[1]) | |
93 |
print "revision %d" % |
|
83 | print "revision %d" % ctx.rev() | |
94 | print "" |
|
84 | print "" | |
95 | if prefix != "": |
|
85 | if prefix != "": | |
96 |
print "%s%s" % (prefix, |
|
86 | print "%s%s" % (prefix, description.replace('\n', nlprefix).strip()) | |
97 | else: |
|
87 | else: | |
98 |
print |
|
88 | print description | |
99 | if prefix: |
|
89 | if prefix: | |
100 | sys.stdout.write('\0') |
|
90 | sys.stdout.write('\0') | |
101 |
|
91 | |||
@@ -146,8 +136,7 b' def catfile(ui, repo, type=None, r=None,' | |||||
146 | # you can specify a commit to stop at by starting the sha1 with ^ |
|
136 | # you can specify a commit to stop at by starting the sha1 with ^ | |
147 | def revtree(args, repo, full="tree", maxnr=0, parents=False): |
|
137 | def revtree(args, repo, full="tree", maxnr=0, parents=False): | |
148 | def chlogwalk(): |
|
138 | def chlogwalk(): | |
149 |
c |
|
139 | count = repo.changelog.count() | |
150 | count = ch.count() |
|
|||
151 | i = count |
|
140 | i = count | |
152 | l = [0] * 100 |
|
141 | l = [0] * 100 | |
153 | chunk = 100 |
|
142 | chunk = 100 | |
@@ -163,7 +152,8 b' def revtree(args, repo, full="tree", max' | |||||
163 | l[chunk - x:] = [0] * (chunk - x) |
|
152 | l[chunk - x:] = [0] * (chunk - x) | |
164 | break |
|
153 | break | |
165 | if full != None: |
|
154 | if full != None: | |
166 |
l[x] = |
|
155 | l[x] = repo.changectx(i + x) | |
|
156 | l[x].changeset() # force reading | |||
167 | else: |
|
157 | else: | |
168 | l[x] = 1 |
|
158 | l[x] = 1 | |
169 | for x in xrange(chunk-1, -1, -1): |
|
159 | for x in xrange(chunk-1, -1, -1): | |
@@ -217,7 +207,7 b' def revtree(args, repo, full="tree", max' | |||||
217 |
|
207 | |||
218 | # walk the repository looking for commits that are in our |
|
208 | # walk the repository looking for commits that are in our | |
219 | # reachability graph |
|
209 | # reachability graph | |
220 |
for i, c |
|
210 | for i, ctx in chlogwalk(): | |
221 | n = repo.changelog.node(i) |
|
211 | n = repo.changelog.node(i) | |
222 | mask = is_reachable(want_sha1, reachable, n) |
|
212 | mask = is_reachable(want_sha1, reachable, n) | |
223 | if mask: |
|
213 | if mask: | |
@@ -232,13 +222,13 b' def revtree(args, repo, full="tree", max' | |||||
232 | print hg.short(n) + parentstr |
|
222 | print hg.short(n) + parentstr | |
233 | elif full == "commit": |
|
223 | elif full == "commit": | |
234 | print hg.short(n) + parentstr |
|
224 | print hg.short(n) + parentstr | |
235 |
catcommit(repo, n, ' ', c |
|
225 | catcommit(repo, n, ' ', ctx) | |
236 | else: |
|
226 | else: | |
237 | (p1, p2) = repo.changelog.parents(n) |
|
227 | (p1, p2) = repo.changelog.parents(n) | |
238 | (h, h1, h2) = map(hg.short, (n, p1, p2)) |
|
228 | (h, h1, h2) = map(hg.short, (n, p1, p2)) | |
239 | (i1, i2) = map(repo.changelog.rev, (p1, p2)) |
|
229 | (i1, i2) = map(repo.changelog.rev, (p1, p2)) | |
240 |
|
230 | |||
241 |
date = c |
|
231 | date = ctx.date()[0] | |
242 | print "%s %s:%s" % (date, h, mask), |
|
232 | print "%s %s:%s" % (date, h, mask), | |
243 | mask = is_reachable(want_sha1, reachable, p1) |
|
233 | mask = is_reachable(want_sha1, reachable, p1) | |
244 | if i1 != hg.nullrev and mask > 0: |
|
234 | if i1 != hg.nullrev and mask > 0: |
@@ -29,11 +29,9 b' remove patch from applied stack ' | |||||
29 | refresh contents of top applied patch qrefresh |
|
29 | refresh contents of top applied patch qrefresh | |
30 | ''' |
|
30 | ''' | |
31 |
|
31 | |||
32 |
from mercurial. |
|
32 | from mercurial.i18n import _ | |
33 | from mercurial.i18n import gettext as _ |
|
33 | from mercurial import commands, cmdutil, hg, patch, revlog, util, changegroup | |
34 | from mercurial import commands |
|
34 | import os, sys, re, errno | |
35 | demandload(globals(), "os sys re struct traceback errno bz2") |
|
|||
36 | demandload(globals(), "mercurial:cmdutil,hg,patch,revlog,util,changegroup") |
|
|||
37 |
|
35 | |||
38 | commands.norepo += " qclone qversion" |
|
36 | commands.norepo += " qclone qversion" | |
39 |
|
37 | |||
@@ -328,11 +326,12 b' class queue:' | |||||
328 | hg.clean(repo, head, wlock=wlock) |
|
326 | hg.clean(repo, head, wlock=wlock) | |
329 | self.strip(repo, n, update=False, backup='strip', wlock=wlock) |
|
327 | self.strip(repo, n, update=False, backup='strip', wlock=wlock) | |
330 |
|
328 | |||
331 |
c = repo.change |
|
329 | ctx = repo.changectx(rev) | |
332 | ret = hg.merge(repo, rev, wlock=wlock) |
|
330 | ret = hg.merge(repo, rev, wlock=wlock) | |
333 | if ret: |
|
331 | if ret: | |
334 | raise util.Abort(_("update returned %d") % ret) |
|
332 | raise util.Abort(_("update returned %d") % ret) | |
335 | n = repo.commit(None, c[4], c[1], force=1, wlock=wlock) |
|
333 | n = repo.commit(None, ctx.description(), ctx.user(), | |
|
334 | force=1, wlock=wlock) | |||
336 | if n == None: |
|
335 | if n == None: | |
337 | raise util.Abort(_("repo commit failed")) |
|
336 | raise util.Abort(_("repo commit failed")) | |
338 | try: |
|
337 | try: | |
@@ -614,15 +613,12 b' class queue:' | |||||
614 | self.ui.warn("saving bundle to %s\n" % name) |
|
613 | self.ui.warn("saving bundle to %s\n" % name) | |
615 | return changegroup.writebundle(cg, name, "HG10BZ") |
|
614 | return changegroup.writebundle(cg, name, "HG10BZ") | |
616 |
|
615 | |||
617 |
def stripall( |
|
616 | def stripall(revnum): | |
618 |
|
|
617 | mm = repo.changectx(rev).manifest() | |
619 | c = cl.read(rev) |
|
|||
620 | mm = repo.manifest.read(c[0]) |
|
|||
621 | seen = {} |
|
618 | seen = {} | |
622 |
|
619 | |||
623 | for x in xrange(revnum, cl.count()): |
|
620 | for x in xrange(revnum, repo.changelog.count()): | |
624 | c = cl.read(cl.node(x)) |
|
621 | for f in repo.changectx(x).files(): | |
625 | for f in c[3]: |
|
|||
626 | if f in seen: |
|
622 | if f in seen: | |
627 | continue |
|
623 | continue | |
628 | seen[f] = 1 |
|
624 | seen[f] = 1 | |
@@ -703,7 +699,7 b' class queue:' | |||||
703 | backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') |
|
699 | backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip') | |
704 | chgrpfile = bundle(backupch) |
|
700 | chgrpfile = bundle(backupch) | |
705 |
|
701 | |||
706 |
stripall( |
|
702 | stripall(revnum) | |
707 |
|
703 | |||
708 | change = chlog.read(rev) |
|
704 | change = chlog.read(rev) | |
709 | chlog.strip(revnum, revnum) |
|
705 | chlog.strip(revnum, revnum) | |
@@ -834,14 +830,7 b' class queue:' | |||||
834 | wlock=None): |
|
830 | wlock=None): | |
835 | def getfile(f, rev): |
|
831 | def getfile(f, rev): | |
836 | t = repo.file(f).read(rev) |
|
832 | t = repo.file(f).read(rev) | |
837 | try: |
|
833 | repo.wfile(f, "w").write(t) | |
838 | repo.wfile(f, "w").write(t) |
|
|||
839 | except IOError: |
|
|||
840 | try: |
|
|||
841 | os.makedirs(os.path.dirname(repo.wjoin(f))) |
|
|||
842 | except OSError, err: |
|
|||
843 | if err.errno != errno.EEXIST: raise |
|
|||
844 | repo.wfile(f, "w").write(t) |
|
|||
845 |
|
834 | |||
846 | if not wlock: |
|
835 | if not wlock: | |
847 | wlock = repo.wlock() |
|
836 | wlock = repo.wlock() |
@@ -65,11 +65,10 b'' | |||||
65 | # if you like, you can put notify config file in repo that users can |
|
65 | # if you like, you can put notify config file in repo that users can | |
66 | # push changes to, they can manage their own subscriptions. |
|
66 | # push changes to, they can manage their own subscriptions. | |
67 |
|
67 | |||
68 |
from mercurial. |
|
68 | from mercurial.i18n import _ | |
69 | from mercurial.i18n import gettext as _ |
|
|||
70 | from mercurial.node import * |
|
69 | from mercurial.node import * | |
71 |
|
|
70 | from mercurial import patch, cmdutil, templater, util, mail | |
72 |
|
|
71 | import email.Parser, fnmatch, socket, time | |
73 |
|
72 | |||
74 | # template for single changeset can include email headers. |
|
73 | # template for single changeset can include email headers. | |
75 | single_template = ''' |
|
74 | single_template = ''' | |
@@ -113,7 +112,7 b' class notifier(object):' | |||||
113 | template = (self.ui.config('notify', hooktype) or |
|
112 | template = (self.ui.config('notify', hooktype) or | |
114 | self.ui.config('notify', 'template')) |
|
113 | self.ui.config('notify', 'template')) | |
115 | self.t = cmdutil.changeset_templater(self.ui, self.repo, |
|
114 | self.t = cmdutil.changeset_templater(self.ui, self.repo, | |
116 |
False |
|
115 | False, mapfile, False) | |
117 | if not mapfile and not template: |
|
116 | if not mapfile and not template: | |
118 | template = deftemplates.get(hooktype) or single_template |
|
117 | template = deftemplates.get(hooktype) or single_template | |
119 | if template: |
|
118 | if template: |
@@ -63,11 +63,10 b'' | |||||
63 | # |
|
63 | # | |
64 | # That should be all. Now your patchbomb is on its way out. |
|
64 | # That should be all. Now your patchbomb is on its way out. | |
65 |
|
65 | |||
66 | from mercurial.demandload import * |
|
66 | import os, errno, socket | |
67 |
|
|
67 | import email.MIMEMultipart, email.MIMEText, email.Utils | |
68 |
|
|
68 | from mercurial import cmdutil, commands, hg, mail, ui, patch, util | |
69 | os errno popen2 socket sys tempfile''') |
|
69 | from mercurial.i18n import _ | |
70 | from mercurial.i18n import gettext as _ |
|
|||
71 | from mercurial.node import * |
|
70 | from mercurial.node import * | |
72 |
|
71 | |||
73 | try: |
|
72 | try: | |
@@ -216,8 +215,6 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
216 | bcc = [a.strip() for a in bcc if a.strip()] |
|
215 | bcc = [a.strip() for a in bcc if a.strip()] | |
217 |
|
216 | |||
218 | if len(patches) > 1: |
|
217 | if len(patches) > 1: | |
219 | ui.write(_('\nWrite the introductory message for the patch series.\n\n')) |
|
|||
220 |
|
||||
221 | tlen = len(str(len(patches))) |
|
218 | tlen = len(str(len(patches))) | |
222 |
|
219 | |||
223 | subj = '[PATCH %0*d of %d] %s' % ( |
|
220 | subj = '[PATCH %0*d of %d] %s' % ( | |
@@ -227,21 +224,13 b' def patchbomb(ui, repo, *revs, **opts):' | |||||
227 | prompt('Subject:', rest = ' [PATCH %0*d of %d] ' % (tlen, 0, |
|
224 | prompt('Subject:', rest = ' [PATCH %0*d of %d] ' % (tlen, 0, | |
228 | len(patches)))) |
|
225 | len(patches)))) | |
229 |
|
226 | |||
230 | ui.write(_('Finish with ^D or a dot on a line by itself.\n\n')) |
|
227 | body = '' | |
231 |
|
||||
232 | body = [] |
|
|||
233 |
|
||||
234 | while True: |
|
|||
235 | try: l = raw_input() |
|
|||
236 | except EOFError: break |
|
|||
237 | if l == '.': break |
|
|||
238 | body.append(l) |
|
|||
239 |
|
||||
240 | if opts['diffstat']: |
|
228 | if opts['diffstat']: | |
241 | d = cdiffstat(_('Final summary:\n'), jumbo) |
|
229 | d = cdiffstat(_('Final summary:\n'), jumbo) | |
242 |
if d: body |
|
230 | if d: body = '\n' + d | |
243 |
|
231 | |||
244 | body = '\n'.join(body) + '\n' |
|
232 | ui.write(_('\nWrite the introductory message for the patch series.\n\n')) | |
|
233 | body = ui.edit(body, sender) | |||
245 |
|
234 | |||
246 | msg = email.MIMEText.MIMEText(body) |
|
235 | msg = email.MIMEText.MIMEText(body) | |
247 | msg['Subject'] = subj |
|
236 | msg['Subject'] = subj |
@@ -5,11 +5,10 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 |
from mercurial. |
|
8 | from mercurial.i18n import _ | |
9 | from mercurial.i18n import gettext as _ |
|
9 | import os, tempfile | |
10 | demandload(globals(), 'os tempfile') |
|
10 | from mercurial import bundlerepo, cmdutil, commands, hg, merge, patch, revlog | |
11 | demandload(globals(), 'mercurial:bundlerepo,cmdutil,commands,hg,merge,patch') |
|
11 | from mercurial import util | |
12 | demandload(globals(), 'mercurial:revlog,util') |
|
|||
13 |
|
12 | |||
14 | '''patch transplanting tool |
|
13 | '''patch transplanting tool | |
15 |
|
14 | |||
@@ -588,5 +587,5 b' cmdtable = {' | |||||
588 | ('', 'log', None, _('append transplant info to log message')), |
|
587 | ('', 'log', None, _('append transplant info to log message')), | |
589 | ('c', 'continue', None, _('continue last transplant session after repair')), |
|
588 | ('c', 'continue', None, _('continue last transplant session after repair')), | |
590 | ('', 'filter', '', _('filter changesets through FILTER'))], |
|
589 | ('', 'filter', '', _('filter changesets through FILTER'))], | |
591 |
_('hg transplant [-s REPOSITORY] [-b BRANCH] [-p REV] [-m REV] [ |
|
590 | _('hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] [-m REV] [REV]...')) | |
592 | } |
|
591 | } |
@@ -5,8 +5,7 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import * |
|
8 | import cStringIO, changelog, errno, manifest, os, tempfile, util | |
9 | demandload(globals(), "cStringIO changelog errno manifest os tempfile util") |
|
|||
10 |
|
9 | |||
11 | # writes to metadata files are ordered. reads: changelog, manifest, |
|
10 | # writes to metadata files are ordered. reads: changelog, manifest, | |
12 | # normal files. writes: normal files, manifest, changelog. |
|
11 | # normal files. writes: normal files, manifest, changelog. |
@@ -5,10 +5,9 b'' | |||||
5 | # This software may be used and distributed according to the terms of |
|
5 | # This software may be used and distributed according to the terms of | |
6 | # the GNU General Public License, incorporated herein by reference. |
|
6 | # the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 |
from |
|
8 | from i18n import _ | |
9 | from i18n import gettext as _ |
|
|||
10 | from node import * |
|
9 | from node import * | |
11 |
|
|
10 | import cStringIO, os, stat, tarfile, time, util, zipfile | |
12 |
|
11 | |||
13 | def tidyprefix(dest, prefix, suffixes): |
|
12 | def tidyprefix(dest, prefix, suffixes): | |
14 | '''choose prefix to use for names in archive. make sure prefix is |
|
13 | '''choose prefix to use for names in archive. make sure prefix is | |
@@ -155,15 +154,12 b' def archive(repo, dest, node, kind, deco' | |||||
155 | def write(name, mode, data): |
|
154 | def write(name, mode, data): | |
156 | if matchfn and not matchfn(name): return |
|
155 | if matchfn and not matchfn(name): return | |
157 | if decode: |
|
156 | if decode: | |
158 | fp = cStringIO.StringIO() |
|
157 | data = repo.wwritedata(name, data) | |
159 | repo.wwrite(name, data, fp) |
|
|||
160 | data = fp.getvalue() |
|
|||
161 | archiver.addfile(name, mode, data) |
|
158 | archiver.addfile(name, mode, data) | |
162 |
|
159 | |||
163 |
c |
|
160 | ctx = repo.changectx(node) | |
164 | mn = change[0] |
|
161 | archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0]) | |
165 | archiver = archivers[kind](dest, prefix, mtime or change[2][0]) |
|
162 | m = ctx.manifest() | |
166 | m = repo.manifest.read(mn) |
|
|||
167 | items = m.items() |
|
163 | items = m.items() | |
168 | items.sort() |
|
164 | items.sort() | |
169 | write('.hg_archival.txt', 0644, |
|
165 | write('.hg_archival.txt', 0644, |
@@ -11,9 +11,8 b' of the GNU General Public License, incor' | |||||
11 | """ |
|
11 | """ | |
12 |
|
12 | |||
13 | from node import * |
|
13 | from node import * | |
14 |
from i18n import |
|
14 | from i18n import _ | |
15 | from demandload import demandload |
|
15 | import changegroup, util, os, struct, bz2, tempfile | |
16 | demandload(globals(), "changegroup util os struct bz2 tempfile") |
|
|||
17 |
|
16 | |||
18 | import localrepo, changelog, manifest, filelog, revlog |
|
17 | import localrepo, changelog, manifest, filelog, revlog | |
19 |
|
18 | |||
@@ -50,7 +49,7 b' class bundlerevlog(revlog.revlog):' | |||||
50 | continue |
|
49 | continue | |
51 | for p in (p1, p2): |
|
50 | for p in (p1, p2): | |
52 | if not p in self.nodemap: |
|
51 | if not p in self.nodemap: | |
53 |
raise revlog. |
|
52 | raise revlog.LookupError(_("unknown parent %s") % short(p1)) | |
54 | if linkmapper is None: |
|
53 | if linkmapper is None: | |
55 | link = n |
|
54 | link = n | |
56 | else: |
|
55 | else: |
@@ -6,9 +6,9 b' changegroup.py - Mercurial changegroup m' | |||||
6 | This software may be used and distributed according to the terms |
|
6 | This software may be used and distributed according to the terms | |
7 | of the GNU General Public License, incorporated herein by reference. |
|
7 | of the GNU General Public License, incorporated herein by reference. | |
8 | """ |
|
8 | """ | |
9 | from i18n import gettext as _ |
|
9 | ||
10 |
from |
|
10 | from i18n import _ | |
11 |
|
|
11 | import struct, os, bz2, zlib, util, tempfile | |
12 |
|
12 | |||
13 | def getchunk(source): |
|
13 | def getchunk(source): | |
14 | """get a chunk from a changegroup""" |
|
14 | """get a chunk from a changegroup""" | |
@@ -67,8 +67,6 b' def writebundle(cg, filename, bundletype' | |||||
67 | cleanup = None |
|
67 | cleanup = None | |
68 | try: |
|
68 | try: | |
69 | if filename: |
|
69 | if filename: | |
70 | if os.path.exists(filename): |
|
|||
71 | raise util.Abort(_("file '%s' already exists") % filename) |
|
|||
72 | fh = open(filename, "wb") |
|
70 | fh = open(filename, "wb") | |
73 | else: |
|
71 | else: | |
74 | fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") |
|
72 | fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") |
@@ -6,9 +6,8 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from revlog import * |
|
8 | from revlog import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | from demandload import demandload |
|
10 | import os, time, util | |
11 | demandload(globals(), "os time util") |
|
|||
12 |
|
11 | |||
13 | def _string_escape(text): |
|
12 | def _string_escape(text): | |
14 | """ |
|
13 | """ |
@@ -5,11 +5,9 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
|||
9 | from node import * |
|
8 | from node import * | |
10 |
from i18n import |
|
9 | from i18n import _ | |
11 | demandload(globals(), 'os sys') |
|
10 | import os, sys, mdiff, util, templater, patch | |
12 | demandload(globals(), 'mdiff util templater patch') |
|
|||
13 |
|
11 | |||
14 | revrangesep = ':' |
|
12 | revrangesep = ':' | |
15 |
|
13 | |||
@@ -148,13 +146,12 b' def walk(repo, pats=[], opts={}, node=No' | |||||
148 | def findrenames(repo, added=None, removed=None, threshold=0.5): |
|
146 | def findrenames(repo, added=None, removed=None, threshold=0.5): | |
149 | if added is None or removed is None: |
|
147 | if added is None or removed is None: | |
150 | added, removed = repo.status()[1:3] |
|
148 | added, removed = repo.status()[1:3] | |
151 | changes = repo.changelog.read(repo.dirstate.parents()[0]) |
|
149 | ctx = repo.changectx() | |
152 | mf = repo.manifest.read(changes[0]) |
|
|||
153 | for a in added: |
|
150 | for a in added: | |
154 | aa = repo.wread(a) |
|
151 | aa = repo.wread(a) | |
155 | bestscore, bestname = None, None |
|
152 | bestscore, bestname = None, None | |
156 | for r in removed: |
|
153 | for r in removed: | |
157 |
rr = |
|
154 | rr = ctx.filectx(r).data() | |
158 | delta = mdiff.textdiff(aa, rr) |
|
155 | delta = mdiff.textdiff(aa, rr) | |
159 | if len(delta) < len(aa): |
|
156 | if len(delta) < len(aa): | |
160 | myscore = 1.0 - (float(len(delta)) / len(aa)) |
|
157 | myscore = 1.0 - (float(len(delta)) / len(aa)) | |
@@ -199,12 +196,11 b' def addremove(repo, pats=[], opts={}, wl' | |||||
199 | class changeset_printer(object): |
|
196 | class changeset_printer(object): | |
200 | '''show changeset information when templating not requested.''' |
|
197 | '''show changeset information when templating not requested.''' | |
201 |
|
198 | |||
202 |
def __init__(self, ui, repo, patch, |
|
199 | def __init__(self, ui, repo, patch, buffered): | |
203 | self.ui = ui |
|
200 | self.ui = ui | |
204 | self.repo = repo |
|
201 | self.repo = repo | |
205 | self.buffered = buffered |
|
202 | self.buffered = buffered | |
206 | self.patch = patch |
|
203 | self.patch = patch | |
207 | self.brinfo = brinfo |
|
|||
208 | self.header = {} |
|
204 | self.header = {} | |
209 | self.hunk = {} |
|
205 | self.hunk = {} | |
210 | self.lastheader = None |
|
206 | self.lastheader = None | |
@@ -268,11 +264,6 b' class changeset_printer(object):' | |||||
268 | for parent in parents: |
|
264 | for parent in parents: | |
269 | self.ui.write(_("parent: %d:%s\n") % parent) |
|
265 | self.ui.write(_("parent: %d:%s\n") % parent) | |
270 |
|
266 | |||
271 | if self.brinfo: |
|
|||
272 | br = self.repo.branchlookup([changenode]) |
|
|||
273 | if br: |
|
|||
274 | self.ui.write(_("branch: %s\n") % " ".join(br[changenode])) |
|
|||
275 |
|
||||
276 | if self.ui.debugflag: |
|
267 | if self.ui.debugflag: | |
277 | self.ui.write(_("manifest: %d:%s\n") % |
|
268 | self.ui.write(_("manifest: %d:%s\n") % | |
278 | (self.repo.manifest.rev(changes[0]), hex(changes[0]))) |
|
269 | (self.repo.manifest.rev(changes[0]), hex(changes[0]))) | |
@@ -320,8 +311,8 b' class changeset_printer(object):' | |||||
320 | class changeset_templater(changeset_printer): |
|
311 | class changeset_templater(changeset_printer): | |
321 | '''format changeset information.''' |
|
312 | '''format changeset information.''' | |
322 |
|
313 | |||
323 |
def __init__(self, ui, repo, patch, |
|
314 | def __init__(self, ui, repo, patch, mapfile, buffered): | |
324 |
changeset_printer.__init__(self, ui, repo, patch, |
|
315 | changeset_printer.__init__(self, ui, repo, patch, buffered) | |
325 | self.t = templater.templater(mapfile, templater.common_filters, |
|
316 | self.t = templater.templater(mapfile, templater.common_filters, | |
326 | cache={'parent': '{rev}:{node|short} ', |
|
317 | cache={'parent': '{rev}:{node|short} ', | |
327 | 'manifest': '{rev}:{node|short}', |
|
318 | 'manifest': '{rev}:{node|short}', | |
@@ -407,12 +398,6 b' class changeset_templater(changeset_prin' | |||||
407 | if branch: |
|
398 | if branch: | |
408 | branch = util.tolocal(branch) |
|
399 | branch = util.tolocal(branch) | |
409 | return showlist('branch', [branch], plural='branches', **args) |
|
400 | return showlist('branch', [branch], plural='branches', **args) | |
410 | # add old style branches if requested |
|
|||
411 | if self.brinfo: |
|
|||
412 | br = self.repo.branchlookup([changenode]) |
|
|||
413 | if changenode in br: |
|
|||
414 | return showlist('branch', br[changenode], |
|
|||
415 | plural='branches', **args) |
|
|||
416 |
|
401 | |||
417 | def showparents(**args): |
|
402 | def showparents(**args): | |
418 | parents = [[('rev', log.rev(p)), ('node', hex(p))] |
|
403 | parents = [[('rev', log.rev(p)), ('node', hex(p))] | |
@@ -526,11 +511,6 b' def show_changeset(ui, repo, opts, buffe' | |||||
526 | if opts.get('patch'): |
|
511 | if opts.get('patch'): | |
527 | patch = matchfn or util.always |
|
512 | patch = matchfn or util.always | |
528 |
|
513 | |||
529 | br = None |
|
|||
530 | if opts.get('branches'): |
|
|||
531 | ui.warn(_("the --branches option is deprecated, " |
|
|||
532 | "please use 'hg branches' instead\n")) |
|
|||
533 | br = True |
|
|||
534 | tmpl = opts.get('template') |
|
514 | tmpl = opts.get('template') | |
535 | mapfile = None |
|
515 | mapfile = None | |
536 | if tmpl: |
|
516 | if tmpl: | |
@@ -552,12 +532,12 b' def show_changeset(ui, repo, opts, buffe' | |||||
552 | or templater.templatepath(mapfile)) |
|
532 | or templater.templatepath(mapfile)) | |
553 | if mapname: mapfile = mapname |
|
533 | if mapname: mapfile = mapname | |
554 | try: |
|
534 | try: | |
555 |
t = changeset_templater(ui, repo, patch, |
|
535 | t = changeset_templater(ui, repo, patch, mapfile, buffered) | |
556 | except SyntaxError, inst: |
|
536 | except SyntaxError, inst: | |
557 | raise util.Abort(inst.args[0]) |
|
537 | raise util.Abort(inst.args[0]) | |
558 | if tmpl: t.use_template(tmpl) |
|
538 | if tmpl: t.use_template(tmpl) | |
559 | return t |
|
539 | return t | |
560 |
return changeset_printer(ui, repo, patch, |
|
540 | return changeset_printer(ui, repo, patch, buffered) | |
561 |
|
541 | |||
562 | def finddate(ui, repo, date): |
|
542 | def finddate(ui, repo, date): | |
563 | """Find the tipmost changeset that matches the given date spec""" |
|
543 | """Find the tipmost changeset that matches the given date spec""" |
@@ -5,14 +5,14 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
8 | import demandimport; demandimport.enable() | |
9 | from node import * |
|
9 | from node import * | |
10 |
from i18n import |
|
10 | from i18n import _ | |
11 |
|
|
11 | import bisect, os, re, sys, signal, imp, urllib, pdb, shlex, stat | |
12 |
|
|
12 | import fancyopts, ui, hg, util, lock, revlog, bundlerepo | |
13 |
|
|
13 | import difflib, patch, time, help, mdiff, tempfile | |
14 |
|
|
14 | import traceback, errno, version, atexit, socket | |
15 |
|
|
15 | import archival, changegroup, cmdutil, hgweb.server, sshserver | |
16 |
|
16 | |||
17 | class UnknownCommand(Exception): |
|
17 | class UnknownCommand(Exception): | |
18 | """Exception raised if command is not in the command table.""" |
|
18 | """Exception raised if command is not in the command table.""" | |
@@ -240,8 +240,7 b' def backout(ui, repo, rev, **opts):' | |||||
240 | if op1 != node: |
|
240 | if op1 != node: | |
241 | if opts['merge']: |
|
241 | if opts['merge']: | |
242 | ui.status(_('merging with changeset %s\n') % nice(op1)) |
|
242 | ui.status(_('merging with changeset %s\n') % nice(op1)) | |
243 |
|
|
243 | hg.merge(repo, hex(op1)) | |
244 | hg.merge(repo, n) |
|
|||
245 | else: |
|
244 | else: | |
246 | ui.status(_('the backout changeset is a new head - ' |
|
245 | ui.status(_('the backout changeset is a new head - ' | |
247 | 'do not forget to merge\n')) |
|
246 | 'do not forget to merge\n')) | |
@@ -685,15 +684,12 b" def debugcomplete(ui, cmd='', **opts):" | |||||
685 | clist.sort() |
|
684 | clist.sort() | |
686 | ui.write("%s\n" % "\n".join(clist)) |
|
685 | ui.write("%s\n" % "\n".join(clist)) | |
687 |
|
686 | |||
688 |
def debugrebuildstate(ui, repo, rev= |
|
687 | def debugrebuildstate(ui, repo, rev=""): | |
689 | """rebuild the dirstate as it would look like for the given revision""" |
|
688 | """rebuild the dirstate as it would look like for the given revision""" | |
690 |
if |
|
689 | if rev == "": | |
691 | rev = repo.changelog.tip() |
|
690 | rev = repo.changelog.tip() | |
692 | else: |
|
691 | ctx = repo.changectx(rev) | |
693 | rev = repo.lookup(rev) |
|
692 | files = ctx.manifest() | |
694 | change = repo.changelog.read(rev) |
|
|||
695 | n = change[0] |
|
|||
696 | files = repo.manifest.read(n) |
|
|||
697 | wlock = repo.wlock() |
|
693 | wlock = repo.wlock() | |
698 | repo.dirstate.rebuild(rev, files) |
|
694 | repo.dirstate.rebuild(rev, files) | |
699 |
|
695 | |||
@@ -704,10 +700,8 b' def debugcheckstate(ui, repo):' | |||||
704 | dc = repo.dirstate.map |
|
700 | dc = repo.dirstate.map | |
705 | keys = dc.keys() |
|
701 | keys = dc.keys() | |
706 | keys.sort() |
|
702 | keys.sort() | |
707 |
m1 |
|
703 | m1 = repo.changectx(parent1).manifest() | |
708 |
m2 |
|
704 | m2 = repo.changectx(parent2).manifest() | |
709 | m1 = repo.manifest.read(m1n) |
|
|||
710 | m2 = repo.manifest.read(m2n) |
|
|||
711 | errors = 0 |
|
705 | errors = 0 | |
712 | for f in dc: |
|
706 | for f in dc: | |
713 | state = repo.dirstate.state(f) |
|
707 | state = repo.dirstate.state(f) | |
@@ -1150,13 +1144,14 b' def grep(ui, repo, pattern, *pats, **opt' | |||||
1150 |
|
1144 | |||
1151 | prev = {} |
|
1145 | prev = {} | |
1152 | def display(fn, rev, states, prevstates): |
|
1146 | def display(fn, rev, states, prevstates): | |
1153 | counts = {'-': 0, '+': 0} |
|
1147 | found = False | |
1154 | filerevmatches = {} |
|
1148 | filerevmatches = {} | |
1155 | if incrementing or not opts['all']: |
|
1149 | r = prev.get(fn, -1) | |
1156 | a, b, r = prevstates, states, rev |
|
1150 | if opts['all']: | |
|
1151 | iter = difflinestates(states, prevstates) | |||
1157 | else: |
|
1152 | else: | |
1158 | a, b, r = states, prevstates, prev.get(fn, -1) |
|
1153 | iter = [('', l) for l in prevstates] | |
1159 |
for change, l in |
|
1154 | for change, l in iter: | |
1160 | cols = [fn, str(r)] |
|
1155 | cols = [fn, str(r)] | |
1161 | if opts['line_number']: |
|
1156 | if opts['line_number']: | |
1162 | cols.append(str(l.linenum)) |
|
1157 | cols.append(str(l.linenum)) | |
@@ -1172,19 +1167,17 b' def grep(ui, repo, pattern, *pats, **opt' | |||||
1172 | else: |
|
1167 | else: | |
1173 | cols.append(l.line) |
|
1168 | cols.append(l.line) | |
1174 | ui.write(sep.join(cols), eol) |
|
1169 | ui.write(sep.join(cols), eol) | |
1175 |
|
|
1170 | found = True | |
1176 |
return |
|
1171 | return found | |
1177 |
|
1172 | |||
1178 | fstate = {} |
|
1173 | fstate = {} | |
1179 | skip = {} |
|
1174 | skip = {} | |
1180 | get = util.cachefunc(lambda r: repo.changectx(r).changeset()) |
|
1175 | get = util.cachefunc(lambda r: repo.changectx(r).changeset()) | |
1181 | changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) |
|
1176 | changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) | |
1182 |
|
|
1177 | found = False | |
1183 | incrementing = False |
|
|||
1184 | follow = opts.get('follow') |
|
1178 | follow = opts.get('follow') | |
1185 | for st, rev, fns in changeiter: |
|
1179 | for st, rev, fns in changeiter: | |
1186 | if st == 'window': |
|
1180 | if st == 'window': | |
1187 | incrementing = rev |
|
|||
1188 | matches.clear() |
|
1181 | matches.clear() | |
1189 | elif st == 'add': |
|
1182 | elif st == 'add': | |
1190 | mf = repo.changectx(rev).manifest() |
|
1183 | mf = repo.changectx(rev).manifest() | |
@@ -1210,10 +1203,10 b' def grep(ui, repo, pattern, *pats, **opt' | |||||
1210 | if copy: |
|
1203 | if copy: | |
1211 | skip[copy] = True |
|
1204 | skip[copy] = True | |
1212 | continue |
|
1205 | continue | |
1213 |
if |
|
1206 | if fn in prev or fstate[fn]: | |
1214 |
|
|
1207 | r = display(fn, rev, m, fstate[fn]) | |
1215 |
|
|
1208 | found = found or r | |
1216 |
if |
|
1209 | if r and not opts['all']: | |
1217 | skip[fn] = True |
|
1210 | skip[fn] = True | |
1218 | if copy: |
|
1211 | if copy: | |
1219 | skip[copy] = True |
|
1212 | skip[copy] = True | |
@@ -1222,15 +1215,14 b' def grep(ui, repo, pattern, *pats, **opt' | |||||
1222 | fstate[copy] = m |
|
1215 | fstate[copy] = m | |
1223 | prev[fn] = rev |
|
1216 | prev[fn] = rev | |
1224 |
|
1217 | |||
1225 | if not incrementing: |
|
1218 | fstate = fstate.items() | |
1226 | fstate = fstate.items() |
|
1219 | fstate.sort() | |
1227 | fstate.sort() |
|
1220 | for fn, state in fstate: | |
1228 |
f |
|
1221 | if fn in skip: | |
1229 |
|
|
1222 | continue | |
1230 | continue |
|
1223 | if fn not in copies.get(prev[fn], {}): | |
1231 | if fn not in copies.get(prev[fn], {}): |
|
1224 | found = display(fn, rev, {}, state) or found | |
1232 | display(fn, rev, {}, state) |
|
1225 | return (not found and 1) or 0 | |
1233 | return (count == 0 and 1) or 0 |
|
|||
1234 |
|
1226 | |||
1235 | def heads(ui, repo, **opts): |
|
1227 | def heads(ui, repo, **opts): | |
1236 | """show current repository heads |
|
1228 | """show current repository heads | |
@@ -1539,8 +1531,12 b' def incoming(ui, repo, source="default",' | |||||
1539 | other = hg.repository(ui, source) |
|
1531 | other = hg.repository(ui, source) | |
1540 | incoming = repo.findincoming(other, force=opts["force"]) |
|
1532 | incoming = repo.findincoming(other, force=opts["force"]) | |
1541 | if not incoming: |
|
1533 | if not incoming: | |
|
1534 | try: | |||
|
1535 | os.unlink(opts["bundle"]) | |||
|
1536 | except: | |||
|
1537 | pass | |||
1542 | ui.status(_("no changes found\n")) |
|
1538 | ui.status(_("no changes found\n")) | |
1543 | return |
|
1539 | return 1 | |
1544 |
|
1540 | |||
1545 | cleanup = None |
|
1541 | cleanup = None | |
1546 | try: |
|
1542 | try: | |
@@ -1705,7 +1701,6 b' def log(ui, repo, *pats, **opts):' | |||||
1705 | if opts["date"]: |
|
1701 | if opts["date"]: | |
1706 | df = util.matchdate(opts["date"]) |
|
1702 | df = util.matchdate(opts["date"]) | |
1707 |
|
1703 | |||
1708 |
|
||||
1709 | displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn) |
|
1704 | displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn) | |
1710 | for st, rev, fns in changeiter: |
|
1705 | for st, rev, fns in changeiter: | |
1711 | if st == 'add': |
|
1706 | if st == 'add': | |
@@ -1772,7 +1767,7 b' def manifest(ui, repo, rev=None):' | |||||
1772 | ui.write("%3s " % (m.execf(f) and "755" or "644")) |
|
1767 | ui.write("%3s " % (m.execf(f) and "755" or "644")) | |
1773 | ui.write("%s\n" % f) |
|
1768 | ui.write("%s\n" % f) | |
1774 |
|
1769 | |||
1775 |
def merge(ui, repo, node=None, force=None |
|
1770 | def merge(ui, repo, node=None, force=None): | |
1776 | """merge working directory with another revision |
|
1771 | """merge working directory with another revision | |
1777 |
|
1772 | |||
1778 | Merge the contents of the current working directory and the |
|
1773 | Merge the contents of the current working directory and the | |
@@ -1786,9 +1781,7 b' def merge(ui, repo, node=None, force=Non' | |||||
1786 | revision to merge with must be provided. |
|
1781 | revision to merge with must be provided. | |
1787 | """ |
|
1782 | """ | |
1788 |
|
1783 | |||
1789 |
if node |
|
1784 | if not node: | |
1790 | node = _lookup(repo, node, branch) |
|
|||
1791 | else: |
|
|||
1792 | heads = repo.heads() |
|
1785 | heads = repo.heads() | |
1793 | if len(heads) > 2: |
|
1786 | if len(heads) > 2: | |
1794 | raise util.Abort(_('repo has %d heads - ' |
|
1787 | raise util.Abort(_('repo has %d heads - ' | |
@@ -1823,7 +1816,7 b' def outgoing(ui, repo, dest=None, **opts' | |||||
1823 | o = repo.findoutgoing(other, force=opts['force']) |
|
1816 | o = repo.findoutgoing(other, force=opts['force']) | |
1824 | if not o: |
|
1817 | if not o: | |
1825 | ui.status(_("no changes found\n")) |
|
1818 | ui.status(_("no changes found\n")) | |
1826 | return |
|
1819 | return 1 | |
1827 | o = repo.changelog.nodesbetween(o, revs)[0] |
|
1820 | o = repo.changelog.nodesbetween(o, revs)[0] | |
1828 | if opts['newest_first']: |
|
1821 | if opts['newest_first']: | |
1829 | o.reverse() |
|
1822 | o.reverse() | |
@@ -2136,8 +2129,9 b' def revert(ui, repo, *pats, **opts):' | |||||
2136 | if not opts['rev'] and p2 != nullid: |
|
2129 | if not opts['rev'] and p2 != nullid: | |
2137 | raise util.Abort(_('uncommitted merge - please provide a ' |
|
2130 | raise util.Abort(_('uncommitted merge - please provide a ' | |
2138 | 'specific revision')) |
|
2131 | 'specific revision')) | |
2139 |
|
|
2132 | ctx = repo.changectx(opts['rev']) | |
2140 | mf = repo.manifest.read(repo.changelog.read(node)[0]) |
|
2133 | node = ctx.node() | |
|
2134 | mf = ctx.manifest() | |||
2141 | if node == parent: |
|
2135 | if node == parent: | |
2142 | pmf = mf |
|
2136 | pmf = mf | |
2143 | else: |
|
2137 | else: | |
@@ -2227,7 +2221,7 b' def revert(ui, repo, *pats, **opts):' | |||||
2227 | if pmf is None: |
|
2221 | if pmf is None: | |
2228 | # only need parent manifest in this unlikely case, |
|
2222 | # only need parent manifest in this unlikely case, | |
2229 | # so do not read by default |
|
2223 | # so do not read by default | |
2230 | pmf = repo.manifest.read(repo.changelog.read(parent)[0]) |
|
2224 | pmf = repo.changectx(parent).manifest() | |
2231 | if abs in pmf: |
|
2225 | if abs in pmf: | |
2232 | if mfentry: |
|
2226 | if mfentry: | |
2233 | # if version of file is same in parent and target |
|
2227 | # if version of file is same in parent and target | |
@@ -2461,9 +2455,10 b' def tags(ui, repo):' | |||||
2461 | hexfunc = ui.debugflag and hex or short |
|
2455 | hexfunc = ui.debugflag and hex or short | |
2462 | for t, n in l: |
|
2456 | for t, n in l: | |
2463 | try: |
|
2457 | try: | |
|
2458 | hn = hexfunc(n) | |||
2464 | r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n)) |
|
2459 | r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n)) | |
2465 |
except |
|
2460 | except revlog.LookupError: | |
2466 |
r = " ?: |
|
2461 | r = " ?:%s" % hn | |
2467 | if ui.quiet: |
|
2462 | if ui.quiet: | |
2468 | ui.write("%s\n" % t) |
|
2463 | ui.write("%s\n" % t) | |
2469 | else: |
|
2464 | else: | |
@@ -2488,7 +2483,7 b' def unbundle(ui, repo, fname, **opts):' | |||||
2488 | modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname) |
|
2483 | modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname) | |
2489 | return postincoming(ui, repo, modheads, opts['update']) |
|
2484 | return postincoming(ui, repo, modheads, opts['update']) | |
2490 |
|
2485 | |||
2491 |
def update(ui, repo, node=None, clean=False, |
|
2486 | def update(ui, repo, node=None, clean=False, date=None): | |
2492 | """update working directory |
|
2487 | """update working directory | |
2493 |
|
2488 | |||
2494 | Update the working directory to the specified revision. |
|
2489 | Update the working directory to the specified revision. | |
@@ -2508,36 +2503,11 b' def update(ui, repo, node=None, clean=Fa' | |||||
2508 | raise util.Abort(_("you can't specify a revision and a date")) |
|
2503 | raise util.Abort(_("you can't specify a revision and a date")) | |
2509 | node = cmdutil.finddate(ui, repo, date) |
|
2504 | node = cmdutil.finddate(ui, repo, date) | |
2510 |
|
2505 | |||
2511 | node = _lookup(repo, node, branch) |
|
|||
2512 | if clean: |
|
2506 | if clean: | |
2513 | return hg.clean(repo, node) |
|
2507 | return hg.clean(repo, node) | |
2514 | else: |
|
2508 | else: | |
2515 | return hg.update(repo, node) |
|
2509 | return hg.update(repo, node) | |
2516 |
|
2510 | |||
2517 | def _lookup(repo, node, branch=None): |
|
|||
2518 | if branch: |
|
|||
2519 | repo.ui.warn(_("the --branch option is deprecated, " |
|
|||
2520 | "please use 'hg branch' instead\n")) |
|
|||
2521 | br = repo.branchlookup(branch=branch) |
|
|||
2522 | found = [] |
|
|||
2523 | for x in br: |
|
|||
2524 | if branch in br[x]: |
|
|||
2525 | found.append(x) |
|
|||
2526 | if len(found) > 1: |
|
|||
2527 | repo.ui.warn(_("Found multiple heads for %s\n") % branch) |
|
|||
2528 | for x in found: |
|
|||
2529 | cmdutil.show_changeset(ui, repo, {}).show(changenode=x) |
|
|||
2530 | raise util.Abort("") |
|
|||
2531 | if len(found) == 1: |
|
|||
2532 | node = found[0] |
|
|||
2533 | repo.ui.warn(_("Using head %s for branch %s\n") |
|
|||
2534 | % (short(node), branch)) |
|
|||
2535 | else: |
|
|||
2536 | raise util.Abort(_("branch %s not found") % branch) |
|
|||
2537 | else: |
|
|||
2538 | node = node and repo.lookup(node) or repo.changelog.tip() |
|
|||
2539 | return node |
|
|||
2540 |
|
||||
2541 | def verify(ui, repo): |
|
2511 | def verify(ui, repo): | |
2542 | """verify the integrity of the repository |
|
2512 | """verify the integrity of the repository | |
2543 |
|
2513 | |||
@@ -2743,8 +2713,7 b' table = {' | |||||
2743 | _('hg grep [OPTION]... PATTERN [FILE]...')), |
|
2713 | _('hg grep [OPTION]... PATTERN [FILE]...')), | |
2744 | "heads": |
|
2714 | "heads": | |
2745 | (heads, |
|
2715 | (heads, | |
2746 | [('b', 'branches', None, _('show branches (DEPRECATED)')), |
|
2716 | [('', 'style', '', _('display using template map file')), | |
2747 | ('', 'style', '', _('display using template map file')), |
|
|||
2748 | ('r', 'rev', '', _('show only heads which are descendants of rev')), |
|
2717 | ('r', 'rev', '', _('show only heads which are descendants of rev')), | |
2749 | ('', 'template', '', _('display with template'))], |
|
2718 | ('', 'template', '', _('display with template'))], | |
2750 | _('hg heads [-r REV]')), |
|
2719 | _('hg heads [-r REV]')), | |
@@ -2755,7 +2724,7 b' table = {' | |||||
2755 | [('p', 'strip', 1, |
|
2724 | [('p', 'strip', 1, | |
2756 | _('directory strip option for patch. This has the same\n' |
|
2725 | _('directory strip option for patch. This has the same\n' | |
2757 | 'meaning as the corresponding patch option')), |
|
2726 | 'meaning as the corresponding patch option')), | |
2758 |
('b', 'base', '', _('base path |
|
2727 | ('b', 'base', '', _('base path')), | |
2759 | ('f', 'force', None, |
|
2728 | ('f', 'force', None, | |
2760 | _('skip check for outstanding uncommitted changes'))] + commitopts, |
|
2729 | _('skip check for outstanding uncommitted changes'))] + commitopts, | |
2761 | _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')), |
|
2730 | _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')), | |
@@ -2787,8 +2756,7 b' table = {' | |||||
2787 | _('hg locate [OPTION]... [PATTERN]...')), |
|
2756 | _('hg locate [OPTION]... [PATTERN]...')), | |
2788 | "^log|history": |
|
2757 | "^log|history": | |
2789 | (log, |
|
2758 | (log, | |
2790 | [('b', 'branches', None, _('show branches (DEPRECATED)')), |
|
2759 | [('f', 'follow', None, | |
2791 | ('f', 'follow', None, |
|
|||
2792 | _('follow changeset history, or file history across copies and renames')), |
|
2760 | _('follow changeset history, or file history across copies and renames')), | |
2793 | ('', 'follow-first', None, |
|
2761 | ('', 'follow-first', None, | |
2794 | _('only follow the first parent of merge changesets')), |
|
2762 | _('only follow the first parent of merge changesets')), | |
@@ -2809,8 +2777,7 b' table = {' | |||||
2809 | "manifest": (manifest, [], _('hg manifest [REV]')), |
|
2777 | "manifest": (manifest, [], _('hg manifest [REV]')), | |
2810 | "^merge": |
|
2778 | "^merge": | |
2811 | (merge, |
|
2779 | (merge, | |
2812 | [('b', 'branch', '', _('merge with head of a specific branch (DEPRECATED)')), |
|
2780 | [('f', 'force', None, _('force a merge with outstanding changes'))], | |
2813 | ('f', 'force', None, _('force a merge with outstanding changes'))], |
|
|||
2814 | _('hg merge [-f] [REV]')), |
|
2781 | _('hg merge [-f] [REV]')), | |
2815 | "outgoing|out": (outgoing, |
|
2782 | "outgoing|out": (outgoing, | |
2816 | [('M', 'no-merges', None, _('do not show merges')), |
|
2783 | [('M', 'no-merges', None, _('do not show merges')), | |
@@ -2825,8 +2792,7 b' table = {' | |||||
2825 | _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')), |
|
2792 | _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')), | |
2826 | "^parents": |
|
2793 | "^parents": | |
2827 | (parents, |
|
2794 | (parents, | |
2828 |
[(' |
|
2795 | [('r', 'rev', '', _('show parents from the specified rev')), | |
2829 | ('r', 'rev', '', _('show parents from the specified rev')), |
|
|||
2830 | ('', 'style', '', _('display using template map file')), |
|
2796 | ('', 'style', '', _('display using template map file')), | |
2831 | ('', 'template', '', _('display with template'))], |
|
2797 | ('', 'template', '', _('display with template'))], | |
2832 | _('hg parents [-r REV] [FILE]')), |
|
2798 | _('hg parents [-r REV] [FILE]')), | |
@@ -2929,8 +2895,7 b' table = {' | |||||
2929 | "tags": (tags, [], _('hg tags')), |
|
2895 | "tags": (tags, [], _('hg tags')), | |
2930 | "tip": |
|
2896 | "tip": | |
2931 | (tip, |
|
2897 | (tip, | |
2932 | [('b', 'branches', None, _('show branches (DEPRECATED)')), |
|
2898 | [('', 'style', '', _('display using template map file')), | |
2933 | ('', 'style', '', _('display using template map file')), |
|
|||
2934 | ('p', 'patch', None, _('show patch')), |
|
2899 | ('p', 'patch', None, _('show patch')), | |
2935 | ('', 'template', '', _('display with template'))], |
|
2900 | ('', 'template', '', _('display with template'))], | |
2936 | _('hg tip [-p]')), |
|
2901 | _('hg tip [-p]')), | |
@@ -2941,9 +2906,7 b' table = {' | |||||
2941 | _('hg unbundle [-u] FILE')), |
|
2906 | _('hg unbundle [-u] FILE')), | |
2942 | "^update|up|checkout|co": |
|
2907 | "^update|up|checkout|co": | |
2943 | (update, |
|
2908 | (update, | |
2944 | [('b', 'branch', '', |
|
2909 | [('C', 'clean', None, _('overwrite locally modified files')), | |
2945 | _('checkout the head of a specific branch (DEPRECATED)')), |
|
|||
2946 | ('C', 'clean', None, _('overwrite locally modified files')), |
|
|||
2947 | ('d', 'date', '', _('tipmost revision matching date'))], |
|
2910 | ('d', 'date', '', _('tipmost revision matching date'))], | |
2948 | _('hg update [-C] [-d DATE] [REV]')), |
|
2911 | _('hg update [-C] [-d DATE] [REV]')), | |
2949 | "verify": (verify, [], _('hg verify')), |
|
2912 | "verify": (verify, [], _('hg verify')), | |
@@ -3097,9 +3060,10 b' def load_extensions(ui):' | |||||
3097 | if uisetup: |
|
3060 | if uisetup: | |
3098 | uisetup(ui) |
|
3061 | uisetup(ui) | |
3099 | cmdtable = getattr(mod, 'cmdtable', {}) |
|
3062 | cmdtable = getattr(mod, 'cmdtable', {}) | |
3100 | for t in cmdtable: |
|
3063 | overrides = [cmd for cmd in cmdtable if cmd in table] | |
3101 | if t in table: |
|
3064 | if overrides: | |
3102 |
|
|
3065 | ui.warn(_("extension '%s' overrides commands: %s\n") | |
|
3066 | % (name, " ".join(overrides))) | |||
3103 | table.update(cmdtable) |
|
3067 | table.update(cmdtable) | |
3104 |
|
3068 | |||
3105 | def parseconfig(config): |
|
3069 | def parseconfig(config): |
@@ -6,9 +6,8 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | from demandload import demandload |
|
10 | import ancestor, bdiff, repo, revlog, util, os, errno | |
11 | demandload(globals(), "ancestor bdiff repo revlog util os") |
|
|||
12 |
|
11 | |||
13 | class changectx(object): |
|
12 | class changectx(object): | |
14 | """A changecontext object makes access to data related to a particular |
|
13 | """A changecontext object makes access to data related to a particular | |
@@ -84,21 +83,22 b' class changectx(object):' | |||||
84 | try: |
|
83 | try: | |
85 | return self._manifest[path] |
|
84 | return self._manifest[path] | |
86 | except KeyError: |
|
85 | except KeyError: | |
87 |
raise re |
|
86 | raise revlog.LookupError(_("'%s' not found in manifest") % path) | |
88 | if '_manifestdelta' in self.__dict__ or path in self.files(): |
|
87 | if '_manifestdelta' in self.__dict__ or path in self.files(): | |
89 | if path in self._manifestdelta: |
|
88 | if path in self._manifestdelta: | |
90 | return self._manifestdelta[path] |
|
89 | return self._manifestdelta[path] | |
91 | node, flag = self._repo.manifest.find(self._changeset[0], path) |
|
90 | node, flag = self._repo.manifest.find(self._changeset[0], path) | |
92 | if not node: |
|
91 | if not node: | |
93 |
raise re |
|
92 | raise revlog.LookupError(_("'%s' not found in manifest") % path) | |
94 |
|
93 | |||
95 | return node |
|
94 | return node | |
96 |
|
95 | |||
97 | def filectx(self, path, fileid=None): |
|
96 | def filectx(self, path, fileid=None, filelog=None): | |
98 | """get a file context from this changeset""" |
|
97 | """get a file context from this changeset""" | |
99 | if fileid is None: |
|
98 | if fileid is None: | |
100 | fileid = self.filenode(path) |
|
99 | fileid = self.filenode(path) | |
101 |
return filectx(self._repo, path, fileid=fileid, |
|
100 | return filectx(self._repo, path, fileid=fileid, | |
|
101 | changectx=self, filelog=filelog) | |||
102 |
|
102 | |||
103 | def filectxs(self): |
|
103 | def filectxs(self): | |
104 | """generate a file context for each file in this changeset's |
|
104 | """generate a file context for each file in this changeset's | |
@@ -126,16 +126,18 b' class filectx(object):' | |||||
126 | self._repo = repo |
|
126 | self._repo = repo | |
127 | self._path = path |
|
127 | self._path = path | |
128 |
|
128 | |||
129 |
assert changeid is not None |
|
129 | assert (changeid is not None | |
|
130 | or fileid is not None | |||
|
131 | or changectx is not None) | |||
130 |
|
132 | |||
131 | if filelog: |
|
133 | if filelog: | |
132 | self._filelog = filelog |
|
134 | self._filelog = filelog | |
133 | if changectx: |
|
|||
134 | self._changectx = changectx |
|
|||
135 | self._changeid = changectx.node() |
|
|||
136 |
|
135 | |||
137 | if fileid is None: |
|
136 | if fileid is None: | |
138 |
|
|
137 | if changectx is None: | |
|
138 | self._changeid = changeid | |||
|
139 | else: | |||
|
140 | self._changectx = changectx | |||
139 | else: |
|
141 | else: | |
140 | self._fileid = fileid |
|
142 | self._fileid = fileid | |
141 |
|
143 | |||
@@ -150,13 +152,10 b' class filectx(object):' | |||||
150 | self._changeid = self._filelog.linkrev(self._filenode) |
|
152 | self._changeid = self._filelog.linkrev(self._filenode) | |
151 | return self._changeid |
|
153 | return self._changeid | |
152 | elif name == '_filenode': |
|
154 | elif name == '_filenode': | |
153 | try: |
|
155 | if '_fileid' in self.__dict__: | |
154 | if '_fileid' in self.__dict__: |
|
156 | self._filenode = self._filelog.lookup(self._fileid) | |
155 | self._filenode = self._filelog.lookup(self._fileid) |
|
157 | else: | |
156 | else: |
|
158 | self._filenode = self._changectx.filenode(self._path) | |
157 | self._filenode = self._changectx.filenode(self._path) |
|
|||
158 | except revlog.RevlogError, inst: |
|
|||
159 | raise repo.LookupError(str(inst)) |
|
|||
160 | return self._filenode |
|
159 | return self._filenode | |
161 | elif name == '_filerev': |
|
160 | elif name == '_filerev': | |
162 | self._filerev = self._filelog.rev(self._filenode) |
|
161 | self._filerev = self._filelog.rev(self._filenode) | |
@@ -168,7 +167,7 b' class filectx(object):' | |||||
168 | try: |
|
167 | try: | |
169 | n = self._filenode |
|
168 | n = self._filenode | |
170 | return True |
|
169 | return True | |
171 |
except re |
|
170 | except revlog.LookupError: | |
172 | # file is missing |
|
171 | # file is missing | |
173 | return False |
|
172 | return False | |
174 |
|
173 | |||
@@ -379,13 +378,15 b' class workingctx(changectx):' | |||||
379 | """generate a manifest corresponding to the working directory""" |
|
378 | """generate a manifest corresponding to the working directory""" | |
380 |
|
379 | |||
381 | man = self._parents[0].manifest().copy() |
|
380 | man = self._parents[0].manifest().copy() | |
|
381 | is_exec = util.execfunc(self._repo.root, man.execf) | |||
|
382 | is_link = util.linkfunc(self._repo.root, man.linkf) | |||
382 | copied = self._repo.dirstate.copies() |
|
383 | copied = self._repo.dirstate.copies() | |
383 | modified, added, removed, deleted, unknown = self._status[:5] |
|
384 | modified, added, removed, deleted, unknown = self._status[:5] | |
384 | for i, l in (("a", added), ("m", modified), ("u", unknown)): |
|
385 | for i, l in (("a", added), ("m", modified), ("u", unknown)): | |
385 | for f in l: |
|
386 | for f in l: | |
386 | man[f] = man.get(copied.get(f, f), nullid) + i |
|
387 | man[f] = man.get(copied.get(f, f), nullid) + i | |
387 | try: |
|
388 | try: | |
388 |
man.set(f, |
|
389 | man.set(f, is_exec(f), is_link(f)) | |
389 | except OSError: |
|
390 | except OSError: | |
390 | pass |
|
391 | pass | |
391 |
|
392 | |||
@@ -424,9 +425,10 b' class workingctx(changectx):' | |||||
424 | def children(self): |
|
425 | def children(self): | |
425 | return [] |
|
426 | return [] | |
426 |
|
427 | |||
427 | def filectx(self, path): |
|
428 | def filectx(self, path, filelog=None): | |
428 | """get a file context from the working directory""" |
|
429 | """get a file context from the working directory""" | |
429 |
return workingfilectx(self._repo, path, workingctx=self |
|
430 | return workingfilectx(self._repo, path, workingctx=self, | |
|
431 | filelog=filelog) | |||
430 |
|
432 | |||
431 | def ancestor(self, c2): |
|
433 | def ancestor(self, c2): | |
432 | """return the ancestor context of self and c2""" |
|
434 | """return the ancestor context of self and c2""" | |
@@ -484,7 +486,7 b' class workingfilectx(filectx):' | |||||
484 | rp = self._repopath |
|
486 | rp = self._repopath | |
485 | if rp == self._path: |
|
487 | if rp == self._path: | |
486 | return None |
|
488 | return None | |
487 |
return rp, self._ |
|
489 | return rp, self._changectx._parents[0]._manifest.get(rp, nullid) | |
488 |
|
490 | |||
489 | def parents(self): |
|
491 | def parents(self): | |
490 | '''return parent filectxs, following copies if necessary''' |
|
492 | '''return parent filectxs, following copies if necessary''' | |
@@ -505,5 +507,12 b' class workingfilectx(filectx):' | |||||
505 | return [] |
|
507 | return [] | |
506 |
|
508 | |||
507 | def size(self): return os.stat(self._repo.wjoin(self._path)).st_size |
|
509 | def size(self): return os.stat(self._repo.wjoin(self._path)).st_size | |
|
510 | def date(self): | |||
|
511 | t, tz = self._changectx.date() | |||
|
512 | try: | |||
|
513 | return (os.lstat(repo.wjoin(self._path)).st_mtime, tz) | |||
|
514 | except OSError, err: | |||
|
515 | if err.errno != errno.ENOENT: raise | |||
|
516 | return (t, tz) | |||
508 |
|
517 | |||
509 | def cmp(self, text): return self._repo.wread(self._path) == text |
|
518 | def cmp(self, text): return self._repo.wread(self._path) == text |
@@ -8,9 +8,8 b' of the GNU General Public License, incor' | |||||
8 | """ |
|
8 | """ | |
9 |
|
9 | |||
10 | from node import * |
|
10 | from node import * | |
11 |
from i18n import |
|
11 | from i18n import _ | |
12 | from demandload import * |
|
12 | import struct, os, time, bisect, stat, strutil, util, re, errno | |
13 | demandload(globals(), "struct os time bisect stat strutil util re errno") |
|
|||
14 |
|
13 | |||
15 | class dirstate(object): |
|
14 | class dirstate(object): | |
16 | format = ">cllll" |
|
15 | format = ">cllll" | |
@@ -338,14 +337,13 b' class dirstate(object):' | |||||
338 | return ret |
|
337 | return ret | |
339 |
|
338 | |||
340 | def supported_type(self, f, st, verbose=False): |
|
339 | def supported_type(self, f, st, verbose=False): | |
341 | if stat.S_ISREG(st.st_mode): |
|
340 | if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode): | |
342 | return True |
|
341 | return True | |
343 | if verbose: |
|
342 | if verbose: | |
344 | kind = 'unknown' |
|
343 | kind = 'unknown' | |
345 | if stat.S_ISCHR(st.st_mode): kind = _('character device') |
|
344 | if stat.S_ISCHR(st.st_mode): kind = _('character device') | |
346 | elif stat.S_ISBLK(st.st_mode): kind = _('block device') |
|
345 | elif stat.S_ISBLK(st.st_mode): kind = _('block device') | |
347 | elif stat.S_ISFIFO(st.st_mode): kind = _('fifo') |
|
346 | elif stat.S_ISFIFO(st.st_mode): kind = _('fifo') | |
348 | elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link') |
|
|||
349 | elif stat.S_ISSOCK(st.st_mode): kind = _('socket') |
|
347 | elif stat.S_ISSOCK(st.st_mode): kind = _('socket') | |
350 | elif stat.S_ISDIR(st.st_mode): kind = _('directory') |
|
348 | elif stat.S_ISDIR(st.st_mode): kind = _('directory') | |
351 | self.ui.warn(_('%s: unsupported file type (type is %s)\n') % ( |
|
349 | self.ui.warn(_('%s: unsupported file type (type is %s)\n') % ( |
@@ -6,8 +6,7 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from revlog import * |
|
8 | from revlog import * | |
9 | from demandload import * |
|
9 | import os | |
10 | demandload(globals(), "os") |
|
|||
11 |
|
10 | |||
12 | class filelog(revlog): |
|
11 | class filelog(revlog): | |
13 | def __init__(self, opener, path, defversion=REVLOG_DEFAULT_VERSION): |
|
12 | def __init__(self, opener, path, defversion=REVLOG_DEFAULT_VERSION): |
@@ -8,10 +8,11 b'' | |||||
8 |
|
8 | |||
9 | from node import * |
|
9 | from node import * | |
10 | from repo import * |
|
10 | from repo import * | |
11 |
from |
|
11 | from i18n import _ | |
12 | from i18n import gettext as _ |
|
12 | import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo | |
13 | demandload(globals(), "localrepo bundlerepo httprepo sshrepo statichttprepo") |
|
13 | import errno, lock, os, shutil, util | |
14 | demandload(globals(), "errno lock os shutil util merge@_merge verify@_verify") |
|
14 | import merge as _merge | |
|
15 | import verify as _verify | |||
15 |
|
16 | |||
16 | def _local(path): |
|
17 | def _local(path): | |
17 | return (os.path.isfile(util.drop_scheme('file', path)) and |
|
18 | return (os.path.isfile(util.drop_scheme('file', path)) and |
@@ -6,6 +6,11 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | from mercurial.demandload import demandload |
|
9 | import hgweb_mod, hgwebdir_mod | |
10 | demandload(globals(), "mercurial.hgweb.hgweb_mod:hgweb") |
|
10 | ||
11 | demandload(globals(), "mercurial.hgweb.hgwebdir_mod:hgwebdir") |
|
11 | def hgweb(*args, **kwargs): | |
|
12 | return hgweb_mod.hgweb(*args, **kwargs) | |||
|
13 | ||||
|
14 | def hgwebdir(*args, **kwargs): | |||
|
15 | return hgwebdir_mod.hgwebdir(*args, **kwargs) | |||
|
16 |
@@ -7,7 +7,6 b'' | |||||
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | import os, mimetypes |
|
9 | import os, mimetypes | |
10 | import os.path |
|
|||
11 |
|
10 | |||
12 | def get_mtime(repo_path): |
|
11 | def get_mtime(repo_path): | |
13 | store_path = os.path.join(repo_path, ".hg") |
|
12 | store_path = os.path.join(repo_path, ".hg") |
@@ -6,17 +6,13 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | import os |
|
9 | import os, mimetypes, re, zlib, mimetools, cStringIO, sys | |
10 | import os.path |
|
10 | import tempfile, urllib, bz2 | |
11 | import mimetypes |
|
|||
12 | from mercurial.demandload import demandload |
|
|||
13 | demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile") |
|
|||
14 | demandload(globals(), 'urllib bz2') |
|
|||
15 | demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone,patch") |
|
|||
16 | demandload(globals(), "mercurial:revlog,templater") |
|
|||
17 | demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile,style_map") |
|
|||
18 | from mercurial.node import * |
|
11 | from mercurial.node import * | |
19 | from mercurial.i18n import gettext as _ |
|
12 | from mercurial.i18n import gettext as _ | |
|
13 | from mercurial import mdiff, ui, hg, util, archival, streamclone, patch | |||
|
14 | from mercurial import revlog, templater | |||
|
15 | from common import get_mtime, staticfile, style_map | |||
20 |
|
16 | |||
21 | def _up(p): |
|
17 | def _up(p): | |
22 | if p[0] != "/": |
|
18 | if p[0] != "/": | |
@@ -172,14 +168,10 b' class hgweb(object):' | |||||
172 | yield self.t("diffline", line=l) |
|
168 | yield self.t("diffline", line=l) | |
173 |
|
169 | |||
174 | r = self.repo |
|
170 | r = self.repo | |
175 |
c |
|
171 | c1 = r.changectx(node1) | |
176 |
|
|
172 | c2 = r.changectx(node2) | |
177 | change1 = cl.read(node1) |
|
173 | date1 = util.datestr(c1.date()) | |
178 | change2 = cl.read(node2) |
|
174 | date2 = util.datestr(c2.date()) | |
179 | mmap1 = mf.read(change1[0]) |
|
|||
180 | mmap2 = mf.read(change2[0]) |
|
|||
181 | date1 = util.datestr(change1[2]) |
|
|||
182 | date2 = util.datestr(change2[2]) |
|
|||
183 |
|
175 | |||
184 | modified, added, removed, deleted, unknown = r.status(node1, node2)[:5] |
|
176 | modified, added, removed, deleted, unknown = r.status(node1, node2)[:5] | |
185 | if files: |
|
177 | if files: | |
@@ -188,17 +180,17 b' class hgweb(object):' | |||||
188 |
|
180 | |||
189 | diffopts = patch.diffopts(self.repo.ui, untrusted=True) |
|
181 | diffopts = patch.diffopts(self.repo.ui, untrusted=True) | |
190 | for f in modified: |
|
182 | for f in modified: | |
191 |
to = |
|
183 | to = c1.filectx(f).data() | |
192 |
tn = |
|
184 | tn = c2.filectx(f).data() | |
193 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, |
|
185 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, | |
194 | opts=diffopts), f, tn) |
|
186 | opts=diffopts), f, tn) | |
195 | for f in added: |
|
187 | for f in added: | |
196 | to = None |
|
188 | to = None | |
197 |
tn = |
|
189 | tn = c2.filectx(f).data() | |
198 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, |
|
190 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, | |
199 | opts=diffopts), f, tn) |
|
191 | opts=diffopts), f, tn) | |
200 | for f in removed: |
|
192 | for f in removed: | |
201 |
to = |
|
193 | to = c1.filectx(f).data() | |
202 | tn = None |
|
194 | tn = None | |
203 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, |
|
195 | yield diffblock(mdiff.unidiff(to, date1, tn, date2, f, | |
204 | opts=diffopts), f, tn) |
|
196 | opts=diffopts), f, tn) | |
@@ -497,8 +489,6 b' class hgweb(object):' | |||||
497 | archives=self.archivelist(hex(node))) |
|
489 | archives=self.archivelist(hex(node))) | |
498 |
|
490 | |||
499 | def tags(self): |
|
491 | def tags(self): | |
500 | cl = self.repo.changelog |
|
|||
501 |
|
||||
502 | i = self.repo.tagslist() |
|
492 | i = self.repo.tagslist() | |
503 | i.reverse() |
|
493 | i.reverse() | |
504 |
|
494 | |||
@@ -509,7 +499,7 b' class hgweb(object):' | |||||
509 | continue |
|
499 | continue | |
510 | yield {"parity": self.stripes(parity), |
|
500 | yield {"parity": self.stripes(parity), | |
511 | "tag": k, |
|
501 | "tag": k, | |
512 |
"date": |
|
502 | "date": self.repo.changectx(n).date(), | |
513 | "node": hex(n)} |
|
503 | "node": hex(n)} | |
514 | parity += 1 |
|
504 | parity += 1 | |
515 |
|
505 | |||
@@ -519,8 +509,6 b' class hgweb(object):' | |||||
519 | entriesnotip=lambda **x: entries(True, **x)) |
|
509 | entriesnotip=lambda **x: entries(True, **x)) | |
520 |
|
510 | |||
521 | def summary(self): |
|
511 | def summary(self): | |
522 | cl = self.repo.changelog |
|
|||
523 |
|
||||
524 | i = self.repo.tagslist() |
|
512 | i = self.repo.tagslist() | |
525 | i.reverse() |
|
513 | i.reverse() | |
526 |
|
514 | |||
@@ -535,14 +523,11 b' class hgweb(object):' | |||||
535 | if count > 10: # limit to 10 tags |
|
523 | if count > 10: # limit to 10 tags | |
536 | break; |
|
524 | break; | |
537 |
|
525 | |||
538 | c = cl.read(n) |
|
|||
539 | t = c[2] |
|
|||
540 |
|
||||
541 | yield self.t("tagentry", |
|
526 | yield self.t("tagentry", | |
542 |
parity |
|
527 | parity=self.stripes(parity), | |
543 |
tag |
|
528 | tag=k, | |
544 |
node |
|
529 | node=hex(n), | |
545 |
date |
|
530 | date=self.repo.changectx(n).date()) | |
546 | parity += 1 |
|
531 | parity += 1 | |
547 |
|
532 | |||
548 | def heads(**map): |
|
533 | def heads(**map): | |
@@ -564,40 +549,38 b' class hgweb(object):' | |||||
564 |
|
549 | |||
565 | def changelist(**map): |
|
550 | def changelist(**map): | |
566 | parity = 0 |
|
551 | parity = 0 | |
567 | cl = self.repo.changelog |
|
|||
568 | l = [] # build a list in forward order for efficiency |
|
552 | l = [] # build a list in forward order for efficiency | |
569 | for i in xrange(start, end): |
|
553 | for i in xrange(start, end): | |
570 |
|
|
554 | ctx = self.repo.changectx(i) | |
571 |
|
|
555 | hn = hex(ctx.node()) | |
572 | hn = hex(n) |
|
|||
573 | t = changes[2] |
|
|||
574 |
|
556 | |||
575 | l.insert(0, self.t( |
|
557 | l.insert(0, self.t( | |
576 | 'shortlogentry', |
|
558 | 'shortlogentry', | |
577 |
parity |
|
559 | parity=parity, | |
578 |
author |
|
560 | author=ctx.user(), | |
579 |
desc |
|
561 | desc=ctx.description(), | |
580 |
date |
|
562 | date=ctx.date(), | |
581 |
rev |
|
563 | rev=i, | |
582 |
node |
|
564 | node=hn)) | |
583 | parity = 1 - parity |
|
565 | parity = 1 - parity | |
584 |
|
566 | |||
585 | yield l |
|
567 | yield l | |
586 |
|
568 | |||
|
569 | cl = self.repo.changelog | |||
587 | count = cl.count() |
|
570 | count = cl.count() | |
588 | start = max(0, count - self.maxchanges) |
|
571 | start = max(0, count - self.maxchanges) | |
589 | end = min(count, start + self.maxchanges) |
|
572 | end = min(count, start + self.maxchanges) | |
590 |
|
573 | |||
591 | yield self.t("summary", |
|
574 | yield self.t("summary", | |
592 |
desc |
|
575 | desc=self.config("web", "description", "unknown"), | |
593 |
owner |
|
576 | owner=(self.config("ui", "username") or # preferred | |
594 |
|
|
577 | self.config("web", "contact") or # deprecated | |
595 |
|
|
578 | self.config("web", "author", "unknown")), # also | |
596 |
lastchange |
|
579 | lastchange=cl.read(cl.tip())[2], | |
597 |
tags |
|
580 | tags=tagentries, | |
598 |
heads |
|
581 | heads=heads, | |
599 |
shortlog |
|
582 | shortlog=changelist, | |
600 |
node |
|
583 | node=hex(cl.tip()), | |
601 | archives=self.archivelist("tip")) |
|
584 | archives=self.archivelist("tip")) | |
602 |
|
585 | |||
603 | def filediff(self, fctx): |
|
586 | def filediff(self, fctx): | |
@@ -873,7 +856,7 b' class hgweb(object):' | |||||
873 | try: |
|
856 | try: | |
874 | req.write(self.filerevision(self.filectx(req))) |
|
857 | req.write(self.filerevision(self.filectx(req))) | |
875 | return |
|
858 | return | |
876 |
except |
|
859 | except revlog.LookupError: | |
877 | pass |
|
860 | pass | |
878 |
|
861 | |||
879 | req.write(self.manifest(self.changectx(req), path)) |
|
862 | req.write(self.manifest(self.changectx(req), path)) |
@@ -6,13 +6,12 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | import os |
|
9 | from mercurial import demandimport; demandimport.enable() | |
10 | from mercurial.demandload import demandload |
|
10 | import os, mimetools, cStringIO | |
11 | demandload(globals(), "mimetools cStringIO") |
|
|||
12 | demandload(globals(), "mercurial:ui,hg,util,templater") |
|
|||
13 | demandload(globals(), "mercurial.hgweb.hgweb_mod:hgweb") |
|
|||
14 | demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile,style_map") |
|
|||
15 | from mercurial.i18n import gettext as _ |
|
11 | from mercurial.i18n import gettext as _ | |
|
12 | from mercurial import ui, hg, util, templater | |||
|
13 | from common import get_mtime, staticfile, style_map | |||
|
14 | from hgweb_mod import hgweb | |||
16 |
|
15 | |||
17 | # This is a stopgap |
|
16 | # This is a stopgap | |
18 | class hgwebdir(object): |
|
17 | class hgwebdir(object): |
@@ -6,8 +6,7 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | from mercurial.demandload import demandload |
|
9 | import socket, cgi, errno | |
10 | demandload(globals(), "socket sys cgi os errno") |
|
|||
11 | from mercurial.i18n import gettext as _ |
|
10 | from mercurial.i18n import gettext as _ | |
12 |
|
11 | |||
13 | class wsgiapplication(object): |
|
12 | class wsgiapplication(object): |
@@ -6,11 +6,11 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | from mercurial.demandload import demandload |
|
9 | import os, sys, errno, urllib, BaseHTTPServer, socket, SocketServer, traceback | |
10 | import os, sys, errno |
|
10 | from mercurial import ui, hg, util, templater | |
11 | demandload(globals(), "urllib BaseHTTPServer socket SocketServer traceback") |
|
11 | from hgweb_mod import hgweb | |
12 | demandload(globals(), "mercurial:ui,hg,util,templater") |
|
12 | from hgwebdir_mod import hgwebdir | |
13 | demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:wsgiapplication") |
|
13 | from request import wsgiapplication | |
14 | from mercurial.i18n import gettext as _ |
|
14 | from mercurial.i18n import gettext as _ | |
15 |
|
15 | |||
16 | def _splitURI(uri): |
|
16 | def _splitURI(uri): |
@@ -8,10 +8,9 b'' | |||||
8 |
|
8 | |||
9 | from node import * |
|
9 | from node import * | |
10 | from remoterepo import * |
|
10 | from remoterepo import * | |
11 |
from i18n import |
|
11 | from i18n import _ | |
12 | from demandload import * |
|
12 | import hg, os, urllib, urllib2, urlparse, zlib, util, httplib | |
13 | demandload(globals(), "hg os urllib urllib2 urlparse zlib util httplib") |
|
13 | import errno, keepalive, tempfile, socket, changegroup | |
14 | demandload(globals(), "errno keepalive tempfile socket changegroup") |
|
|||
15 |
|
14 | |||
16 | class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm): |
|
15 | class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm): | |
17 | def __init__(self, ui): |
|
16 | def __init__(self, ui): |
@@ -7,9 +7,7 b' This software may be used and distribute' | |||||
7 | of the GNU General Public License, incorporated herein by reference. |
|
7 | of the GNU General Public License, incorporated herein by reference. | |
8 | """ |
|
8 | """ | |
9 |
|
9 | |||
10 | # the import from gettext is _really_ slow |
|
10 | import gettext | |
11 | # for now we use a dummy function |
|
11 | t = gettext.translation('hg', fallback=1) | |
12 | gettext = lambda x: x |
|
12 | gettext = t.gettext | |
13 |
|
|
13 | _ = gettext | |
14 | #t = gettext.translation('hg', '/usr/share/locale', fallback=1) |
|
|||
15 | #gettext = t.gettext |
|
@@ -6,13 +6,11 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | from demandload import * |
|
10 | import repo, appendfile, changegroup | |
11 | import repo |
|
11 | import changelog, dirstate, filelog, manifest, context | |
12 | demandload(globals(), "appendfile changegroup") |
|
12 | import re, lock, transaction, tempfile, stat, mdiff, errno, ui | |
13 | demandload(globals(), "changelog dirstate filelog manifest context") |
|
13 | import os, revlog, time, util | |
14 | demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") |
|
|||
15 | demandload(globals(), "os revlog time util") |
|
|||
16 |
|
14 | |||
17 | class localrepository(repo.repository): |
|
15 | class localrepository(repo.repository): | |
18 | capabilities = ('lookup', 'changegroupsubset') |
|
16 | capabilities = ('lookup', 'changegroupsubset') | |
@@ -119,10 +117,14 b' class localrepository(repo.repository):' | |||||
119 | self.tagscache = None |
|
117 | self.tagscache = None | |
120 | self.branchcache = None |
|
118 | self.branchcache = None | |
121 | self.nodetagscache = None |
|
119 | self.nodetagscache = None | |
122 |
self. |
|
120 | self.filterpats = {} | |
123 | self.decodepats = None |
|
|||
124 | self.transhandle = None |
|
121 | self.transhandle = None | |
125 |
|
122 | |||
|
123 | self._link = lambda x: False | |||
|
124 | if util.checklink(self.root): | |||
|
125 | r = self.root # avoid circular reference in lambda | |||
|
126 | self._link = lambda x: util.is_link(os.path.join(r, x)) | |||
|
127 | ||||
126 | self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) |
|
128 | self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) | |
127 |
|
129 | |||
128 | def url(self): |
|
130 | def url(self): | |
@@ -319,7 +321,7 b' class localrepository(repo.repository):' | |||||
319 | rev = c.rev() |
|
321 | rev = c.rev() | |
320 | try: |
|
322 | try: | |
321 | fnode = c.filenode('.hgtags') |
|
323 | fnode = c.filenode('.hgtags') | |
322 |
except re |
|
324 | except revlog.LookupError: | |
323 | continue |
|
325 | continue | |
324 | ret.append((rev, node, fnode)) |
|
326 | ret.append((rev, node, fnode)) | |
325 | if fnode in last: |
|
327 | if fnode in last: | |
@@ -480,17 +482,15 b' class localrepository(repo.repository):' | |||||
480 | def wfile(self, f, mode='r'): |
|
482 | def wfile(self, f, mode='r'): | |
481 | return self.wopener(f, mode) |
|
483 | return self.wopener(f, mode) | |
482 |
|
484 | |||
483 |
def |
|
485 | def _filter(self, filter, filename, data): | |
484 | if self.encodepats == None: |
|
486 | if filter not in self.filterpats: | |
485 | l = [] |
|
487 | l = [] | |
486 |
for pat, cmd in self.ui.configitems( |
|
488 | for pat, cmd in self.ui.configitems(filter): | |
487 | mf = util.matcher(self.root, "", [pat], [], [])[1] |
|
489 | mf = util.matcher(self.root, "", [pat], [], [])[1] | |
488 | l.append((mf, cmd)) |
|
490 | l.append((mf, cmd)) | |
489 |
self. |
|
491 | self.filterpats[filter] = l | |
490 |
|
492 | |||
491 | data = self.wopener(filename, 'r').read() |
|
493 | for mf, cmd in self.filterpats[filter]: | |
492 |
|
||||
493 | for mf, cmd in self.encodepats: |
|
|||
494 | if mf(filename): |
|
494 | if mf(filename): | |
495 | self.ui.debug(_("filtering %s through %s\n") % (filename, cmd)) |
|
495 | self.ui.debug(_("filtering %s through %s\n") % (filename, cmd)) | |
496 | data = util.filter(data, cmd) |
|
496 | data = util.filter(data, cmd) | |
@@ -498,23 +498,32 b' class localrepository(repo.repository):' | |||||
498 |
|
498 | |||
499 | return data |
|
499 | return data | |
500 |
|
500 | |||
501 |
def |
|
501 | def wread(self, filename): | |
502 | if self.decodepats == None: |
|
502 | if self._link(filename): | |
503 | l = [] |
|
503 | data = os.readlink(self.wjoin(filename)) | |
504 | for pat, cmd in self.ui.configitems("decode"): |
|
504 | else: | |
505 | mf = util.matcher(self.root, "", [pat], [], [])[1] |
|
505 | data = self.wopener(filename, 'r').read() | |
506 | l.append((mf, cmd)) |
|
506 | return self._filter("encode", filename, data) | |
507 | self.decodepats = l |
|
|||
508 |
|
507 | |||
509 | for mf, cmd in self.decodepats: |
|
508 | def wwrite(self, filename, data, flags): | |
510 | if mf(filename): |
|
509 | data = self._filter("decode", filename, data) | |
511 | self.ui.debug(_("filtering %s through %s\n") % (filename, cmd)) |
|
510 | if "l" in flags: | |
512 | data = util.filter(data, cmd) |
|
511 | try: | |
513 | break |
|
512 | os.unlink(self.wjoin(filename)) | |
|
513 | except OSError: | |||
|
514 | pass | |||
|
515 | os.symlink(data, self.wjoin(filename)) | |||
|
516 | else: | |||
|
517 | try: | |||
|
518 | if self._link(filename): | |||
|
519 | os.unlink(self.wjoin(filename)) | |||
|
520 | except OSError: | |||
|
521 | pass | |||
|
522 | self.wopener(filename, 'w').write(data) | |||
|
523 | util.set_exec(self.wjoin(filename), "x" in flags) | |||
514 |
|
524 | |||
515 | if fd: |
|
525 | def wwritedata(self, filename, data): | |
516 |
|
|
526 | return self._filter("decode", filename, data) | |
517 | return self.wopener(filename, 'w').write(data) |
|
|||
518 |
|
527 | |||
519 | def transaction(self): |
|
528 | def transaction(self): | |
520 | tr = self.transhandle |
|
529 | tr = self.transhandle | |
@@ -636,11 +645,11 b' class localrepository(repo.repository):' | |||||
636 | changelist.append(fn) |
|
645 | changelist.append(fn) | |
637 | return fl.add(t, meta, transaction, linkrev, fp1, fp2) |
|
646 | return fl.add(t, meta, transaction, linkrev, fp1, fp2) | |
638 |
|
647 | |||
639 | def rawcommit(self, files, text, user, date, p1=None, p2=None, wlock=None): |
|
648 | def rawcommit(self, files, text, user, date, p1=None, p2=None, wlock=None, extra={}): | |
640 | if p1 is None: |
|
649 | if p1 is None: | |
641 | p1, p2 = self.dirstate.parents() |
|
650 | p1, p2 = self.dirstate.parents() | |
642 | return self.commit(files=files, text=text, user=user, date=date, |
|
651 | return self.commit(files=files, text=text, user=user, date=date, | |
643 | p1=p1, p2=p2, wlock=wlock) |
|
652 | p1=p1, p2=p2, wlock=wlock, extra=extra) | |
644 |
|
653 | |||
645 | def commit(self, files=None, text="", user=None, date=None, |
|
654 | def commit(self, files=None, text="", user=None, date=None, | |
646 | match=util.always, force=False, lock=None, wlock=None, |
|
655 | match=util.always, force=False, lock=None, wlock=None, | |
@@ -714,12 +723,14 b' class localrepository(repo.repository):' | |||||
714 | new = {} |
|
723 | new = {} | |
715 | linkrev = self.changelog.count() |
|
724 | linkrev = self.changelog.count() | |
716 | commit.sort() |
|
725 | commit.sort() | |
|
726 | is_exec = util.execfunc(self.root, m1.execf) | |||
|
727 | is_link = util.linkfunc(self.root, m1.linkf) | |||
717 | for f in commit: |
|
728 | for f in commit: | |
718 | self.ui.note(f + "\n") |
|
729 | self.ui.note(f + "\n") | |
719 | try: |
|
730 | try: | |
720 | new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) |
|
731 | new[f] = self.filecommit(f, m1, m2, linkrev, tr, changed) | |
721 |
m1.set(f, |
|
732 | m1.set(f, is_exec(f), is_link(f)) | |
722 |
except |
|
733 | except OSError: | |
723 | if use_dirstate: |
|
734 | if use_dirstate: | |
724 | self.ui.warn(_("trouble committing %s!\n") % f) |
|
735 | self.ui.warn(_("trouble committing %s!\n") % f) | |
725 | raise |
|
736 | raise | |
@@ -729,11 +740,13 b' class localrepository(repo.repository):' | |||||
729 | # update manifest |
|
740 | # update manifest | |
730 | m1.update(new) |
|
741 | m1.update(new) | |
731 | remove.sort() |
|
742 | remove.sort() | |
|
743 | removed = [] | |||
732 |
|
744 | |||
733 | for f in remove: |
|
745 | for f in remove: | |
734 | if f in m1: |
|
746 | if f in m1: | |
735 | del m1[f] |
|
747 | del m1[f] | |
736 | mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], (new, remove)) |
|
748 | removed.append(f) | |
|
749 | mn = self.manifest.add(m1, tr, linkrev, c1[0], c2[0], (new, removed)) | |||
737 |
|
750 | |||
738 | # add changeset |
|
751 | # add changeset | |
739 | new = new.keys() |
|
752 | new = new.keys() | |
@@ -748,8 +761,10 b' class localrepository(repo.repository):' | |||||
748 | edittext.append("HG: user: %s" % user) |
|
761 | edittext.append("HG: user: %s" % user) | |
749 | if p2 != nullid: |
|
762 | if p2 != nullid: | |
750 | edittext.append("HG: branch merge") |
|
763 | edittext.append("HG: branch merge") | |
|
764 | if branchname: | |||
|
765 | edittext.append("HG: branch %s" % util.tolocal(branchname)) | |||
751 | edittext.extend(["HG: changed %s" % f for f in changed]) |
|
766 | edittext.extend(["HG: changed %s" % f for f in changed]) | |
752 | edittext.extend(["HG: removed %s" % f for f in remove]) |
|
767 | edittext.extend(["HG: removed %s" % f for f in removed]) | |
753 | if not changed and not remove: |
|
768 | if not changed and not remove: | |
754 | edittext.append("HG: no files changed") |
|
769 | edittext.append("HG: no files changed") | |
755 | edittext.append("") |
|
770 | edittext.append("") | |
@@ -767,17 +782,20 b' class localrepository(repo.repository):' | |||||
767 | text = '\n'.join(lines) |
|
782 | text = '\n'.join(lines) | |
768 | if branchname: |
|
783 | if branchname: | |
769 | extra["branch"] = branchname |
|
784 | extra["branch"] = branchname | |
770 | n = self.changelog.add(mn, changed + remove, text, tr, p1, p2, |
|
785 | n = self.changelog.add(mn, changed + removed, text, tr, p1, p2, | |
771 | user, date, extra) |
|
786 | user, date, extra) | |
772 | self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, |
|
787 | self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, | |
773 | parent2=xp2) |
|
788 | parent2=xp2) | |
774 | tr.close() |
|
789 | tr.close() | |
775 |
|
790 | |||
|
791 | if self.branchcache and "branch" in extra: | |||
|
792 | self.branchcache[util.tolocal(extra["branch"])] = n | |||
|
793 | ||||
776 | if use_dirstate or update_dirstate: |
|
794 | if use_dirstate or update_dirstate: | |
777 | self.dirstate.setparents(n) |
|
795 | self.dirstate.setparents(n) | |
778 | if use_dirstate: |
|
796 | if use_dirstate: | |
779 | self.dirstate.update(new, "n") |
|
797 | self.dirstate.update(new, "n") | |
780 | self.dirstate.forget(remove) |
|
798 | self.dirstate.forget(removed) | |
781 |
|
799 | |||
782 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) |
|
800 | self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2) | |
783 | return n |
|
801 | return n | |
@@ -877,9 +895,11 b' class localrepository(repo.repository):' | |||||
877 | # generate a pseudo-manifest for the working dir |
|
895 | # generate a pseudo-manifest for the working dir | |
878 | # XXX: create it in dirstate.py ? |
|
896 | # XXX: create it in dirstate.py ? | |
879 | mf2 = mfmatches(self.dirstate.parents()[0]) |
|
897 | mf2 = mfmatches(self.dirstate.parents()[0]) | |
|
898 | is_exec = util.execfunc(self.root, mf2.execf) | |||
|
899 | is_link = util.linkfunc(self.root, mf2.linkf) | |||
880 | for f in lookup + modified + added: |
|
900 | for f in lookup + modified + added: | |
881 | mf2[f] = "" |
|
901 | mf2[f] = "" | |
882 |
mf2.set(f, |
|
902 | mf2.set(f, is_exec(f), is_link(f)) | |
883 | for f in removed: |
|
903 | for f in removed: | |
884 | if f in mf2: |
|
904 | if f in mf2: | |
885 | del mf2[f] |
|
905 | del mf2[f] | |
@@ -918,11 +938,12 b' class localrepository(repo.repository):' | |||||
918 | wlock = self.wlock() |
|
938 | wlock = self.wlock() | |
919 | for f in list: |
|
939 | for f in list: | |
920 | p = self.wjoin(f) |
|
940 | p = self.wjoin(f) | |
921 |
i |
|
941 | islink = os.path.islink(p) | |
|
942 | if not islink and not os.path.exists(p): | |||
922 | self.ui.warn(_("%s does not exist!\n") % f) |
|
943 | self.ui.warn(_("%s does not exist!\n") % f) | |
923 | elif not os.path.isfile(p): |
|
944 | elif not islink and not os.path.isfile(p): | |
924 |
self.ui.warn(_("%s not added: only files |
|
945 | self.ui.warn(_("%s not added: only files and symlinks " | |
925 | % f) |
|
946 | "supported currently\n") % f) | |
926 | elif self.dirstate.state(f) in 'an': |
|
947 | elif self.dirstate.state(f) in 'an': | |
927 | self.ui.warn(_("%s already tracked!\n") % f) |
|
948 | self.ui.warn(_("%s already tracked!\n") % f) | |
928 | else: |
|
949 | else: | |
@@ -969,8 +990,7 b' class localrepository(repo.repository):' | |||||
969 | self.ui.warn("%s not removed!\n" % f) |
|
990 | self.ui.warn("%s not removed!\n" % f) | |
970 | else: |
|
991 | else: | |
971 | t = self.file(f).read(m[f]) |
|
992 | t = self.file(f).read(m[f]) | |
972 | self.wwrite(f, t) |
|
993 | self.wwrite(f, t, m.flags(f)) | |
973 | util.set_exec(self.wjoin(f), m.execf(f)) |
|
|||
974 | self.dirstate.update([f], "n") |
|
994 | self.dirstate.update([f], "n") | |
975 |
|
995 | |||
976 | def copy(self, source, dest, wlock=None): |
|
996 | def copy(self, source, dest, wlock=None): | |
@@ -993,112 +1013,6 b' class localrepository(repo.repository):' | |||||
993 | heads.sort() |
|
1013 | heads.sort() | |
994 | return [n for (r, n) in heads] |
|
1014 | return [n for (r, n) in heads] | |
995 |
|
1015 | |||
996 | # branchlookup returns a dict giving a list of branches for |
|
|||
997 | # each head. A branch is defined as the tag of a node or |
|
|||
998 | # the branch of the node's parents. If a node has multiple |
|
|||
999 | # branch tags, tags are eliminated if they are visible from other |
|
|||
1000 | # branch tags. |
|
|||
1001 | # |
|
|||
1002 | # So, for this graph: a->b->c->d->e |
|
|||
1003 | # \ / |
|
|||
1004 | # aa -----/ |
|
|||
1005 | # a has tag 2.6.12 |
|
|||
1006 | # d has tag 2.6.13 |
|
|||
1007 | # e would have branch tags for 2.6.12 and 2.6.13. Because the node |
|
|||
1008 | # for 2.6.12 can be reached from the node 2.6.13, that is eliminated |
|
|||
1009 | # from the list. |
|
|||
1010 | # |
|
|||
1011 | # It is possible that more than one head will have the same branch tag. |
|
|||
1012 | # callers need to check the result for multiple heads under the same |
|
|||
1013 | # branch tag if that is a problem for them (ie checkout of a specific |
|
|||
1014 | # branch). |
|
|||
1015 | # |
|
|||
1016 | # passing in a specific branch will limit the depth of the search |
|
|||
1017 | # through the parents. It won't limit the branches returned in the |
|
|||
1018 | # result though. |
|
|||
1019 | def branchlookup(self, heads=None, branch=None): |
|
|||
1020 | if not heads: |
|
|||
1021 | heads = self.heads() |
|
|||
1022 | headt = [ h for h in heads ] |
|
|||
1023 | chlog = self.changelog |
|
|||
1024 | branches = {} |
|
|||
1025 | merges = [] |
|
|||
1026 | seenmerge = {} |
|
|||
1027 |
|
||||
1028 | # traverse the tree once for each head, recording in the branches |
|
|||
1029 | # dict which tags are visible from this head. The branches |
|
|||
1030 | # dict also records which tags are visible from each tag |
|
|||
1031 | # while we traverse. |
|
|||
1032 | while headt or merges: |
|
|||
1033 | if merges: |
|
|||
1034 | n, found = merges.pop() |
|
|||
1035 | visit = [n] |
|
|||
1036 | else: |
|
|||
1037 | h = headt.pop() |
|
|||
1038 | visit = [h] |
|
|||
1039 | found = [h] |
|
|||
1040 | seen = {} |
|
|||
1041 | while visit: |
|
|||
1042 | n = visit.pop() |
|
|||
1043 | if n in seen: |
|
|||
1044 | continue |
|
|||
1045 | pp = chlog.parents(n) |
|
|||
1046 | tags = self.nodetags(n) |
|
|||
1047 | if tags: |
|
|||
1048 | for x in tags: |
|
|||
1049 | if x == 'tip': |
|
|||
1050 | continue |
|
|||
1051 | for f in found: |
|
|||
1052 | branches.setdefault(f, {})[n] = 1 |
|
|||
1053 | branches.setdefault(n, {})[n] = 1 |
|
|||
1054 | break |
|
|||
1055 | if n not in found: |
|
|||
1056 | found.append(n) |
|
|||
1057 | if branch in tags: |
|
|||
1058 | continue |
|
|||
1059 | seen[n] = 1 |
|
|||
1060 | if pp[1] != nullid and n not in seenmerge: |
|
|||
1061 | merges.append((pp[1], [x for x in found])) |
|
|||
1062 | seenmerge[n] = 1 |
|
|||
1063 | if pp[0] != nullid: |
|
|||
1064 | visit.append(pp[0]) |
|
|||
1065 | # traverse the branches dict, eliminating branch tags from each |
|
|||
1066 | # head that are visible from another branch tag for that head. |
|
|||
1067 | out = {} |
|
|||
1068 | viscache = {} |
|
|||
1069 | for h in heads: |
|
|||
1070 | def visible(node): |
|
|||
1071 | if node in viscache: |
|
|||
1072 | return viscache[node] |
|
|||
1073 | ret = {} |
|
|||
1074 | visit = [node] |
|
|||
1075 | while visit: |
|
|||
1076 | x = visit.pop() |
|
|||
1077 | if x in viscache: |
|
|||
1078 | ret.update(viscache[x]) |
|
|||
1079 | elif x not in ret: |
|
|||
1080 | ret[x] = 1 |
|
|||
1081 | if x in branches: |
|
|||
1082 | visit[len(visit):] = branches[x].keys() |
|
|||
1083 | viscache[node] = ret |
|
|||
1084 | return ret |
|
|||
1085 | if h not in branches: |
|
|||
1086 | continue |
|
|||
1087 | # O(n^2), but somewhat limited. This only searches the |
|
|||
1088 | # tags visible from a specific head, not all the tags in the |
|
|||
1089 | # whole repo. |
|
|||
1090 | for b in branches[h]: |
|
|||
1091 | vis = False |
|
|||
1092 | for bb in branches[h].keys(): |
|
|||
1093 | if b != bb: |
|
|||
1094 | if b in visible(bb): |
|
|||
1095 | vis = True |
|
|||
1096 | break |
|
|||
1097 | if not vis: |
|
|||
1098 | l = out.setdefault(h, []) |
|
|||
1099 | l[len(l):] = self.nodetags(b) |
|
|||
1100 | return out |
|
|||
1101 |
|
||||
1102 | def branches(self, nodes): |
|
1016 | def branches(self, nodes): | |
1103 | if not nodes: |
|
1017 | if not nodes: | |
1104 | nodes = [self.changelog.tip()] |
|
1018 | nodes = [self.changelog.tip()] |
@@ -5,8 +5,7 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import * |
|
8 | import errno, os, socket, time, util | |
9 | demandload(globals(), 'errno os socket time util') |
|
|||
10 |
|
9 | |||
11 | class LockException(IOError): |
|
10 | class LockException(IOError): | |
12 | def __init__(self, errno, strerror, filename, desc): |
|
11 | def __init__(self, errno, strerror, filename, desc): |
@@ -5,9 +5,8 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 |
from i18n import |
|
8 | from i18n import _ | |
9 | from demandload import * |
|
9 | import os, smtplib, templater, util | |
10 | demandload(globals(), "os re smtplib templater util") |
|
|||
11 |
|
10 | |||
12 | def _smtp(ui): |
|
11 | def _smtp(ui): | |
13 | '''send mail using smtp.''' |
|
12 | '''send mail using smtp.''' |
@@ -6,10 +6,8 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from revlog import * |
|
8 | from revlog import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | from demandload import * |
|
10 | import array, bisect, struct, mdiff | |
11 | demandload(globals(), "array bisect struct") |
|
|||
12 | demandload(globals(), "mdiff") |
|
|||
13 |
|
11 | |||
14 | class manifestdict(dict): |
|
12 | class manifestdict(dict): | |
15 | def __init__(self, mapping=None, flags=None): |
|
13 | def __init__(self, mapping=None, flags=None): |
@@ -5,9 +5,7 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
8 | import bdiff, mpatch, re, struct, util | |
9 | import bdiff, mpatch |
|
|||
10 | demandload(globals(), "re struct util") |
|
|||
11 |
|
9 | |||
12 | def splitnewlines(text): |
|
10 | def splitnewlines(text): | |
13 | '''like str.splitlines, but only split on newlines.''' |
|
11 | '''like str.splitlines, but only split on newlines.''' |
@@ -6,9 +6,8 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | from demandload import * |
|
10 | import errno, util, os, tempfile | |
11 | demandload(globals(), "errno util os tempfile") |
|
|||
12 |
|
11 | |||
13 | def filemerge(repo, fw, fo, wctx, mctx): |
|
12 | def filemerge(repo, fw, fo, wctx, mctx): | |
14 | """perform a 3-way merge in the working directory |
|
13 | """perform a 3-way merge in the working directory | |
@@ -21,8 +20,9 b' def filemerge(repo, fw, fo, wctx, mctx):' | |||||
21 | def temp(prefix, ctx): |
|
20 | def temp(prefix, ctx): | |
22 | pre = "%s~%s." % (os.path.basename(ctx.path()), prefix) |
|
21 | pre = "%s~%s." % (os.path.basename(ctx.path()), prefix) | |
23 | (fd, name) = tempfile.mkstemp(prefix=pre) |
|
22 | (fd, name) = tempfile.mkstemp(prefix=pre) | |
|
23 | data = repo.wwritedata(ctx.path(), ctx.data()) | |||
24 | f = os.fdopen(fd, "wb") |
|
24 | f = os.fdopen(fd, "wb") | |
25 | repo.wwrite(ctx.path(), ctx.data(), f) |
|
25 | f.write(data) | |
26 | f.close() |
|
26 | f.close() | |
27 | return name |
|
27 | return name | |
28 |
|
28 | |||
@@ -220,12 +220,17 b' def manifestmerge(repo, p1, p2, pa, over' | |||||
220 | copy = {} |
|
220 | copy = {} | |
221 |
|
221 | |||
222 | def fmerge(f, f2=None, fa=None): |
|
222 | def fmerge(f, f2=None, fa=None): | |
223 |
"""merge |
|
223 | """merge flags""" | |
224 | if not f2: |
|
224 | if not f2: | |
225 | f2 = f |
|
225 | f2 = f | |
226 | fa = f |
|
226 | fa = f | |
227 | a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) |
|
227 | a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2) | |
228 |
|
|
228 | if ((a^b) | (a^c)) ^ a: | |
|
229 | return 'x' | |||
|
230 | a, b, c = ma.linkf(fa), m1.linkf(f), m2.linkf(f2) | |||
|
231 | if ((a^b) | (a^c)) ^ a: | |||
|
232 | return 'l' | |||
|
233 | return '' | |||
229 |
|
234 | |||
230 | def act(msg, m, f, *args): |
|
235 | def act(msg, m, f, *args): | |
231 | repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) |
|
236 | repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) | |
@@ -250,21 +255,21 b' def manifestmerge(repo, p1, p2, pa, over' | |||||
250 | # is remote's version newer? |
|
255 | # is remote's version newer? | |
251 | # or are we going back in time and clean? |
|
256 | # or are we going back in time and clean? | |
252 | elif overwrite or m2[f] != a or (backwards and not n[20:]): |
|
257 | elif overwrite or m2[f] != a or (backwards and not n[20:]): | |
253 |
act("remote is newer", "g", f, m2. |
|
258 | act("remote is newer", "g", f, m2.flags(f)) | |
254 | # local is newer, not overwrite, check mode bits |
|
259 | # local is newer, not overwrite, check mode bits | |
255 |
elif fmerge(f) != m1. |
|
260 | elif fmerge(f) != m1.flags(f): | |
256 |
act("update permissions", "e", f, m2. |
|
261 | act("update permissions", "e", f, m2.flags(f)) | |
257 | # contents same, check mode bits |
|
262 | # contents same, check mode bits | |
258 |
elif m1. |
|
263 | elif m1.flags(f) != m2.flags(f): | |
259 |
if overwrite or fmerge(f) != m1. |
|
264 | if overwrite or fmerge(f) != m1.flags(f): | |
260 |
act("update permissions", "e", f, m2. |
|
265 | act("update permissions", "e", f, m2.flags(f)) | |
261 | elif f in copied: |
|
266 | elif f in copied: | |
262 | continue |
|
267 | continue | |
263 | elif f in copy: |
|
268 | elif f in copy: | |
264 | f2 = copy[f] |
|
269 | f2 = copy[f] | |
265 | if f2 not in m2: # directory rename |
|
270 | if f2 not in m2: # directory rename | |
266 | act("remote renamed directory to " + f2, "d", |
|
271 | act("remote renamed directory to " + f2, "d", | |
267 |
f, None, f2, m1. |
|
272 | f, None, f2, m1.flags(f)) | |
268 | elif f2 in m1: # case 2 A,B/B/B |
|
273 | elif f2 in m1: # case 2 A,B/B/B | |
269 | act("local copied to " + f2, "m", |
|
274 | act("local copied to " + f2, "m", | |
270 | f, f2, f, fmerge(f, f2, f2), False) |
|
275 | f, f2, f, fmerge(f, f2, f2), False) | |
@@ -295,7 +300,7 b' def manifestmerge(repo, p1, p2, pa, over' | |||||
295 | f2 = copy[f] |
|
300 | f2 = copy[f] | |
296 | if f2 not in m1: # directory rename |
|
301 | if f2 not in m1: # directory rename | |
297 | act("local renamed directory to " + f2, "d", |
|
302 | act("local renamed directory to " + f2, "d", | |
298 |
None, f, f2, m2. |
|
303 | None, f, f2, m2.flags(f)) | |
299 | elif f2 in m2: # rename case 1, A/A,B/A |
|
304 | elif f2 in m2: # rename case 1, A/A,B/A | |
300 | act("remote copied to " + f, "m", |
|
305 | act("remote copied to " + f, "m", | |
301 | f2, f, f, fmerge(f2, f, f2), False) |
|
306 | f2, f, f, fmerge(f2, f, f2), False) | |
@@ -304,14 +309,14 b' def manifestmerge(repo, p1, p2, pa, over' | |||||
304 | f2, f, f, fmerge(f2, f, f2), True) |
|
309 | f2, f, f, fmerge(f2, f, f2), True) | |
305 | elif f in ma: |
|
310 | elif f in ma: | |
306 | if overwrite or backwards: |
|
311 | if overwrite or backwards: | |
307 |
act("recreating", "g", f, m2. |
|
312 | act("recreating", "g", f, m2.flags(f)) | |
308 | elif n != ma[f]: |
|
313 | elif n != ma[f]: | |
309 | if repo.ui.prompt( |
|
314 | if repo.ui.prompt( | |
310 | (_("remote changed %s which local deleted\n") % f) + |
|
315 | (_("remote changed %s which local deleted\n") % f) + | |
311 | _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): |
|
316 | _("(k)eep or (d)elete?"), _("[kd]"), _("k")) == _("k"): | |
312 |
act("prompt recreating", "g", f, m2. |
|
317 | act("prompt recreating", "g", f, m2.flags(f)) | |
313 | else: |
|
318 | else: | |
314 |
act("remote created", "g", f, m2. |
|
319 | act("remote created", "g", f, m2.flags(f)) | |
315 |
|
320 | |||
316 | return action |
|
321 | return action | |
317 |
|
322 | |||
@@ -335,7 +340,7 b' def applyupdates(repo, action, wctx, mct' | |||||
335 | (f, inst.strerror)) |
|
340 | (f, inst.strerror)) | |
336 | removed += 1 |
|
341 | removed += 1 | |
337 | elif m == "m": # merge |
|
342 | elif m == "m": # merge | |
338 | f2, fd, flag, move = a[2:] |
|
343 | f2, fd, flags, move = a[2:] | |
339 | r = filemerge(repo, f, f2, wctx, mctx) |
|
344 | r = filemerge(repo, f, f2, wctx, mctx) | |
340 | if r > 0: |
|
345 | if r > 0: | |
341 | unresolved += 1 |
|
346 | unresolved += 1 | |
@@ -346,35 +351,32 b' def applyupdates(repo, action, wctx, mct' | |||||
346 | merged += 1 |
|
351 | merged += 1 | |
347 | if f != fd: |
|
352 | if f != fd: | |
348 | repo.ui.debug(_("copying %s to %s\n") % (f, fd)) |
|
353 | repo.ui.debug(_("copying %s to %s\n") % (f, fd)) | |
349 | repo.wwrite(fd, repo.wread(f)) |
|
354 | repo.wwrite(fd, repo.wread(f), flags) | |
350 | if move: |
|
355 | if move: | |
351 | repo.ui.debug(_("removing %s\n") % f) |
|
356 | repo.ui.debug(_("removing %s\n") % f) | |
352 | os.unlink(repo.wjoin(f)) |
|
357 | os.unlink(repo.wjoin(f)) | |
353 | util.set_exec(repo.wjoin(fd), flag) |
|
358 | util.set_exec(repo.wjoin(fd), "x" in flags) | |
354 | elif m == "g": # get |
|
359 | elif m == "g": # get | |
355 | flag = a[2] |
|
360 | flags = a[2] | |
356 | repo.ui.note(_("getting %s\n") % f) |
|
361 | repo.ui.note(_("getting %s\n") % f) | |
357 | t = mctx.filectx(f).data() |
|
362 | t = mctx.filectx(f).data() | |
358 | repo.wwrite(f, t) |
|
363 | repo.wwrite(f, t, flags) | |
359 | util.set_exec(repo.wjoin(f), flag) |
|
|||
360 | updated += 1 |
|
364 | updated += 1 | |
361 | elif m == "d": # directory rename |
|
365 | elif m == "d": # directory rename | |
362 | f2, fd, flag = a[2:] |
|
366 | f2, fd, flags = a[2:] | |
363 | if f: |
|
367 | if f: | |
364 | repo.ui.note(_("moving %s to %s\n") % (f, fd)) |
|
368 | repo.ui.note(_("moving %s to %s\n") % (f, fd)) | |
365 | t = wctx.filectx(f).data() |
|
369 | t = wctx.filectx(f).data() | |
366 | repo.wwrite(fd, t) |
|
370 | repo.wwrite(fd, t, flags) | |
367 | util.set_exec(repo.wjoin(fd), flag) |
|
|||
368 | util.unlink(repo.wjoin(f)) |
|
371 | util.unlink(repo.wjoin(f)) | |
369 | if f2: |
|
372 | if f2: | |
370 | repo.ui.note(_("getting %s to %s\n") % (f2, fd)) |
|
373 | repo.ui.note(_("getting %s to %s\n") % (f2, fd)) | |
371 | t = mctx.filectx(f2).data() |
|
374 | t = mctx.filectx(f2).data() | |
372 | repo.wwrite(fd, t) |
|
375 | repo.wwrite(fd, t, flags) | |
373 | util.set_exec(repo.wjoin(fd), flag) |
|
|||
374 | updated += 1 |
|
376 | updated += 1 | |
375 | elif m == "e": # exec |
|
377 | elif m == "e": # exec | |
376 | flag = a[2] |
|
378 | flags = a[2] | |
377 | util.set_exec(repo.wjoin(f), flag) |
|
379 | util.set_exec(repo.wjoin(f), flags) | |
378 |
|
380 | |||
379 | return updated, merged, removed, unresolved |
|
381 | return updated, merged, removed, unresolved | |
380 |
|
382 | |||
@@ -441,6 +443,9 b' def update(repo, node, branchmerge, forc' | |||||
441 | wlock = working dir lock, if already held |
|
443 | wlock = working dir lock, if already held | |
442 | """ |
|
444 | """ | |
443 |
|
445 | |||
|
446 | if node is None: | |||
|
447 | node = "tip" | |||
|
448 | ||||
444 | if not wlock: |
|
449 | if not wlock: | |
445 | wlock = repo.wlock() |
|
450 | wlock = repo.wlock() | |
446 |
|
451 |
@@ -7,8 +7,7 b' This software may be used and distribute' | |||||
7 | of the GNU General Public License, incorporated herein by reference. |
|
7 | of the GNU General Public License, incorporated herein by reference. | |
8 | """ |
|
8 | """ | |
9 |
|
9 | |||
10 | from demandload import demandload |
|
10 | import binascii | |
11 | demandload(globals(), "binascii") |
|
|||
12 |
|
11 | |||
13 | nullrev = -1 |
|
12 | nullrev = -1 | |
14 | nullid = "\0" * 20 |
|
13 | nullid = "\0" * 20 |
@@ -5,12 +5,11 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
8 | from i18n import _ | |
9 | from i18n import gettext as _ |
|
|||
10 | from node import * |
|
9 | from node import * | |
11 | demandload(globals(), "base85 cmdutil mdiff util") |
|
10 | import base85, cmdutil, mdiff, util, context, revlog | |
12 |
|
|
11 | import cStringIO, email.Parser, os, popen2, re, sha | |
13 | demandload(globals(), "sys tempfile zlib") |
|
12 | import sys, tempfile, zlib | |
14 |
|
13 | |||
15 | # helper functions |
|
14 | # helper functions | |
16 |
|
15 | |||
@@ -378,8 +377,9 b' def updatedir(ui, repo, patches, wlock=N' | |||||
378 | dst = os.path.join(repo.root, gp.path) |
|
377 | dst = os.path.join(repo.root, gp.path) | |
379 | # patch won't create empty files |
|
378 | # patch won't create empty files | |
380 | if ctype == 'ADD' and not os.path.exists(dst): |
|
379 | if ctype == 'ADD' and not os.path.exists(dst): | |
381 | repo.wwrite(gp.path, '') |
|
380 | repo.wwrite(gp.path, '', x and 'x' or '') | |
382 |
|
|
381 | else: | |
|
382 | util.set_exec(dst, x) | |||
383 | cmdutil.addremove(repo, cfiles, wlock=wlock) |
|
383 | cmdutil.addremove(repo, cfiles, wlock=wlock) | |
384 | files = patches.keys() |
|
384 | files = patches.keys() | |
385 | files.extend([r for r in removes if r not in files]) |
|
385 | files.extend([r for r in removes if r not in files]) | |
@@ -437,27 +437,25 b' def diff(repo, node1=None, node2=None, f' | |||||
437 | if not node1: |
|
437 | if not node1: | |
438 | node1 = repo.dirstate.parents()[0] |
|
438 | node1 = repo.dirstate.parents()[0] | |
439 |
|
439 | |||
440 |
c |
|
440 | ccache = {} | |
441 |
def getc |
|
441 | def getctx(r): | |
442 |
if |
|
442 | if r not in ccache: | |
443 |
c |
|
443 | ccache[r] = context.changectx(repo, r) | |
444 |
return c |
|
444 | return ccache[r] | |
445 | mcache = {} |
|
445 | ||
446 | def getmanifest(n): |
|
446 | flcache = {} | |
447 | if n not in mcache: |
|
447 | def getfilectx(f, ctx): | |
448 | mcache[n] = repo.manifest.read(n) |
|
448 | flctx = ctx.filectx(f, filelog=flcache.get(f)) | |
449 |
|
|
449 | if f not in flcache: | |
450 | fcache = {} |
|
450 | flcache[f] = flctx._filelog | |
451 | def getfile(f): |
|
451 | return flctx | |
452 | if f not in fcache: |
|
|||
453 | fcache[f] = repo.file(f) |
|
|||
454 | return fcache[f] |
|
|||
455 |
|
452 | |||
456 | # reading the data for node1 early allows it to play nicely |
|
453 | # reading the data for node1 early allows it to play nicely | |
457 | # with repo.status and the revlog cache. |
|
454 | # with repo.status and the revlog cache. | |
458 | change = getchangelog(node1) |
|
455 | ctx1 = context.changectx(repo, node1) | |
459 | mmap = getmanifest(change[0]) |
|
456 | # force manifest reading | |
460 | date1 = util.datestr(change[2]) |
|
457 | man1 = ctx1.manifest() | |
|
458 | date1 = util.datestr(ctx1.date()) | |||
461 |
|
459 | |||
462 | if not changes: |
|
460 | if not changes: | |
463 | changes = repo.status(node1, node2, files, match=match)[:5] |
|
461 | changes = repo.status(node1, node2, files, match=match)[:5] | |
@@ -477,67 +475,38 b' def diff(repo, node1=None, node2=None, f' | |||||
477 | if not modified and not added and not removed: |
|
475 | if not modified and not added and not removed: | |
478 | return |
|
476 | return | |
479 |
|
477 | |||
480 | # returns False if there was no rename between n1 and n2 |
|
478 | if node2: | |
481 | # returns None if the file was created between n1 and n2 |
|
479 | ctx2 = context.changectx(repo, node2) | |
482 | # returns the (file, node) present in n1 that was renamed to f in n2 |
|
480 | else: | |
483 | def renamedbetween(f, n1, n2): |
|
481 | ctx2 = context.workingctx(repo) | |
484 | r1, r2 = map(repo.changelog.rev, (n1, n2)) |
|
482 | man2 = ctx2.manifest() | |
|
483 | ||||
|
484 | # returns False if there was no rename between ctx1 and ctx2 | |||
|
485 | # returns None if the file was created between ctx1 and ctx2 | |||
|
486 | # returns the (file, node) present in ctx1 that was renamed to f in ctx2 | |||
|
487 | def renamed(f): | |||
|
488 | startrev = ctx1.rev() | |||
|
489 | c = ctx2 | |||
|
490 | crev = c.rev() | |||
|
491 | if crev is None: | |||
|
492 | crev = repo.changelog.count() | |||
485 | orig = f |
|
493 | orig = f | |
486 | src = None |
|
494 | while crev > startrev: | |
487 | while r2 > r1: |
|
495 | if f in c.files(): | |
488 | cl = getchangelog(n2) |
|
|||
489 | if f in cl[3]: |
|
|||
490 | m = getmanifest(cl[0]) |
|
|||
491 | try: |
|
496 | try: | |
492 |
src = getfile(f).renamed( |
|
497 | src = getfilectx(f, c).renamed() | |
493 |
except |
|
498 | except revlog.LookupError: | |
494 | return None |
|
499 | return None | |
495 | if src: |
|
500 | if src: | |
496 | f = src[0] |
|
501 | f = src[0] | |
497 |
|
|
502 | crev = c.parents()[0].rev() | |
498 | r2 = repo.changelog.rev(n2) |
|
503 | # try to reuse | |
499 |
c |
|
504 | c = getctx(crev) | |
500 | m = getmanifest(cl[0]) |
|
505 | if f not in man1: | |
501 | if f not in m: |
|
|||
502 | return None |
|
506 | return None | |
503 | if f == orig: |
|
507 | if f == orig: | |
504 | return False |
|
508 | return False | |
505 |
return f |
|
509 | return f | |
506 |
|
||||
507 | if node2: |
|
|||
508 | change = getchangelog(node2) |
|
|||
509 | mmap2 = getmanifest(change[0]) |
|
|||
510 | _date2 = util.datestr(change[2]) |
|
|||
511 | def date2(f): |
|
|||
512 | return _date2 |
|
|||
513 | def read(f): |
|
|||
514 | return getfile(f).read(mmap2[f]) |
|
|||
515 | def renamed(f): |
|
|||
516 | return renamedbetween(f, node1, node2) |
|
|||
517 | else: |
|
|||
518 | tz = util.makedate()[1] |
|
|||
519 | _date2 = util.datestr() |
|
|||
520 | def date2(f): |
|
|||
521 | try: |
|
|||
522 | return util.datestr((os.lstat(repo.wjoin(f)).st_mtime, tz)) |
|
|||
523 | except OSError, err: |
|
|||
524 | if err.errno != errno.ENOENT: raise |
|
|||
525 | return _date2 |
|
|||
526 | def read(f): |
|
|||
527 | return repo.wread(f) |
|
|||
528 | def renamed(f): |
|
|||
529 | src = repo.dirstate.copied(f) |
|
|||
530 | parent = repo.dirstate.parents()[0] |
|
|||
531 | if src: |
|
|||
532 | f = src |
|
|||
533 | of = renamedbetween(f, node1, parent) |
|
|||
534 | if of or of is None: |
|
|||
535 | return of |
|
|||
536 | elif src: |
|
|||
537 | cl = getchangelog(parent)[0] |
|
|||
538 | return (src, getmanifest(cl)[src]) |
|
|||
539 | else: |
|
|||
540 | return None |
|
|||
541 |
|
510 | |||
542 | if repo.ui.quiet: |
|
511 | if repo.ui.quiet: | |
543 | r = None |
|
512 | r = None | |
@@ -551,20 +520,21 b' def diff(repo, node1=None, node2=None, f' | |||||
551 | src = renamed(f) |
|
520 | src = renamed(f) | |
552 | if src: |
|
521 | if src: | |
553 | copied[f] = src |
|
522 | copied[f] = src | |
554 |
srcs = [x[1 |
|
523 | srcs = [x[1] for x in copied.items()] | |
555 |
|
524 | |||
556 | all = modified + added + removed |
|
525 | all = modified + added + removed | |
557 | all.sort() |
|
526 | all.sort() | |
558 | gone = {} |
|
527 | gone = {} | |
|
528 | ||||
559 | for f in all: |
|
529 | for f in all: | |
560 | to = None |
|
530 | to = None | |
561 | tn = None |
|
531 | tn = None | |
562 | dodiff = True |
|
532 | dodiff = True | |
563 | header = [] |
|
533 | header = [] | |
564 |
if f in m |
|
534 | if f in man1: | |
565 |
to = getfile(f). |
|
535 | to = getfilectx(f, ctx1).data() | |
566 | if f not in removed: |
|
536 | if f not in removed: | |
567 |
tn = |
|
537 | tn = getfilectx(f, ctx2).data() | |
568 | if opts.git: |
|
538 | if opts.git: | |
569 | def gitmode(x): |
|
539 | def gitmode(x): | |
570 | return x and '100755' or '100644' |
|
540 | return x and '100755' or '100644' | |
@@ -575,13 +545,10 b' def diff(repo, node1=None, node2=None, f' | |||||
575 |
|
545 | |||
576 | a, b = f, f |
|
546 | a, b = f, f | |
577 | if f in added: |
|
547 | if f in added: | |
578 | if node2: |
|
548 | mode = gitmode(man2.execf(f)) | |
579 | mode = gitmode(mmap2.execf(f)) |
|
|||
580 | else: |
|
|||
581 | mode = gitmode(util.is_exec(repo.wjoin(f), None)) |
|
|||
582 | if f in copied: |
|
549 | if f in copied: | |
583 |
a |
|
550 | a = copied[f] | |
584 |
omode = gitmode(m |
|
551 | omode = gitmode(man1.execf(a)) | |
585 | addmodehdr(header, omode, mode) |
|
552 | addmodehdr(header, omode, mode) | |
586 | if a in removed and a not in gone: |
|
553 | if a in removed and a not in gone: | |
587 | op = 'rename' |
|
554 | op = 'rename' | |
@@ -590,7 +557,7 b' def diff(repo, node1=None, node2=None, f' | |||||
590 | op = 'copy' |
|
557 | op = 'copy' | |
591 | header.append('%s from %s\n' % (op, a)) |
|
558 | header.append('%s from %s\n' % (op, a)) | |
592 | header.append('%s to %s\n' % (op, f)) |
|
559 | header.append('%s to %s\n' % (op, f)) | |
593 |
to = getfile(a). |
|
560 | to = getfilectx(a, ctx1).data() | |
594 | else: |
|
561 | else: | |
595 | header.append('new file mode %s\n' % mode) |
|
562 | header.append('new file mode %s\n' % mode) | |
596 | if util.binary(tn): |
|
563 | if util.binary(tn): | |
@@ -599,14 +566,11 b' def diff(repo, node1=None, node2=None, f' | |||||
599 | if f in srcs: |
|
566 | if f in srcs: | |
600 | dodiff = False |
|
567 | dodiff = False | |
601 | else: |
|
568 | else: | |
602 |
mode = gitmode(m |
|
569 | mode = gitmode(man1.execf(f)) | |
603 | header.append('deleted file mode %s\n' % mode) |
|
570 | header.append('deleted file mode %s\n' % mode) | |
604 | else: |
|
571 | else: | |
605 |
omode = gitmode(m |
|
572 | omode = gitmode(man1.execf(f)) | |
606 | if node2: |
|
573 | nmode = gitmode(man2.execf(f)) | |
607 | nmode = gitmode(mmap2.execf(f)) |
|
|||
608 | else: |
|
|||
609 | nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) |
|
|||
610 | addmodehdr(header, omode, nmode) |
|
574 | addmodehdr(header, omode, nmode) | |
611 | if util.binary(to) or util.binary(tn): |
|
575 | if util.binary(to) or util.binary(tn): | |
612 | dodiff = 'binary' |
|
576 | dodiff = 'binary' | |
@@ -616,7 +580,10 b' def diff(repo, node1=None, node2=None, f' | |||||
616 | fp.write(''.join(header)) |
|
580 | fp.write(''.join(header)) | |
617 | b85diff(fp, to, tn) |
|
581 | b85diff(fp, to, tn) | |
618 | elif dodiff: |
|
582 | elif dodiff: | |
619 |
text = mdiff.unidiff(to, date1, |
|
583 | text = mdiff.unidiff(to, date1, | |
|
584 | # ctx2 date may be dynamic | |||
|
585 | tn, util.datestr(ctx2.date()), | |||
|
586 | f, r, opts=opts) | |||
620 | if text or len(header) > 1: |
|
587 | if text or len(header) > 1: | |
621 | fp.write(''.join(header)) |
|
588 | fp.write(''.join(header)) | |
622 | fp.write(text) |
|
589 | fp.write(text) | |
@@ -628,12 +595,13 b" def export(repo, revs, template='hg-%h.p" | |||||
628 | total = len(revs) |
|
595 | total = len(revs) | |
629 | revwidth = max([len(str(rev)) for rev in revs]) |
|
596 | revwidth = max([len(str(rev)) for rev in revs]) | |
630 |
|
597 | |||
631 |
def single( |
|
598 | def single(rev, seqno, fp): | |
632 | parents = [p for p in repo.changelog.parents(node) if p != nullid] |
|
599 | ctx = repo.changectx(rev) | |
|
600 | node = ctx.node() | |||
|
601 | parents = [p.node() for p in ctx.parents() if p] | |||
633 | if switch_parent: |
|
602 | if switch_parent: | |
634 | parents.reverse() |
|
603 | parents.reverse() | |
635 | prev = (parents and parents[0]) or nullid |
|
604 | prev = (parents and parents[0]) or nullid | |
636 | change = repo.changelog.read(node) |
|
|||
637 |
|
605 | |||
638 | if not fp: |
|
606 | if not fp: | |
639 | fp = cmdutil.make_file(repo, template, node, total=total, |
|
607 | fp = cmdutil.make_file(repo, template, node, total=total, | |
@@ -642,13 +610,13 b" def export(repo, revs, template='hg-%h.p" | |||||
642 | repo.ui.note("%s\n" % fp.name) |
|
610 | repo.ui.note("%s\n" % fp.name) | |
643 |
|
611 | |||
644 | fp.write("# HG changeset patch\n") |
|
612 | fp.write("# HG changeset patch\n") | |
645 |
fp.write("# User %s\n" % c |
|
613 | fp.write("# User %s\n" % ctx.user()) | |
646 |
fp.write("# Date %d %d\n" % c |
|
614 | fp.write("# Date %d %d\n" % ctx.date()) | |
647 | fp.write("# Node ID %s\n" % hex(node)) |
|
615 | fp.write("# Node ID %s\n" % hex(node)) | |
648 | fp.write("# Parent %s\n" % hex(prev)) |
|
616 | fp.write("# Parent %s\n" % hex(prev)) | |
649 | if len(parents) > 1: |
|
617 | if len(parents) > 1: | |
650 | fp.write("# Parent %s\n" % hex(parents[1])) |
|
618 | fp.write("# Parent %s\n" % hex(parents[1])) | |
651 |
fp.write(c |
|
619 | fp.write(ctx.description().rstrip()) | |
652 | fp.write("\n\n") |
|
620 | fp.write("\n\n") | |
653 |
|
621 | |||
654 | diff(repo, prev, node, fp=fp, opts=opts) |
|
622 | diff(repo, prev, node, fp=fp, opts=opts) | |
@@ -656,7 +624,7 b" def export(repo, revs, template='hg-%h.p" | |||||
656 | fp.close() |
|
624 | fp.close() | |
657 |
|
625 | |||
658 | for seqno, rev in enumerate(revs): |
|
626 | for seqno, rev in enumerate(revs): | |
659 |
single( |
|
627 | single(rev, seqno+1, fp) | |
660 |
|
628 | |||
661 | def diffstat(patchlines): |
|
629 | def diffstat(patchlines): | |
662 | fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt") |
|
630 | fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt") |
@@ -9,9 +9,6 b'' | |||||
9 | class RepoError(Exception): |
|
9 | class RepoError(Exception): | |
10 | pass |
|
10 | pass | |
11 |
|
11 | |||
12 | class LookupError(RepoError): |
|
|||
13 | pass |
|
|||
14 |
|
||||
15 | class repository(object): |
|
12 | class repository(object): | |
16 | def capable(self, name): |
|
13 | def capable(self, name): | |
17 | '''tell whether repo supports named capability. |
|
14 | '''tell whether repo supports named capability. |
@@ -11,10 +11,9 b' of the GNU General Public License, incor' | |||||
11 | """ |
|
11 | """ | |
12 |
|
12 | |||
13 | from node import * |
|
13 | from node import * | |
14 |
from i18n import |
|
14 | from i18n import _ | |
15 | from demandload import demandload |
|
15 | import binascii, changegroup, errno, ancestor, mdiff, os | |
16 | demandload(globals(), "binascii changegroup errno ancestor mdiff os") |
|
16 | import sha, struct, util, zlib | |
17 | demandload(globals(), "sha struct util zlib") |
|
|||
18 |
|
17 | |||
19 | # revlog version strings |
|
18 | # revlog version strings | |
20 | REVLOGV0 = 0 |
|
19 | REVLOGV0 = 0 | |
@@ -282,6 +281,7 b' class lazymap(object):' | |||||
282 | del self.p.map[key] |
|
281 | del self.p.map[key] | |
283 |
|
282 | |||
284 | class RevlogError(Exception): pass |
|
283 | class RevlogError(Exception): pass | |
|
284 | class LookupError(RevlogError): pass | |||
285 |
|
285 | |||
286 | class revlog(object): |
|
286 | class revlog(object): | |
287 | """ |
|
287 | """ | |
@@ -472,7 +472,7 b' class revlog(object):' | |||||
472 | try: |
|
472 | try: | |
473 | return self.nodemap[node] |
|
473 | return self.nodemap[node] | |
474 | except KeyError: |
|
474 | except KeyError: | |
475 |
raise |
|
475 | raise LookupError(_('%s: no node %s') % (self.indexfile, hex(node))) | |
476 | def linkrev(self, node): |
|
476 | def linkrev(self, node): | |
477 | return (node == nullid) and nullrev or self.index[self.rev(node)][-4] |
|
477 | return (node == nullid) and nullrev or self.index[self.rev(node)][-4] | |
478 | def parents(self, node): |
|
478 | def parents(self, node): | |
@@ -767,7 +767,7 b' class revlog(object):' | |||||
767 | node = id |
|
767 | node = id | |
768 | r = self.rev(node) # quick search the index |
|
768 | r = self.rev(node) # quick search the index | |
769 | return node |
|
769 | return node | |
770 |
except |
|
770 | except LookupError: | |
771 | pass # may be partial hex id |
|
771 | pass # may be partial hex id | |
772 | try: |
|
772 | try: | |
773 | # str(rev) |
|
773 | # str(rev) | |
@@ -796,7 +796,7 b' class revlog(object):' | |||||
796 | for n in self.nodemap: |
|
796 | for n in self.nodemap: | |
797 | if n.startswith(bin_id) and hex(n).startswith(id): |
|
797 | if n.startswith(bin_id) and hex(n).startswith(id): | |
798 | if node is not None: |
|
798 | if node is not None: | |
799 |
raise |
|
799 | raise LookupError(_("Ambiguous identifier")) | |
800 | node = n |
|
800 | node = n | |
801 | if node is not None: |
|
801 | if node is not None: | |
802 | return node |
|
802 | return node | |
@@ -816,7 +816,7 b' class revlog(object):' | |||||
816 | if n: |
|
816 | if n: | |
817 | return n |
|
817 | return n | |
818 |
|
818 | |||
819 |
raise |
|
819 | raise LookupError(_("No match found")) | |
820 |
|
820 | |||
821 | def cmp(self, node, text): |
|
821 | def cmp(self, node, text): | |
822 | """compare text with a given file revision""" |
|
822 | """compare text with a given file revision""" | |
@@ -1156,13 +1156,13 b' class revlog(object):' | |||||
1156 |
|
1156 | |||
1157 | for p in (p1, p2): |
|
1157 | for p in (p1, p2): | |
1158 | if not p in self.nodemap: |
|
1158 | if not p in self.nodemap: | |
1159 |
raise |
|
1159 | raise LookupError(_("unknown parent %s") % short(p)) | |
1160 |
|
1160 | |||
1161 | if not chain: |
|
1161 | if not chain: | |
1162 | # retrieve the parent revision of the delta chain |
|
1162 | # retrieve the parent revision of the delta chain | |
1163 | chain = p1 |
|
1163 | chain = p1 | |
1164 | if not chain in self.nodemap: |
|
1164 | if not chain in self.nodemap: | |
1165 |
raise |
|
1165 | raise LookupError(_("unknown base %s") % short(chain[:4])) | |
1166 |
|
1166 | |||
1167 | # full versions are inserted when the needed deltas become |
|
1167 | # full versions are inserted when the needed deltas become | |
1168 | # comparable to the uncompressed text or when the previous |
|
1168 | # comparable to the uncompressed text or when the previous |
@@ -7,9 +7,8 b'' | |||||
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 | from remoterepo import * |
|
9 | from remoterepo import * | |
10 |
from i18n import |
|
10 | from i18n import _ | |
11 | from demandload import * |
|
11 | import hg, os, re, stat, util | |
12 | demandload(globals(), "hg os re stat util") |
|
|||
13 |
|
12 | |||
14 | class sshrepository(remoterepository): |
|
13 | class sshrepository(remoterepository): | |
15 | def __init__(self, ui, path, create=0): |
|
14 | def __init__(self, ui, path, create=0): |
@@ -6,10 +6,9 b'' | |||||
6 | # This software may be used and distributed according to the terms |
|
6 | # This software may be used and distributed according to the terms | |
7 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | # of the GNU General Public License, incorporated herein by reference. | |
8 |
|
8 | |||
9 | from demandload import demandload |
|
9 | from i18n import _ | |
10 | from i18n import gettext as _ |
|
|||
11 | from node import * |
|
10 | from node import * | |
12 |
|
|
11 | import os, streamclone, sys, tempfile, util | |
13 |
|
12 | |||
14 | class sshserver(object): |
|
13 | class sshserver(object): | |
15 | def __init__(self, ui, repo): |
|
14 | def __init__(self, ui, repo): |
@@ -7,10 +7,9 b'' | |||||
7 | # This software may be used and distributed according to the terms |
|
7 | # This software may be used and distributed according to the terms | |
8 | # of the GNU General Public License, incorporated herein by reference. |
|
8 | # of the GNU General Public License, incorporated herein by reference. | |
9 |
|
9 | |||
10 |
from |
|
10 | from i18n import _ | |
11 | from i18n import gettext as _ |
|
11 | import changelog, filelog, httprangereader | |
12 | demandload(globals(), "changelog filelog httprangereader") |
|
12 | import repo, localrepo, manifest, os, urllib, urllib2, util | |
13 | demandload(globals(), "repo localrepo manifest os urllib urllib2 util") |
|
|||
14 |
|
13 | |||
15 | class rangereader(httprangereader.httprangereader): |
|
14 | class rangereader(httprangereader.httprangereader): | |
16 | def read(self, size=None): |
|
15 | def read(self, size=None): |
@@ -5,9 +5,8 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
8 | from i18n import _ | |
9 | from i18n import gettext as _ |
|
9 | import os, stat, util, lock | |
10 | demandload(globals(), "os stat util lock") |
|
|||
11 |
|
10 | |||
12 | # if server supports streaming clone, it advertises "stream" |
|
11 | # if server supports streaming clone, it advertises "stream" | |
13 | # capability with value that is version+flags of repo it is serving. |
|
12 | # capability with value that is version+flags of repo it is serving. |
@@ -5,10 +5,9 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from demandload import demandload |
|
8 | from i18n import _ | |
9 | from i18n import gettext as _ |
|
|||
10 | from node import * |
|
9 | from node import * | |
11 |
|
|
10 | import cgi, re, sys, os, time, urllib, util, textwrap | |
12 |
|
11 | |||
13 | def parsestring(s, quoted=True): |
|
12 | def parsestring(s, quoted=True): | |
14 | '''parse a string using simple c-like syntax. |
|
13 | '''parse a string using simple c-like syntax. |
@@ -11,9 +11,8 b'' | |||||
11 | # This software may be used and distributed according to the terms |
|
11 | # This software may be used and distributed according to the terms | |
12 | # of the GNU General Public License, incorporated herein by reference. |
|
12 | # of the GNU General Public License, incorporated herein by reference. | |
13 |
|
13 | |||
14 | from demandload import demandload |
|
14 | from i18n import _ | |
15 | from i18n import gettext as _ |
|
15 | import os | |
16 | demandload(globals(), 'os') |
|
|||
17 |
|
16 | |||
18 | class transaction(object): |
|
17 | class transaction(object): | |
19 | def __init__(self, report, opener, journal, after=None): |
|
18 | def __init__(self, report, opener, journal, after=None): |
@@ -5,10 +5,9 b'' | |||||
5 | # This software may be used and distributed according to the terms |
|
5 | # This software may be used and distributed according to the terms | |
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 |
from i18n import |
|
8 | from i18n import _ | |
9 | from demandload import * |
|
9 | import errno, getpass, os, re, socket, sys, tempfile | |
10 | demandload(globals(), "errno getpass os re socket sys tempfile") |
|
10 | import ConfigParser, traceback, util | |
11 | demandload(globals(), "ConfigParser traceback util") |
|
|||
12 |
|
11 | |||
13 | def dupconfig(orig): |
|
12 | def dupconfig(orig): | |
14 | new = util.configparser(orig.defaults()) |
|
13 | new = util.configparser(orig.defaults()) | |
@@ -386,6 +385,9 b' class ui(object):' | |||||
386 | if not sys.stdout.closed: sys.stdout.flush() |
|
385 | if not sys.stdout.closed: sys.stdout.flush() | |
387 | for a in args: |
|
386 | for a in args: | |
388 | sys.stderr.write(str(a)) |
|
387 | sys.stderr.write(str(a)) | |
|
388 | # stderr may be buffered under win32 when redirected to files, | |||
|
389 | # including stdout. | |||
|
390 | if not sys.stderr.closed: sys.stderr.flush() | |||
389 | except IOError, inst: |
|
391 | except IOError, inst: | |
390 | if inst.errno != errno.EPIPE: |
|
392 | if inst.errno != errno.EPIPE: | |
391 | raise |
|
393 | raise |
@@ -12,10 +12,9 b' This contains helper routines that are i' | |||||
12 | platform-specific details from the core. |
|
12 | platform-specific details from the core. | |
13 | """ |
|
13 | """ | |
14 |
|
14 | |||
15 |
from i18n import |
|
15 | from i18n import _ | |
16 | from demandload import * |
|
16 | import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile | |
17 | demandload(globals(), "cStringIO errno getpass popen2 re shutil sys tempfile") |
|
17 | import os, threading, time, calendar, ConfigParser, locale | |
18 | demandload(globals(), "os threading time calendar ConfigParser locale") |
|
|||
19 |
|
18 | |||
20 | _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \ |
|
19 | _encoding = os.environ.get("HGENCODING") or locale.getpreferredencoding() \ | |
21 | or "ascii" |
|
20 | or "ascii" | |
@@ -694,9 +693,47 b' def checkfolding(path):' | |||||
694 | except: |
|
693 | except: | |
695 | return True |
|
694 | return True | |
696 |
|
695 | |||
|
696 | def checkexec(path): | |||
|
697 | """ | |||
|
698 | Check whether the given path is on a filesystem with UNIX-like exec flags | |||
|
699 | ||||
|
700 | Requires a directory (like /foo/.hg) | |||
|
701 | """ | |||
|
702 | fh, fn = tempfile.mkstemp("", "", path) | |||
|
703 | os.close(fh) | |||
|
704 | m = os.stat(fn).st_mode | |||
|
705 | os.chmod(fn, m ^ 0111) | |||
|
706 | r = (os.stat(fn).st_mode != m) | |||
|
707 | os.unlink(fn) | |||
|
708 | return r | |||
|
709 | ||||
|
710 | def execfunc(path, fallback): | |||
|
711 | '''return an is_exec() function with default to fallback''' | |||
|
712 | if checkexec(path): | |||
|
713 | return lambda x: is_exec(os.path.join(path, x)) | |||
|
714 | return fallback | |||
|
715 | ||||
|
716 | def checklink(path): | |||
|
717 | """check whether the given path is on a symlink-capable filesystem""" | |||
|
718 | # mktemp is not racy because symlink creation will fail if the | |||
|
719 | # file already exists | |||
|
720 | name = tempfile.mktemp(dir=path) | |||
|
721 | try: | |||
|
722 | os.symlink(".", name) | |||
|
723 | os.unlink(name) | |||
|
724 | return True | |||
|
725 | except (OSError, AttributeError): | |||
|
726 | return False | |||
|
727 | ||||
|
728 | def linkfunc(path, fallback): | |||
|
729 | '''return an is_link() function with default to fallback''' | |||
|
730 | if checklink(path): | |||
|
731 | return lambda x: is_link(os.path.join(path, x)) | |||
|
732 | return fallback | |||
|
733 | ||||
697 | # Platform specific variants |
|
734 | # Platform specific variants | |
698 | if os.name == 'nt': |
|
735 | if os.name == 'nt': | |
699 | demandload(globals(), "msvcrt") |
|
736 | import msvcrt | |
700 | nulldev = 'NUL:' |
|
737 | nulldev = 'NUL:' | |
701 |
|
738 | |||
702 | class winstdout: |
|
739 | class winstdout: | |
@@ -753,10 +790,10 b" if os.name == 'nt':" | |||||
753 | '''return False if pid dead, True if running or not known''' |
|
790 | '''return False if pid dead, True if running or not known''' | |
754 | return True |
|
791 | return True | |
755 |
|
792 | |||
756 |
def |
|
793 | def set_exec(f, mode): | |
757 |
|
|
794 | pass | |
758 |
|
795 | |||
759 |
def set_ |
|
796 | def set_link(f, mode): | |
760 | pass |
|
797 | pass | |
761 |
|
798 | |||
762 | def set_binary(fd): |
|
799 | def set_binary(fd): | |
@@ -798,6 +835,8 b" if os.name == 'nt':" | |||||
798 |
|
835 | |||
799 | else: |
|
836 | else: | |
800 | nulldev = '/dev/null' |
|
837 | nulldev = '/dev/null' | |
|
838 | _umask = os.umask(0) | |||
|
839 | os.umask(_umask) | |||
801 |
|
840 | |||
802 | def rcfiles(path): |
|
841 | def rcfiles(path): | |
803 | rcs = [os.path.join(path, 'hgrc')] |
|
842 | rcs = [os.path.join(path, 'hgrc')] | |
@@ -828,7 +867,7 b' else:' | |||||
828 | pf = pf[1:-1] # Remove the quotes |
|
867 | pf = pf[1:-1] # Remove the quotes | |
829 | return pf |
|
868 | return pf | |
830 |
|
869 | |||
831 |
def is_exec(f |
|
870 | def is_exec(f): | |
832 | """check whether a file is executable""" |
|
871 | """check whether a file is executable""" | |
833 | return (os.lstat(f).st_mode & 0100 != 0) |
|
872 | return (os.lstat(f).st_mode & 0100 != 0) | |
834 |
|
873 | |||
@@ -839,12 +878,34 b' else:' | |||||
839 | if mode: |
|
878 | if mode: | |
840 | # Turn on +x for every +r bit when making a file executable |
|
879 | # Turn on +x for every +r bit when making a file executable | |
841 | # and obey umask. |
|
880 | # and obey umask. | |
842 | umask = os.umask(0) |
|
881 | os.chmod(f, s | (s & 0444) >> 2 & ~_umask) | |
843 | os.umask(umask) |
|
|||
844 | os.chmod(f, s | (s & 0444) >> 2 & ~umask) |
|
|||
845 | else: |
|
882 | else: | |
846 | os.chmod(f, s & 0666) |
|
883 | os.chmod(f, s & 0666) | |
847 |
|
884 | |||
|
885 | def is_link(f): | |||
|
886 | """check whether a file is a symlink""" | |||
|
887 | return (os.lstat(f).st_mode & 0120000 == 0120000) | |||
|
888 | ||||
|
889 | def set_link(f, mode): | |||
|
890 | """make a file a symbolic link/regular file | |||
|
891 | ||||
|
892 | if a file is changed to a link, its contents become the link data | |||
|
893 | if a link is changed to a file, its link data become its contents | |||
|
894 | """ | |||
|
895 | ||||
|
896 | m = is_link(f) | |||
|
897 | if m == bool(mode): | |||
|
898 | return | |||
|
899 | ||||
|
900 | if mode: # switch file to link | |||
|
901 | data = file(f).read() | |||
|
902 | os.unlink(f) | |||
|
903 | os.symlink(data, f) | |||
|
904 | else: | |||
|
905 | data = os.readlink(f) | |||
|
906 | os.unlink(f) | |||
|
907 | file(f, "w").write(data) | |||
|
908 | ||||
848 | def set_binary(fd): |
|
909 | def set_binary(fd): | |
849 | pass |
|
910 | pass | |
850 |
|
911 |
@@ -13,10 +13,10 b'' | |||||
13 |
|
13 | |||
14 | import win32api |
|
14 | import win32api | |
15 |
|
15 | |||
16 |
from |
|
16 | from i18n import _ | |
17 | from i18n import gettext as _ |
|
17 | import errno, os, pywintypes, win32con, win32file, win32process | |
18 | demandload(globals(), 'errno os pywintypes win32con win32file win32process') |
|
18 | import cStringIO, winerror | |
19 | demandload(globals(), 'cStringIO win32com.shell:shell,shellcon winerror') |
|
19 | from win32com.shell import shell,shellcon | |
20 |
|
20 | |||
21 | class WinError: |
|
21 | class WinError: | |
22 | winerror_map = { |
|
22 | winerror_map = { |
@@ -6,7 +6,7 b'' | |||||
6 | # of the GNU General Public License, incorporated herein by reference. |
|
6 | # of the GNU General Public License, incorporated herein by reference. | |
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 |
from i18n import |
|
9 | from i18n import _ | |
10 | import revlog, mdiff |
|
10 | import revlog, mdiff | |
11 |
|
11 | |||
12 | def verify(repo): |
|
12 | def verify(repo): |
@@ -13,9 +13,11 b' import os' | |||||
13 | from distutils.core import setup, Extension |
|
13 | from distutils.core import setup, Extension | |
14 | from distutils.command.install_data import install_data |
|
14 | from distutils.command.install_data import install_data | |
15 |
|
15 | |||
16 | # mercurial.packagescan must be the first mercurial module imported |
|
|||
17 | import mercurial.packagescan |
|
|||
18 | import mercurial.version |
|
16 | import mercurial.version | |
|
17 | import mercurial.demandimport | |||
|
18 | mercurial.demandimport.enable = lambda: None | |||
|
19 | ||||
|
20 | extra = {} | |||
19 |
|
21 | |||
20 | # py2exe needs to be installed to work |
|
22 | # py2exe needs to be installed to work | |
21 | try: |
|
23 | try: | |
@@ -35,34 +37,10 b' try:' | |||||
35 | except ImportError: |
|
37 | except ImportError: | |
36 | pass |
|
38 | pass | |
37 |
|
39 | |||
38 | # Due to the use of demandload py2exe is not finding the modules. |
|
40 | extra['console'] = ['hg'] | |
39 | # packagescan.getmodules creates a list of modules included in |
|
|||
40 | # the mercurial package plus dependant modules. |
|
|||
41 | from py2exe.build_exe import py2exe as build_exe |
|
|||
42 |
|
41 | |||
43 | class py2exe_for_demandload(build_exe): |
|
|||
44 | """ overwrites the py2exe command class for getting the build |
|
|||
45 | directory and for setting the 'includes' option.""" |
|
|||
46 | def initialize_options(self): |
|
|||
47 | self.build_lib = None |
|
|||
48 | build_exe.initialize_options(self) |
|
|||
49 | def finalize_options(self): |
|
|||
50 | # Get the build directory, ie. where to search for modules. |
|
|||
51 | self.set_undefined_options('build', |
|
|||
52 | ('build_lib', 'build_lib')) |
|
|||
53 | # Sets the 'includes' option with the list of needed modules |
|
|||
54 | if not self.includes: |
|
|||
55 | self.includes = [] |
|
|||
56 | else: |
|
|||
57 | self.includes = self.includes.split(',') |
|
|||
58 | mercurial.packagescan.scan(self.build_lib, 'mercurial') |
|
|||
59 | mercurial.packagescan.scan(self.build_lib, 'mercurial.hgweb') |
|
|||
60 | mercurial.packagescan.scan(self.build_lib, 'hgext') |
|
|||
61 | self.includes += mercurial.packagescan.getmodules() |
|
|||
62 | build_exe.finalize_options(self) |
|
|||
63 | except ImportError: |
|
42 | except ImportError: | |
64 | py2exe_for_demandload = None |
|
43 | pass | |
65 |
|
||||
66 |
|
44 | |||
67 | # specify version string, otherwise 'hg identify' will be used: |
|
45 | # specify version string, otherwise 'hg identify' will be used: | |
68 | version = '' |
|
46 | version = '' | |
@@ -75,10 +53,6 b' class install_package_data(install_data)' | |||||
75 |
|
53 | |||
76 | mercurial.version.remember_version(version) |
|
54 | mercurial.version.remember_version(version) | |
77 | cmdclass = {'install_data': install_package_data} |
|
55 | cmdclass = {'install_data': install_package_data} | |
78 | py2exe_opts = {} |
|
|||
79 | if py2exe_for_demandload is not None: |
|
|||
80 | cmdclass['py2exe'] = py2exe_for_demandload |
|
|||
81 | py2exe_opts['console'] = ['hg'] |
|
|||
82 |
|
56 | |||
83 | setup(name='mercurial', |
|
57 | setup(name='mercurial', | |
84 | version=mercurial.version.get_version(), |
|
58 | version=mercurial.version.get_version(), | |
@@ -100,4 +74,4 b" setup(name='mercurial'," | |||||
100 | license='COPYING', |
|
74 | license='COPYING', | |
101 | readme='contrib/macosx/Readme.html', |
|
75 | readme='contrib/macosx/Readme.html', | |
102 | welcome='contrib/macosx/Welcome.html')), |
|
76 | welcome='contrib/macosx/Welcome.html')), | |
103 |
** |
|
77 | **extra) |
@@ -14,3 +14,8 b" diffblock = '#lines#'" | |||||
14 | filediff = filediff.tmpl |
|
14 | filediff = filediff.tmpl | |
15 | fileannotate = fileannotate.tmpl |
|
15 | fileannotate = fileannotate.tmpl | |
16 | annotateline = '#author#@#rev#: #line#' |
|
16 | annotateline = '#author#@#rev#: #line#' | |
|
17 | manifest = manifest.tmpl | |||
|
18 | manifestdirentry = 'drwxr-xr-x {basename}\n' | |||
|
19 | manifestfileentry = '{permissions|permissions} {size} {basename}\n' | |||
|
20 | index = index.tmpl | |||
|
21 | indexentry = '#url#\n' |
@@ -1,93 +1,7 b'' | |||||
1 | A simple testing framework |
|
|||
2 |
|
||||
3 | To run the tests, do: |
|
1 | To run the tests, do: | |
4 |
|
2 | |||
5 | cd tests/ |
|
3 | cd tests/ | |
6 | python run-tests.py |
|
4 | python run-tests.py | |
7 |
|
5 | |||
8 | This finds all scripts in the test directory named test-* and executes |
|
6 | See http://www.selenic.com/mercurial/wiki/index.cgi/WritingTests for | |
9 | them. The scripts can be either shell scripts or Python. Each test is |
|
7 | more information on writing tests. | |
10 | run in a temporary directory that is removed when the test is complete. |
|
|||
11 |
|
||||
12 | A test-<x> succeeds if the script returns success and its output |
|
|||
13 | matches test-<x>.out. If the new output doesn't match, it is stored in |
|
|||
14 | test-<x>.err. |
|
|||
15 |
|
||||
16 | There are some tricky points here that you should be aware of when |
|
|||
17 | writing tests: |
|
|||
18 |
|
||||
19 | - hg commit and hg merge want user interaction |
|
|||
20 |
|
||||
21 | for commit use -m "text" |
|
|||
22 | for hg merge, set HGMERGE to something noninteractive (like true or merge) |
|
|||
23 |
|
||||
24 | - changeset hashes will change based on user and date which make |
|
|||
25 | things like hg history output change |
|
|||
26 |
|
||||
27 | use commit -m "test" -u test -d "1000000 0" |
|
|||
28 |
|
||||
29 | - diff and export may show the current time |
|
|||
30 |
|
||||
31 | use -D/--nodates to strip the dates |
|
|||
32 |
|
||||
33 | - You can append your own hgrc settings to the file that the environment |
|
|||
34 | variable HGRCPATH points to. This file is cleared before running a test. |
|
|||
35 |
|
||||
36 | You also need to be careful that the tests are portable from one platform |
|
|||
37 | to another. You're probably working on Linux, where the GNU toolchain has |
|
|||
38 | more (or different) functionality than on MacOS, *BSD, Solaris, AIX, etc. |
|
|||
39 | While testing on all platforms is the only sure-fire way to make sure that |
|
|||
40 | you've written portable code, here's a list of problems that have been |
|
|||
41 | found and fixed in the tests. Another, more comprehensive list may be |
|
|||
42 | found in the GNU Autoconf manual, online here: |
|
|||
43 |
|
||||
44 | http://www.gnu.org/software/autoconf/manual/html_node/Portable-Shell.html |
|
|||
45 |
|
||||
46 | sh: |
|
|||
47 |
|
||||
48 | The Bourne shell is a very basic shell. /bin/sh on Linux is typically |
|
|||
49 | bash, which even in Bourne-shell mode has many features that Bourne shells |
|
|||
50 | on other Unix systems don't have (and even on Linux /bin/sh isn't |
|
|||
51 | guaranteed to be bash). You'll need to be careful about constructs that |
|
|||
52 | seem ubiquitous, but are actually not available in the least common |
|
|||
53 | denominator. While using another shell (ksh, bash explicitly, posix shell, |
|
|||
54 | etc.) explicitly may seem like another option, these may not exist in a |
|
|||
55 | portable location, and so are generally probably not a good idea. You may |
|
|||
56 | find that rewriting the test in python will be easier. |
|
|||
57 |
|
||||
58 | - don't use pushd/popd; save the output of "pwd" and use "cd" in place of |
|
|||
59 | the pushd, and cd back to the saved pwd instead of popd. |
|
|||
60 |
|
||||
61 | - don't use math expressions like let, (( ... )), or $(( ... )); use "expr" |
|
|||
62 | instead. |
|
|||
63 |
|
||||
64 | grep: |
|
|||
65 |
|
||||
66 | - don't use the -q option; redirect stdout to /dev/null instead. |
|
|||
67 |
|
||||
68 | - don't use extended regular expressions with grep; use egrep instead, and |
|
|||
69 | don't escape any regex operators. |
|
|||
70 |
|
||||
71 | sed: |
|
|||
72 |
|
||||
73 | - make sure that the beginning-of-line matcher ("^") is at the very |
|
|||
74 | beginning of the expression -- it may not be supported inside parens. |
|
|||
75 |
|
||||
76 | echo: |
|
|||
77 |
|
||||
78 | - echo may interpret "\n" and print a newline; use printf instead if you |
|
|||
79 | want a literal "\n" (backslash + n). |
|
|||
80 |
|
||||
81 | false: |
|
|||
82 |
|
||||
83 | - false is guaranteed only to return a non-zero value; you cannot depend on |
|
|||
84 | it being 1. On Solaris in particular, /bin/false returns 255. Rewrite |
|
|||
85 | your test to not depend on a particular return value, or create a |
|
|||
86 | temporary "false" executable, and call that instead. |
|
|||
87 |
|
||||
88 | diff: |
|
|||
89 |
|
||||
90 | - don't use the -N option. There's no particularly good workaround short |
|
|||
91 | of writing a reasonably complicated replacement script, but substituting |
|
|||
92 | gdiff for diff if you can't rewrite the test not to need -N will probably |
|
|||
93 | do. |
|
@@ -4,6 +4,8 b" echo 'syntax error' > badext.py" | |||||
4 | abspath=`pwd`/badext.py |
|
4 | abspath=`pwd`/badext.py | |
5 |
|
5 | |||
6 | echo '[extensions]' >> $HGRCPATH |
|
6 | echo '[extensions]' >> $HGRCPATH | |
|
7 | echo "gpg =" >> $HGRCPATH | |||
|
8 | echo "hgext.gpg =" >> $HGRCPATH | |||
7 | echo "badext = $abspath" >> $HGRCPATH |
|
9 | echo "badext = $abspath" >> $HGRCPATH | |
8 |
|
10 | |||
9 | hg -q help help |
|
11 | hg -q help help |
@@ -1,4 +1,5 b'' | |||||
1 | *** failed to import extension badext: invalid syntax (badext.py, line 1) |
|
1 | *** failed to import extension badext: invalid syntax (badext.py, line 1) | |
|
2 | extension 'hgext.gpg' overrides commands: sigs sigcheck sign | |||
2 | hg help [COMMAND] |
|
3 | hg help [COMMAND] | |
3 |
|
4 | |||
4 | show help for a command, extension, or list of commands |
|
5 | show help for a command, extension, or list of commands |
@@ -21,8 +21,7 b' abort: no match under directory .../test' | |||||
21 | dir/file |
|
21 | dir/file | |
22 | does-not-exist: No such file or directory |
|
22 | does-not-exist: No such file or directory | |
23 | abort: file .../test/does-not-exist not found! |
|
23 | abort: file .../test/does-not-exist not found! | |
24 | baz: unsupported file type (type is symbolic link) |
|
24 | abort: file .../test/baz not tracked! | |
25 | abort: can't commit .../test/baz: unsupported file type! |
|
|||
26 | abort: file .../test/quux not tracked! |
|
25 | abort: file .../test/quux not tracked! | |
27 | dir/file |
|
26 | dir/file | |
28 | % partial subdir commit test |
|
27 | % partial subdir commit test |
@@ -17,8 +17,11 b" hg commit -m 3 -u eggs -d '3 0'" | |||||
17 | head -n 3 port > port1 |
|
17 | head -n 3 port > port1 | |
18 | mv port1 port |
|
18 | mv port1 port | |
19 | hg commit -m 4 -u spam -d '4 0' |
|
19 | hg commit -m 4 -u spam -d '4 0' | |
|
20 | echo % simple | |||
20 | hg grep port port |
|
21 | hg grep port port | |
|
22 | echo % all | |||
21 | hg grep --all -nu port port |
|
23 | hg grep --all -nu port port | |
|
24 | echo % other | |||
22 | hg grep import port |
|
25 | hg grep import port | |
23 |
|
26 | |||
24 | hg cp port port2 |
|
27 | hg cp port port2 | |
@@ -28,3 +31,22 b" hg grep -f 'import$' port2" | |||||
28 | echo deport >> port2 |
|
31 | echo deport >> port2 | |
29 | hg commit -m 5 -u eggs -d '6 0' |
|
32 | hg commit -m 5 -u eggs -d '6 0' | |
30 | hg grep -f --all -nu port port2 |
|
33 | hg grep -f --all -nu port port2 | |
|
34 | ||||
|
35 | cd .. | |||
|
36 | hg init t2 | |||
|
37 | cd t2 | |||
|
38 | hg grep foobar foo | |||
|
39 | hg grep foobar | |||
|
40 | echo blue >> color | |||
|
41 | echo black >> color | |||
|
42 | hg add color | |||
|
43 | hg ci -m 0 -d '0 0' | |||
|
44 | echo orange >> color | |||
|
45 | hg ci -m 1 -d '0 0' | |||
|
46 | echo black > color | |||
|
47 | hg ci -m 2 -d '0 0' | |||
|
48 | echo orange >> color | |||
|
49 | echo blue >> color | |||
|
50 | hg ci -m 3 -d '0 0' | |||
|
51 | hg grep orange | |||
|
52 | hg grep --all orange |
@@ -1,6 +1,8 b'' | |||||
|
1 | % simple | |||
1 | port:4:export |
|
2 | port:4:export | |
2 | port:4:vaportight |
|
3 | port:4:vaportight | |
3 | port:4:import/export |
|
4 | port:4:import/export | |
|
5 | % all | |||
4 | port:4:4:-:spam:import/export |
|
6 | port:4:4:-:spam:import/export | |
5 | port:3:4:+:eggs:import/export |
|
7 | port:3:4:+:eggs:import/export | |
6 | port:2:1:-:spam:import |
|
8 | port:2:1:-:spam:import | |
@@ -10,6 +12,7 b' port:2:2:+:spam:vaportight' | |||||
10 | port:2:3:+:spam:import/export |
|
12 | port:2:3:+:spam:import/export | |
11 | port:1:2:+:eggs:export |
|
13 | port:1:2:+:eggs:export | |
12 | port:0:1:+:spam:import |
|
14 | port:0:1:+:spam:import | |
|
15 | % other | |||
13 | port:4:import/export |
|
16 | port:4:import/export | |
14 | % follow |
|
17 | % follow | |
15 | port:0:import |
|
18 | port:0:import | |
@@ -23,3 +26,7 b' port:2:2:+:spam:vaportight' | |||||
23 | port:2:3:+:spam:import/export |
|
26 | port:2:3:+:spam:import/export | |
24 | port:1:2:+:eggs:export |
|
27 | port:1:2:+:eggs:export | |
25 | port:0:1:+:spam:import |
|
28 | port:0:1:+:spam:import | |
|
29 | color:3:orange | |||
|
30 | color:3:+:orange | |||
|
31 | color:2:-:orange | |||
|
32 | color:1:+:orange |
@@ -1,11 +1,12 b'' | |||||
|
1 | adding bar | |||
1 | adding foo |
|
2 | adding foo | |
2 | adding bomb |
|
3 | adding bomb | |
3 | adding a.c |
|
4 | adding a.c | |
4 | adding dir/a.o |
|
5 | adding dir/a.o | |
5 | adding dir/b.o |
|
6 | adding dir/b.o | |
|
7 | M dir/b.o | |||
6 | ! a.c |
|
8 | ! a.c | |
7 | ! dir/a.o |
|
9 | ! dir/a.o | |
8 | ! dir/b.o |
|
|||
9 | ? .hgignore |
|
10 | ? .hgignore | |
10 | a.c: unsupported file type (type is fifo) |
|
11 | a.c: unsupported file type (type is fifo) | |
11 | ! a.c |
|
12 | ! a.c |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now