Show More
@@ -0,0 +1,42 b'' | |||||
|
1 | #!/bin/rc | |||
|
2 | # 9diff - Mercurial extdiff wrapper for diff(1) | |||
|
3 | ||||
|
4 | rfork e | |||
|
5 | ||||
|
6 | fn getfiles{ | |||
|
7 | cd $1 && \ | |||
|
8 | for(f in `{du -as | awk '{print $2}'}) | |||
|
9 | test -f $f && echo `{cleanname $f} | |||
|
10 | } | |||
|
11 | ||||
|
12 | fn usage{ | |||
|
13 | echo >[1=2] usage: 9diff [diff options] parent child root | |||
|
14 | exit usage | |||
|
15 | } | |||
|
16 | ||||
|
17 | opts=() | |||
|
18 | while(~ $1 -*){ | |||
|
19 | opts=($opts $1) | |||
|
20 | shift | |||
|
21 | } | |||
|
22 | if(! ~ $#* 3) | |||
|
23 | usage | |||
|
24 | ||||
|
25 | # extdiff will set the parent and child to a single file if there is | |||
|
26 | # only one change. If there are multiple changes, directories will be | |||
|
27 | # set. diff(1) does not cope particularly with directories; instead we | |||
|
28 | # do the recursion ourselves and diff each file individually. | |||
|
29 | if(test -f $1) | |||
|
30 | diff $opts $1 $2 | |||
|
31 | if not{ | |||
|
32 | # extdiff will create a snapshot of the working copy to prevent | |||
|
33 | # conflicts during the diff. We circumvent this behavior by | |||
|
34 | # diffing against the repository root to produce plumbable | |||
|
35 | # output. This is antisocial. | |||
|
36 | for(f in `{sort -u <{getfiles $1} <{getfiles $2}}){ | |||
|
37 | file1=$1/$f; test -f $file1 || file1=/dev/null | |||
|
38 | file2=$3/$f; test -f $file2 || file2=/dev/null | |||
|
39 | diff $opts $file1 $file2 | |||
|
40 | } | |||
|
41 | } | |||
|
42 | exit '' |
@@ -0,0 +1,39 b'' | |||||
|
1 | Mercurial for Plan 9 from Bell Labs | |||
|
2 | =================================== | |||
|
3 | ||||
|
4 | This directory contains support for Mercurial on Plan 9 from Bell Labs | |||
|
5 | platforms. It is assumed that the version of Python running on these | |||
|
6 | systems supports the ANSI/POSIX Environment (APE). At the time of this | |||
|
7 | writing, the bichued/python port is the most commonly installed version | |||
|
8 | of Python on these platforms. If a native port of Python is ever made, | |||
|
9 | some minor modification will need to be made to support some of the more | |||
|
10 | esoteric requirements of the platform rather than those currently made | |||
|
11 | (cf. posix.py). | |||
|
12 | ||||
|
13 | By default, installations will have the factotum extension enabled; this | |||
|
14 | extension permits factotum(4) to act as an authentication agent for | |||
|
15 | HTTP repositories. Additionally, an extdiff command named 9diff is | |||
|
16 | enabled which generates diff(1) compatible output suitable for use with | |||
|
17 | the plumber(4). | |||
|
18 | ||||
|
19 | Commit messages are plumbed using E if no editor is defined; users must | |||
|
20 | update the plumbed file to continue, otherwise the hg process must be | |||
|
21 | interrupted. | |||
|
22 | ||||
|
23 | Some work remains with regard to documentation. Section 5 manual page | |||
|
24 | references for hgignore and hgrc need to be re-numbered to section 6 (file | |||
|
25 | formats) and a new man page writer should be written to support the | |||
|
26 | Plan 9 man macro set. Until these issues can be resolved, manual pages | |||
|
27 | are elided from the installation. | |||
|
28 | ||||
|
29 | Basic install: | |||
|
30 | ||||
|
31 | % mk install # do a system-wide install | |||
|
32 | % hg debuginstall # sanity-check setup | |||
|
33 | % hg # see help | |||
|
34 | ||||
|
35 | A proto(2) file is included in this directory as an example of how a | |||
|
36 | binary distribution could be packaged, ostensibly with contrib(1). | |||
|
37 | ||||
|
38 | See http://mercurial.selenic.com/ for detailed installation | |||
|
39 | instructions, platform-specific notes, and Mercurial user information. |
@@ -0,0 +1,37 b'' | |||||
|
1 | APE=/sys/src/ape | |||
|
2 | <$APE/config | |||
|
3 | ||||
|
4 | PYTHON=python | |||
|
5 | PYTHONBIN=/rc/bin | |||
|
6 | SH=ape/psh | |||
|
7 | ||||
|
8 | PURE=--pure | |||
|
9 | ROOT=../.. | |||
|
10 | ||||
|
11 | # This is slightly underhanded; Plan 9 does not support GNU gettext nor | |||
|
12 | # does it support dynamically loaded extension modules. We work around | |||
|
13 | # this by calling build_py and build_scripts directly; this avoids | |||
|
14 | # additional platform hacks in setup.py. | |||
|
15 | build:VQ: | |||
|
16 | @{ | |||
|
17 | cd $ROOT | |||
|
18 | $SH -c '$PYTHON setup.py $PURE build_py build_scripts' | |||
|
19 | } | |||
|
20 | ||||
|
21 | clean:VQ: | |||
|
22 | @{ | |||
|
23 | cd $ROOT | |||
|
24 | $SH -c '$PYTHON setup.py $PURE clean --all' | |||
|
25 | } | |||
|
26 | ||||
|
27 | install:VQ: build | |||
|
28 | @{ | |||
|
29 | cd $ROOT | |||
|
30 | $SH -c '$PYTHON setup.py $PURE install \ | |||
|
31 | --install-scripts $PYTHONBIN \ | |||
|
32 | --skip-build' \ | |||
|
33 | --force | |||
|
34 | } | |||
|
35 | mkdir -p /lib/mercurial/hgrc.d | |||
|
36 | dircp hgrc.d /lib/mercurial/hgrc.d | |||
|
37 | cp 9diff /rc/bin |
@@ -0,0 +1,20 b'' | |||||
|
1 | lib - sys sys | |||
|
2 | mercurial - sys sys | |||
|
3 | hgrc.d - sys sys | |||
|
4 | 9diff.rc - sys sys | |||
|
5 | factotum.rc - sys sys | |||
|
6 | rc - sys sys | |||
|
7 | bin - sys sys | |||
|
8 | 9diff - sys sys | |||
|
9 | hg - sys sys | |||
|
10 | sys - sys sys | |||
|
11 | lib - sys sys | |||
|
12 | python - sys sys | |||
|
13 | lib - sys sys | |||
|
14 | python2.5 - sys sys | |||
|
15 | site-packages - sys sys | |||
|
16 | hgext - sys sys | |||
|
17 | + - sys sys | |||
|
18 | mercurial - sys sys | |||
|
19 | + - sys sys | |||
|
20 | mercurial-2.1.1-py2.5.egg-info - sys sys |
@@ -0,0 +1,120 b'' | |||||
|
1 | # factotum.py - Plan 9 factotum integration for Mercurial | |||
|
2 | # | |||
|
3 | # Copyright (C) 2012 Steven Stallion <sstallion@gmail.com> | |||
|
4 | # | |||
|
5 | # This program is free software; you can redistribute it and/or modify it | |||
|
6 | # under the terms of the GNU General Public License as published by the | |||
|
7 | # Free Software Foundation; either version 2 of the License, or (at your | |||
|
8 | # option) any later version. | |||
|
9 | # | |||
|
10 | # This program is distributed in the hope that it will be useful, but | |||
|
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | |||
|
13 | # Public License for more details. | |||
|
14 | # | |||
|
15 | # You should have received a copy of the GNU General Public License along | |||
|
16 | # with this program; if not, write to the Free Software Foundation, Inc., | |||
|
17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
|
18 | ||||
|
19 | '''http authentication with factotum | |||
|
20 | ||||
|
21 | This extension allows the factotum facility on Plan 9 from Bell Labs platforms | |||
|
22 | to provide authentication information for HTTP access. Configuration entries | |||
|
23 | specified in the auth section as well as authentication information provided | |||
|
24 | in the repository URL are fully supported. If no prefix is specified, a value | |||
|
25 | of ``*`` will be assumed. | |||
|
26 | ||||
|
27 | By default, keys are specified as:: | |||
|
28 | ||||
|
29 | proto=pass service=hg prefix=<prefix> user=<username> !password=<password> | |||
|
30 | ||||
|
31 | If the factotum extension is unable to read the required key, one will be | |||
|
32 | requested interactively. | |||
|
33 | ||||
|
34 | A configuration section is available to customize runtime behavior. By | |||
|
35 | default, these entries are:: | |||
|
36 | ||||
|
37 | [factotum] | |||
|
38 | mount = /mnt/factotum | |||
|
39 | path = /bin/auth/factotum | |||
|
40 | service = hg | |||
|
41 | ||||
|
42 | The mount entry defines the mount point for the factotum file service. The | |||
|
43 | path entry defines the full path to the factotum binary. Lastly, the service | |||
|
44 | entry controls the service name used when reading keys. | |||
|
45 | ||||
|
46 | ''' | |||
|
47 | ||||
|
48 | from mercurial.i18n import _ | |||
|
49 | from mercurial.url import passwordmgr | |||
|
50 | from mercurial import httpconnection, urllib2, util | |||
|
51 | import os | |||
|
52 | ||||
|
53 | ERRMAX = 128 | |||
|
54 | ||||
|
55 | def auth_getkey(self, params): | |||
|
56 | if not self.ui.interactive(): | |||
|
57 | raise util.Abort(_('factotum not interactive')) | |||
|
58 | if 'user=' not in params: | |||
|
59 | params = '%s user?' % params | |||
|
60 | params = '%s !password?' % params | |||
|
61 | os.system("%s -g '%s'" % (_path, params)) | |||
|
62 | ||||
|
63 | def auth_getuserpasswd(self, getkey, params): | |||
|
64 | params = 'proto=pass %s' % params | |||
|
65 | while True: | |||
|
66 | fd = os.open('%s/rpc' % _mount, os.O_RDWR) | |||
|
67 | try: | |||
|
68 | try: | |||
|
69 | os.write(fd, 'start %s' % params) | |||
|
70 | l = os.read(fd, ERRMAX).split() | |||
|
71 | if l[0] == 'ok': | |||
|
72 | os.write(fd, 'read') | |||
|
73 | l = os.read(fd, ERRMAX).split() | |||
|
74 | if l[0] == 'ok': | |||
|
75 | return l[1:] | |||
|
76 | except (OSError, IOError): | |||
|
77 | raise util.Abort(_('factotum not responding')) | |||
|
78 | finally: | |||
|
79 | os.close(fd) | |||
|
80 | getkey(self, params) | |||
|
81 | ||||
|
82 | def monkeypatch_method(cls): | |||
|
83 | def decorator(func): | |||
|
84 | setattr(cls, func.__name__, func) | |||
|
85 | return func | |||
|
86 | return decorator | |||
|
87 | ||||
|
88 | @monkeypatch_method(passwordmgr) | |||
|
89 | def find_user_password(self, realm, authuri): | |||
|
90 | user, passwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password( | |||
|
91 | self, realm, authuri) | |||
|
92 | if user and passwd: | |||
|
93 | self._writedebug(user, passwd) | |||
|
94 | return (user, passwd) | |||
|
95 | ||||
|
96 | prefix = '' | |||
|
97 | res = httpconnection.readauthforuri(self.ui, authuri, user) | |||
|
98 | if res: | |||
|
99 | _, auth = res | |||
|
100 | prefix = auth.get('prefix') | |||
|
101 | user, passwd = auth.get('username'), auth.get('password') | |||
|
102 | if not user or not passwd: | |||
|
103 | if not prefix: | |||
|
104 | prefix = '*' | |||
|
105 | params = 'service=%s prefix=%s' % (_service, prefix) | |||
|
106 | if user: | |||
|
107 | params = '%s user=%s' % (params, user) | |||
|
108 | user, passwd = auth_getuserpasswd(self, auth_getkey, params) | |||
|
109 | ||||
|
110 | self.add_password(realm, authuri, user, passwd) | |||
|
111 | self._writedebug(user, passwd) | |||
|
112 | return (user, passwd) | |||
|
113 | ||||
|
114 | def uisetup(ui): | |||
|
115 | global _mount | |||
|
116 | _mount = ui.config('factotum', 'mount', '/mnt/factotum') | |||
|
117 | global _path | |||
|
118 | _path = ui.config('factotum', 'path', '/bin/auth/factotum') | |||
|
119 | global _service | |||
|
120 | _service = ui.config('factotum', 'service', 'hg') |
@@ -28,16 +28,17 b' alphabetical order, later ones overridin' | |||||
28 | paths are given below, settings from earlier paths override later |
|
28 | paths are given below, settings from earlier paths override later | |
29 | ones. |
|
29 | ones. | |
30 |
|
30 | |||
31 |
| ( |
|
31 | | (All) ``<repo>/.hg/hgrc`` | |
32 |
|
32 | |||
33 | Per-repository configuration options that only apply in a |
|
33 | Per-repository configuration options that only apply in a | |
34 | particular repository. This file is not version-controlled, and |
|
34 | particular repository. This file is not version-controlled, and | |
35 | will not get transferred during a "clone" operation. Options in |
|
35 | will not get transferred during a "clone" operation. Options in | |
36 | this file override options in all other configuration files. On |
|
36 | this file override options in all other configuration files. On | |
37 |
Unix, most of this file will be ignored if it doesn't |
|
37 | Plan 9 and Unix, most of this file will be ignored if it doesn't | |
38 |
trusted user or to a trusted group. See the documentation |
|
38 | belong to a trusted user or to a trusted group. See the documentation | |
39 | ``[trusted]`` section below for more details. |
|
39 | for the ``[trusted]`` section below for more details. | |
40 |
|
40 | |||
|
41 | | (Plan 9) ``$home/lib/hgrc`` | |||
41 | | (Unix) ``$HOME/.hgrc`` |
|
42 | | (Unix) ``$HOME/.hgrc`` | |
42 | | (Windows) ``%USERPROFILE%\.hgrc`` |
|
43 | | (Windows) ``%USERPROFILE%\.hgrc`` | |
43 | | (Windows) ``%USERPROFILE%\Mercurial.ini`` |
|
44 | | (Windows) ``%USERPROFILE%\Mercurial.ini`` | |
@@ -50,6 +51,8 b' ones.' | |||||
50 | directory. Options in these files override per-system and per-installation |
|
51 | directory. Options in these files override per-system and per-installation | |
51 | options. |
|
52 | options. | |
52 |
|
53 | |||
|
54 | | (Plan 9) ``/lib/mercurial/hgrc`` | |||
|
55 | | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc`` | |||
53 | | (Unix) ``/etc/mercurial/hgrc`` |
|
56 | | (Unix) ``/etc/mercurial/hgrc`` | |
54 | | (Unix) ``/etc/mercurial/hgrc.d/*.rc`` |
|
57 | | (Unix) ``/etc/mercurial/hgrc.d/*.rc`` | |
55 |
|
58 | |||
@@ -58,6 +61,8 b' ones.' | |||||
58 | executed by any user in any directory. Options in these files |
|
61 | executed by any user in any directory. Options in these files | |
59 | override per-installation options. |
|
62 | override per-installation options. | |
60 |
|
63 | |||
|
64 | | (Plan 9) ``<install-root>/lib/mercurial/hgrc`` | |||
|
65 | | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc`` | |||
61 | | (Unix) ``<install-root>/etc/mercurial/hgrc`` |
|
66 | | (Unix) ``<install-root>/etc/mercurial/hgrc`` | |
62 | | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc`` |
|
67 | | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc`` | |
63 |
|
68 |
@@ -333,6 +333,9 b' def findexe(command):' | |||||
333 | if os.sep in command: |
|
333 | if os.sep in command: | |
334 | return findexisting(command) |
|
334 | return findexisting(command) | |
335 |
|
335 | |||
|
336 | if sys.platform == 'plan9': | |||
|
337 | return findexisting(os.path.join('/bin', command)) | |||
|
338 | ||||
336 | for path in os.environ.get('PATH', '').split(os.pathsep): |
|
339 | for path in os.environ.get('PATH', '').split(os.pathsep): | |
337 | executable = findexisting(os.path.join(path, command)) |
|
340 | executable = findexisting(os.path.join(path, command)) | |
338 | if executable is not None: |
|
341 | if executable is not None: |
@@ -436,15 +436,22 b" if os.name != 'nt':" | |||||
436 |
|
436 | |||
437 | def systemrcpath(): |
|
437 | def systemrcpath(): | |
438 | path = [] |
|
438 | path = [] | |
|
439 | if sys.platform == 'plan9': | |||
|
440 | root = '/lib/mercurial' | |||
|
441 | else: | |||
|
442 | root = '/etc/mercurial' | |||
439 | # old mod_python does not set sys.argv |
|
443 | # old mod_python does not set sys.argv | |
440 | if len(getattr(sys, 'argv', [])) > 0: |
|
444 | if len(getattr(sys, 'argv', [])) > 0: | |
441 | p = os.path.dirname(os.path.dirname(sys.argv[0])) |
|
445 | p = os.path.dirname(os.path.dirname(sys.argv[0])) | |
442 |
path.extend(rcfiles(os.path.join(p, |
|
446 | path.extend(rcfiles(os.path.join(p, root))) | |
443 |
path.extend(rcfiles( |
|
447 | path.extend(rcfiles(root)) | |
444 | return path |
|
448 | return path | |
445 |
|
449 | |||
446 | def userrcpath(): |
|
450 | def userrcpath(): | |
447 | return [os.path.expanduser('~/.hgrc')] |
|
451 | if sys.platform == 'plan9': | |
|
452 | return [os.environ['home'] + '/lib/hgrc'] | |||
|
453 | else: | |||
|
454 | return [os.path.expanduser('~/.hgrc')] | |||
448 |
|
455 | |||
449 | else: |
|
456 | else: | |
450 |
|
457 |
@@ -687,10 +687,17 b' class ui(object):' | |||||
687 |
|
687 | |||
688 | def geteditor(self): |
|
688 | def geteditor(self): | |
689 | '''return editor to use''' |
|
689 | '''return editor to use''' | |
|
690 | if sys.platform == 'plan9': | |||
|
691 | # vi is the MIPS instruction simulator on Plan 9. We | |||
|
692 | # instead default to E to plumb commit messages to | |||
|
693 | # avoid confusion. | |||
|
694 | editor = 'E' | |||
|
695 | else: | |||
|
696 | editor = 'vi' | |||
690 | return (os.environ.get("HGEDITOR") or |
|
697 | return (os.environ.get("HGEDITOR") or | |
691 | self.config("ui", "editor") or |
|
698 | self.config("ui", "editor") or | |
692 | os.environ.get("VISUAL") or |
|
699 | os.environ.get("VISUAL") or | |
693 |
os.environ.get("EDITOR", |
|
700 | os.environ.get("EDITOR", editor)) | |
694 |
|
701 | |||
695 | def progress(self, topic, pos, item="", unit="", total=None): |
|
702 | def progress(self, topic, pos, item="", unit="", total=None): | |
696 | '''show a progress message |
|
703 | '''show a progress message |
@@ -422,22 +422,29 b' def system(cmd, environ={}, cwd=None, on' | |||||
422 | return str(val) |
|
422 | return str(val) | |
423 | origcmd = cmd |
|
423 | origcmd = cmd | |
424 | cmd = quotecommand(cmd) |
|
424 | cmd = quotecommand(cmd) | |
425 | env = dict(os.environ) |
|
425 | if sys.platform == 'plan9': | |
426 | env.update((k, py2shell(v)) for k, v in environ.iteritems()) |
|
426 | # subprocess kludge to work around issues in half-baked Python | |
427 | env['HG'] = hgexecutable() |
|
427 | # ports, notably bichued/python: | |
428 | if out is None or out == sys.__stdout__: |
|
428 | if not cwd is None: | |
429 | rc = subprocess.call(cmd, shell=True, close_fds=closefds, |
|
429 | os.chdir(cwd) | |
430 | env=env, cwd=cwd) |
|
430 | rc = os.system(cmd) | |
431 | else: |
|
431 | else: | |
432 | proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, |
|
432 | env = dict(os.environ) | |
433 | env=env, cwd=cwd, stdout=subprocess.PIPE, |
|
433 | env.update((k, py2shell(v)) for k, v in environ.iteritems()) | |
434 | stderr=subprocess.STDOUT) |
|
434 | env['HG'] = hgexecutable() | |
435 | for line in proc.stdout: |
|
435 | if out is None or out == sys.__stdout__: | |
436 | out.write(line) |
|
436 | rc = subprocess.call(cmd, shell=True, close_fds=closefds, | |
437 | proc.wait() |
|
437 | env=env, cwd=cwd) | |
438 | rc = proc.returncode |
|
438 | else: | |
439 | if sys.platform == 'OpenVMS' and rc & 1: |
|
439 | proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, | |
440 | rc = 0 |
|
440 | env=env, cwd=cwd, stdout=subprocess.PIPE, | |
|
441 | stderr=subprocess.STDOUT) | |||
|
442 | for line in proc.stdout: | |||
|
443 | out.write(line) | |||
|
444 | proc.wait() | |||
|
445 | rc = proc.returncode | |||
|
446 | if sys.platform == 'OpenVMS' and rc & 1: | |||
|
447 | rc = 0 | |||
441 | if rc and onerr: |
|
448 | if rc and onerr: | |
442 | errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]), |
|
449 | errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]), | |
443 | explainexit(rc)[0]) |
|
450 | explainexit(rc)[0]) |
@@ -127,10 +127,16 b' except ImportError:' | |||||
127 | py2exeloaded = False |
|
127 | py2exeloaded = False | |
128 |
|
128 | |||
129 | def runcmd(cmd, env): |
|
129 | def runcmd(cmd, env): | |
130 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, |
|
130 | if sys.platform == 'plan9': | |
131 | stderr=subprocess.PIPE, env=env) |
|
131 | # subprocess kludge to work around issues in half-baked Python | |
132 | out, err = p.communicate() |
|
132 | # ports, notably bichued/python: | |
133 | return out, err |
|
133 | _, out, err = os.popen3(cmd) | |
|
134 | return str(out), str(err) | |||
|
135 | else: | |||
|
136 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, | |||
|
137 | stderr=subprocess.PIPE, env=env) | |||
|
138 | out, err = p.communicate() | |||
|
139 | return out, err | |||
134 |
|
140 | |||
135 | def runhg(cmd, env): |
|
141 | def runhg(cmd, env): | |
136 | out, err = runcmd(cmd, env) |
|
142 | out, err = runcmd(cmd, env) |
@@ -1,7 +1,7 b'' | |||||
1 | import os |
|
1 | import os | |
2 | from mercurial import ui, commands, extensions |
|
2 | from mercurial import ui, commands, extensions | |
3 |
|
3 | |||
4 | ignore = set(['highlight', 'inotify', 'win32text']) |
|
4 | ignore = set(['highlight', 'inotify', 'win32text', 'factotum']) | |
5 |
|
5 | |||
6 | if os.name != 'nt': |
|
6 | if os.name != 'nt': | |
7 | ignore.add('win32mbcs') |
|
7 | ignore.add('win32mbcs') |
General Comments 0
You need to be logged in to leave comments.
Login now