##// END OF EJS Templates
plan9: initial support for plan 9 from bell labs...
Steven Stallion -
r16383:f5dd179b default
parent child Browse files
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,5 b''
1 [extensions]
2 extdiff =
3
4 [extdiff]
5 9diff = 9diff -cm $parent $child $root
@@ -0,0 +1,2 b''
1 [extensions]
2 factotum =
@@ -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 | (Unix, Windows) ``<repo>/.hg/hgrc``
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 belong to a
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 for the
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, 'etc/mercurial')))
446 path.extend(rcfiles(os.path.join(p, root)))
443 path.extend(rcfiles('/etc/mercurial'))
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", "vi"))
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