> it would be nice to map as many hg/git operations to file operations as
> possible. for the rest providing special files (ctl, versions, etc) and
> directives don't seem out of place.
I've been thinking about combining synthetic file servers with shell
functionality, where Plan 9's rc (but possibly other shells, if
necessary) are initialised with a suite of commands, some of which,
like functions, will come from the namespace, while others will be
provided by a bind over /bin from the appropriate, fabricated
namespace.
I guess, in a way, this an extension of the concept used in busybox.
The idea then would be to start up a shell environment (not unlike
ape/psh) and navigate within it with conventional commands being
mapped to the appropriate procedures automatically.
I know this is a bit obscure, but I think a few examples attached to
something like hgfs (which I have steered clear of because of my
aversion to having Python in Plan 9 - I plead guilty to bigotism)
would explain things somewhat.
The nearest I've come to implementing some of these ideas, is an rc
startup script I wrote to access the OpenLDAP client commands. I use
it infrequently, but it does save me a lot of bother when I do.
The script, attached, is in turn invoked in a smaller, private script
(I call it $home/bin/rc/Ldap):
#!/bin/rc
window rc -m rcldap
L += 1
# rcmain for LDAP shell instance
if(~ $#home 0) home=/
if(~ $#ifs 0) ifs='
'
prompt=('ldap% ' ' ')
echo -n LDAP >/dev/label
if(~ $rcname ?.out) prompt=('broken! ' ' ')
if(flag p) path=/bin
if not{
finit
if(~ $#path 0) path=(. /bin)
}
test -d /n/ldap -a -d /n/ldap/bin || {
ramfs -m /n/ldap
mkdir /n/ldap/bin /n/ldap/tmp
for (x in add search delete modify modrdn compare passwd whoami) {
touch /n/ldap/bin/$x
test -e /$objtype/bin/pub/ldap^$x && bind
/$objtype/bin/pub/ldap^$x /n/ldap/bin/$x
}
bind /$objtype/bin/pub/ldapmodify /n/ldap/bin/add
bind -b /n/ldap/bin /bin
}
test -f $home/lib/ldaprc && . $home/lib/ldaprc
fn ep {
echo -n $1^' = <' | tr a-z A-Z
test -e '#e/'^$1 && cat '#e/'^$1
echo '>'
}
fn e {
ep admin
ep attrib
ep base
ep binddn
ep filter
ep host
ep opts
ep scope
}
fn s {
arg=()
if(! ~ $#host 0) arg=($arg -h^$host)
if(! ~ $#binddn 0) arg=($arg -D^$binddn)
if(! ~ $#base 0) arg=($arg -b^$base)
if(! ~ $#scope 0) arg=($arg -s^$scope)
if(! ~ $#opts 0) arg=($arg $opts)
if(! ~ $#filter 0) arg=($arg $filter)
if(! ~ $#attrib 0) arg=($arg $attrib)
if(flag x) echo search $arg $*
search $arg $*
}
fn a {
arg=()
if(! ~ $#host 0) arg=($arg -h^$host)
if(! ~ $#admin 0) arg=($arg -D^$admin)
if(! ~ $#opts 0) arg=($arg $opts)
if(flag x) echo add -a $arg
add -a $arg
}
fn m {
arg=()
if(! ~ $#host 0) arg=($arg -h^$host)
if(! ~ $#admin 0) arg=($arg -D^$admin)
if(! ~ $#opts 0) arg=($arg $opts)
if(flag x) echo modify $arg
modify $arg
}
fn d {
arg=()
if(! ~ $#host 0) arg=($arg -h^$host)
if(! ~ $#admin 0) arg=($arg -D^$admin)
if(! ~ $#opts 0) arg=($arg $opts)
if(flag x) echo delete $arg $*
delete $arg $*
}
fn p {
if(~ $#* 0){
filter='(objectclass=person)'}
if not {
filter='(&(objectclass=person)(cn='^$"*^'))'}
if(~ $#attrib 1){
filter='(&'^$filter^'('^$attrib(1)^'=*))'
}
s
}
fn enhance {
arg=()
if(! ~ $#host 0) arg=($arg -h^$host)
if(~ $#admin 0){
if(! ~ $#binddn 0) arg=($arg -D^$"binddn)
}
if not arg=($arg -D^$"admin)
if(! ~ $#opts 0) arg=($arg $opts)
if(! ~ $#* 0){
dn=$1; shift
}
if(! ~ $#* 0){
attrib=$1; shift
}
if(flag x)echo modify $arg
if(! ~ $#dn 0){
if(flag x){
echo dn: $dn
echo changetype: modify
echo add: $attrib
echo $attrib: $"*
echo
}
{
echo dn: $dn
echo changetype: modify
echo add: $attrib
echo $attrib: $"*
echo
} | modify $arg
}
if not modify $arg
}
if(! ~ $#cflag 0){
if(flag l && /bin/test -r $home/lib/profile) . $home/lib/profile
status=''
eval $cflag
}
if not if(flag i){
if(flag l && /bin/test -r $home/lib/profile) . $home/lib/profile
status=''
if(! ~ $#* 0) . $*
. -i '#d/0'
}
if not if(~ $#* 0) . '#d/0'
if not{
status=''
. $*
}
exit $status