add git-annex-shell command
This is not yet complete, as it does not allow starting rsync or scp.
This commit is contained in:
parent
88ff9e82fc
commit
7a52b34e06
9 changed files with 200 additions and 59 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,6 +3,8 @@ test
|
||||||
configure
|
configure
|
||||||
SysConfig.hs
|
SysConfig.hs
|
||||||
git-annex
|
git-annex
|
||||||
|
git-annex-shell
|
||||||
git-annex.1
|
git-annex.1
|
||||||
|
git-annex-shell.1
|
||||||
doc/.ikiwiki
|
doc/.ikiwiki
|
||||||
html
|
html
|
||||||
|
|
36
CmdLine.hs
36
CmdLine.hs
|
@ -6,14 +6,13 @@
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module CmdLine (
|
module CmdLine (
|
||||||
cmdLine,
|
dispatch,
|
||||||
parseCmd,
|
parseCmd,
|
||||||
Option,
|
Option,
|
||||||
storeOptBool,
|
storeOptBool,
|
||||||
storeOptString,
|
storeOptString,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import System.Environment
|
|
||||||
import System.Console.GetOpt
|
import System.Console.GetOpt
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
import Control.Monad.State (liftIO)
|
import Control.Monad.State (liftIO)
|
||||||
|
@ -25,21 +24,11 @@ import Command
|
||||||
import BackendList
|
import BackendList
|
||||||
import Core
|
import Core
|
||||||
import Upgrade
|
import Upgrade
|
||||||
|
import Options
|
||||||
|
|
||||||
{- Each dashed command-line option results in generation of an action
|
{- Runs the passed command line. -}
|
||||||
- in the Annex monad that performs the necessary setting.
|
dispatch :: [String] -> [Command] -> [Option] -> String -> IO ()
|
||||||
-}
|
dispatch args cmds options header = do
|
||||||
type Option = OptDescr (Annex ())
|
|
||||||
|
|
||||||
storeOptBool :: FlagName -> Bool -> Annex ()
|
|
||||||
storeOptBool name val = Annex.flagChange name $ FlagBool val
|
|
||||||
storeOptString :: FlagName -> String -> Annex ()
|
|
||||||
storeOptString name val = Annex.flagChange name $ FlagString val
|
|
||||||
|
|
||||||
{- It all starts here. -}
|
|
||||||
cmdLine :: [Command] -> [Option] -> String -> IO ()
|
|
||||||
cmdLine cmds options header = do
|
|
||||||
args <- getArgs
|
|
||||||
gitrepo <- Git.repoFromCwd
|
gitrepo <- Git.repoFromCwd
|
||||||
state <- Annex.new gitrepo allBackends
|
state <- Annex.new gitrepo allBackends
|
||||||
(actions, state') <- Annex.run state $ parseCmd args header cmds options
|
(actions, state') <- Annex.run state $ parseCmd args header cmds options
|
||||||
|
@ -50,24 +39,27 @@ cmdLine cmds options header = do
|
||||||
parseCmd :: [String] -> String -> [Command] -> [Option] -> Annex [Annex Bool]
|
parseCmd :: [String] -> String -> [Command] -> [Option] -> Annex [Annex Bool]
|
||||||
parseCmd argv header cmds options = do
|
parseCmd argv header cmds options = do
|
||||||
(flags, params) <- liftIO $ getopt
|
(flags, params) <- liftIO $ getopt
|
||||||
when (null params) $ error usagemsg
|
when (null params) $ error $ "missing command" ++ usagemsg
|
||||||
case lookupCmd (head params) of
|
case lookupCmd (head params) of
|
||||||
[] -> error usagemsg
|
[] -> error $ "unknown command" ++ usagemsg
|
||||||
[command] -> do
|
[command] -> do
|
||||||
_ <- sequence flags
|
_ <- sequence flags
|
||||||
prepCmd command (drop 1 params)
|
prepCmd command (drop 1 params)
|
||||||
_ -> error "internal error: multiple matching commands"
|
_ -> error "internal error: multiple matching commands"
|
||||||
where
|
where
|
||||||
getopt = case getOpt Permute options argv of
|
getopt = case getOpt Permute options argv of
|
||||||
(flags, params, []) -> return (flags, params)
|
(flags, params, []) ->
|
||||||
(_, _, errs) -> ioError (userError (concat errs ++ usagemsg))
|
return (flags, params)
|
||||||
|
(_, _, errs) ->
|
||||||
|
ioError (userError (concat errs ++ usagemsg))
|
||||||
lookupCmd cmd = filter (\c -> cmd == cmdname c) cmds
|
lookupCmd cmd = filter (\c -> cmd == cmdname c) cmds
|
||||||
usagemsg = usage header cmds options
|
usagemsg = "\n\n" ++ usage header cmds options
|
||||||
|
|
||||||
{- Usage message with lists of commands and options. -}
|
{- Usage message with lists of commands and options. -}
|
||||||
usage :: String -> [Command] -> [Option] -> String
|
usage :: String -> [Command] -> [Option] -> String
|
||||||
usage header cmds options =
|
usage header cmds options =
|
||||||
usageInfo header options ++ "\nSubcommands:\n" ++ cmddescs
|
usageInfo (header ++ "\n\nOptions:") options ++
|
||||||
|
"\nCommands:\n" ++ cmddescs
|
||||||
where
|
where
|
||||||
cmddescs = unlines $ map (indent . showcmd) cmds
|
cmddescs = unlines $ map (indent . showcmd) cmds
|
||||||
showcmd c =
|
showcmd c =
|
||||||
|
|
|
@ -21,7 +21,7 @@ import Core
|
||||||
import Messages
|
import Messages
|
||||||
|
|
||||||
command :: [Command]
|
command :: [Command]
|
||||||
command = [Command "fromkey" (paramRepeating paramKey) seek
|
command = [Command "fromkey" paramPath seek
|
||||||
"adds a file using a specific key"]
|
"adds a file using a specific key"]
|
||||||
|
|
||||||
seek :: [CommandSeek]
|
seek :: [CommandSeek]
|
||||||
|
|
23
Makefile
23
Makefile
|
@ -2,23 +2,28 @@ PREFIX=/usr
|
||||||
GHCFLAGS=-O2 -Wall
|
GHCFLAGS=-O2 -Wall
|
||||||
GHCMAKE=ghc -odir build -hidir build $(GHCFLAGS) --make
|
GHCMAKE=ghc -odir build -hidir build $(GHCFLAGS) --make
|
||||||
|
|
||||||
all: git-annex git-annex.1 docs
|
bins=git-annex git-annex-shell
|
||||||
|
mans=git-annex.1 git-annex-shell.1
|
||||||
|
|
||||||
|
all: $(bins) $(mans) docs
|
||||||
|
|
||||||
SysConfig.hs: configure.hs
|
SysConfig.hs: configure.hs
|
||||||
$(GHCMAKE) configure
|
$(GHCMAKE) configure
|
||||||
./configure
|
./configure
|
||||||
|
|
||||||
|
$(bins): SysConfig.hs
|
||||||
|
$(GHCMAKE) $@
|
||||||
|
|
||||||
git-annex.1:
|
git-annex.1:
|
||||||
./mdwn2man git-annex 1 doc/git-annex.mdwn > git-annex.1
|
./mdwn2man git-annex 1 doc/git-annex.mdwn > git-annex.1
|
||||||
|
git-annex-shell.1:
|
||||||
git-annex: SysConfig.hs
|
./mdwn2man git-annex 1 doc/git-annex-shell.mdwn > git-annex-shell.1
|
||||||
$(GHCMAKE) git-annex
|
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
install -d $(DESTDIR)$(PREFIX)/bin
|
install -d $(DESTDIR)$(PREFIX)/bin
|
||||||
install git-annex $(DESTDIR)$(PREFIX)/bin
|
install $(bins) $(DESTDIR)$(PREFIX)/bin
|
||||||
install -d $(DESTDIR)$(PREFIX)/share/man/man1
|
install -d $(DESTDIR)$(PREFIX)/share/man/man1
|
||||||
install -m 0644 git-annex.1 $(DESTDIR)$(PREFIX)/share/man/man1
|
install -m 0644 $(mans) $(DESTDIR)$(PREFIX)/share/man/man1
|
||||||
install -d $(DESTDIR)$(PREFIX)/share/doc/git-annex
|
install -d $(DESTDIR)$(PREFIX)/share/doc/git-annex
|
||||||
if [ -d html ]; then \
|
if [ -d html ]; then \
|
||||||
rsync -a --delete html/ $(DESTDIR)$(PREFIX)/share/doc/git-annex/html/; \
|
rsync -a --delete html/ $(DESTDIR)$(PREFIX)/share/doc/git-annex/html/; \
|
||||||
|
@ -36,7 +41,7 @@ else
|
||||||
IKIWIKI=ikiwiki
|
IKIWIKI=ikiwiki
|
||||||
endif
|
endif
|
||||||
|
|
||||||
docs: git-annex.1
|
docs: $(mans)
|
||||||
$(IKIWIKI) doc html -v --wikiname git-annex --plugin=goodstuff \
|
$(IKIWIKI) doc html -v --wikiname git-annex --plugin=goodstuff \
|
||||||
--no-usedirs --disable-plugin=openid --plugin=sidebar \
|
--no-usedirs --disable-plugin=openid --plugin=sidebar \
|
||||||
--underlaydir=/dev/null --disable-plugin=shortcut \
|
--underlaydir=/dev/null --disable-plugin=shortcut \
|
||||||
|
@ -44,7 +49,7 @@ docs: git-annex.1
|
||||||
--exclude='news/.*'
|
--exclude='news/.*'
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build git-annex git-annex.1 test configure SysConfig.hs
|
rm -rf build $(bins) $(mans) test configure SysConfig.hs
|
||||||
rm -rf doc/.ikiwiki html
|
rm -rf doc/.ikiwiki html
|
||||||
|
|
||||||
.PHONY: git-annex test install
|
.PHONY: $(bins) test install
|
||||||
|
|
44
Options.hs
Normal file
44
Options.hs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{- git-annex dashed options
|
||||||
|
-
|
||||||
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Options where
|
||||||
|
|
||||||
|
import System.Console.GetOpt
|
||||||
|
|
||||||
|
import qualified Annex
|
||||||
|
import Types
|
||||||
|
import Command
|
||||||
|
|
||||||
|
{- Each dashed command-line option results in generation of an action
|
||||||
|
- in the Annex monad that performs the necessary setting.
|
||||||
|
-}
|
||||||
|
type Option = OptDescr (Annex ())
|
||||||
|
|
||||||
|
storeOptBool :: FlagName -> Bool -> Annex ()
|
||||||
|
storeOptBool name val = Annex.flagChange name $ FlagBool val
|
||||||
|
storeOptString :: FlagName -> String -> Annex ()
|
||||||
|
storeOptString name val = Annex.flagChange name $ FlagString val
|
||||||
|
|
||||||
|
commonOptions :: [Option]
|
||||||
|
commonOptions = [
|
||||||
|
Option ['f'] ["force"] (NoArg (storeOptBool "force" True))
|
||||||
|
"allow actions that may lose annexed data"
|
||||||
|
, Option ['q'] ["quiet"] (NoArg (storeOptBool "quiet" True))
|
||||||
|
"avoid verbose output"
|
||||||
|
, Option ['v'] ["verbose"] (NoArg (storeOptBool "quiet" False))
|
||||||
|
"allow verbose output"
|
||||||
|
, Option ['b'] ["backend"] (ReqArg (storeOptString "backend") paramName)
|
||||||
|
"specify default key-value backend to use"
|
||||||
|
, Option ['k'] ["key"] (ReqArg (storeOptString "key") paramKey)
|
||||||
|
"specify a key to use"
|
||||||
|
, Option ['t'] ["to"] (ReqArg (storeOptString "torepository") paramRemote)
|
||||||
|
"specify to where to transfer content"
|
||||||
|
, Option ['f'] ["from"] (ReqArg (storeOptString "fromrepository") paramRemote)
|
||||||
|
"specify from where to transfer content"
|
||||||
|
, Option ['x'] ["exclude"] (ReqArg (storeOptString "exclude") paramGlob)
|
||||||
|
"skip files matching the glob pattern"
|
||||||
|
]
|
63
doc/git-annex-shell.mdwn
Normal file
63
doc/git-annex-shell.mdwn
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
git-annex-shell - Restricted login shell for git-annex only SSH access
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
git-annex-shell -c command [params ...]
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
git-annex-shell is a restricted shell, similar to git-shell, which
|
||||||
|
can be used as a login shell for SSH accounts you want to restrict.
|
||||||
|
|
||||||
|
# COMMANDS
|
||||||
|
|
||||||
|
* git-annex fromkey file
|
||||||
|
|
||||||
|
This can be used to maually set up a file to link to a specified key
|
||||||
|
in the key-value backend. How you determine an existing key in the backend
|
||||||
|
varies. For the URL backend, the key is just a URL to the content.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
git annex fromkey --backend=URL --key=http://www.archive.org/somefile somefile
|
||||||
|
|
||||||
|
* git-annex dropkey [key ...]
|
||||||
|
|
||||||
|
This drops the annexed data for the specified
|
||||||
|
keys from this repository.
|
||||||
|
|
||||||
|
This can be used to drop content for arbitrary keys, which do not need
|
||||||
|
to have a file in the git repository pointing at them.
|
||||||
|
|
||||||
|
A backend will typically need to be specified with --backend. If none
|
||||||
|
is specified, the first configured backend is used.
|
||||||
|
|
||||||
|
* git-annex setkey file
|
||||||
|
|
||||||
|
This sets the annxed data for a key to the content of
|
||||||
|
the specified file, and then removes the file.
|
||||||
|
|
||||||
|
A backend will typically need to be specified with --backend. If none
|
||||||
|
is specified, the first configured backend is used.
|
||||||
|
|
||||||
|
Any other command is passed through to git-shell.
|
||||||
|
|
||||||
|
# OPTIONS
|
||||||
|
|
||||||
|
Same as git-annex or git-shell, depending on the command being run.
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
|
||||||
|
[[git-annex]](1)
|
||||||
|
|
||||||
|
git-shell(1)
|
||||||
|
|
||||||
|
# AUTHOR
|
||||||
|
|
||||||
|
Joey Hess <joey@kitenet.net>
|
||||||
|
|
||||||
|
<http://git-annex.branchable.com/>
|
||||||
|
|
||||||
|
Warning: this page is automatically made into a man page via [mdwn2man](http://git.ikiwiki.info/?p=ikiwiki;a=blob;f=mdwn2man;hb=HEAD). Edit with care
|
|
@ -4,7 +4,7 @@ git-annex - manage files with git, without checking their contents in
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
git annex subcommand [params ...]
|
git annex command [params ...]
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ content from the key-value store.
|
||||||
# git annex move iso --to=usbdrive
|
# git annex move iso --to=usbdrive
|
||||||
move iso/Debian_5.0.iso (moving to usbdrive...) ok
|
move iso/Debian_5.0.iso (moving to usbdrive...) ok
|
||||||
|
|
||||||
# SUBCOMMANDS
|
# COMMANDS
|
||||||
|
|
||||||
Like many git commands, git-annex can be passed a path that
|
Like many git commands, git-annex can be passed a path that
|
||||||
is either a file or a directory. In the latter case it acts on all relevant
|
is either a file or a directory. In the latter case it acts on all relevant
|
||||||
files in the directory.
|
files in the directory.
|
||||||
|
|
||||||
Many git-annex subcommands will stage changes for later `git commit` by you.
|
Many git-annex commands will stage changes for later `git commit` by you.
|
||||||
|
|
||||||
* add [path ...]
|
* add [path ...]
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
|
||||||
|
|
||||||
* edit [path ...]
|
* edit [path ...]
|
||||||
|
|
||||||
This is an alias for the unlock subcommand. May be easier to remember,
|
This is an alias for the unlock command. May be easier to remember,
|
||||||
if you think of this as allowing you to edit an annexed file.
|
if you think of this as allowing you to edit an annexed file.
|
||||||
|
|
||||||
* move [path ...]
|
* move [path ...]
|
||||||
|
@ -122,7 +122,7 @@ Many git-annex subcommands will stage changes for later `git commit` by you.
|
||||||
|
|
||||||
* fsck [path ...]
|
* fsck [path ...]
|
||||||
|
|
||||||
With no parameters, this subcommand checks the whole annex for consistency,
|
With no parameters, this command checks the whole annex for consistency,
|
||||||
and warns about any problems found.
|
and warns about any problems found.
|
||||||
|
|
||||||
With parameters, only the specified files are checked.
|
With parameters, only the specified files are checked.
|
||||||
|
|
52
git-annex-shell.hs
Normal file
52
git-annex-shell.hs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{- git-annex-shell main program
|
||||||
|
-
|
||||||
|
- Copyright 2010 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
import System.Console.GetOpt
|
||||||
|
import System.Environment
|
||||||
|
import Control.Monad (when)
|
||||||
|
|
||||||
|
import CmdLine
|
||||||
|
import Command
|
||||||
|
import Utility
|
||||||
|
import Options
|
||||||
|
|
||||||
|
import qualified Command.FromKey
|
||||||
|
import qualified Command.DropKey
|
||||||
|
import qualified Command.SetKey
|
||||||
|
|
||||||
|
cmds :: [Command]
|
||||||
|
cmds = concat
|
||||||
|
[ Command.FromKey.command
|
||||||
|
, Command.DropKey.command
|
||||||
|
, Command.SetKey.command
|
||||||
|
]
|
||||||
|
|
||||||
|
options :: [Option]
|
||||||
|
options = [ Option ['c'] ["command"] (NoArg (storeOptBool "command" True))
|
||||||
|
"ignored for compatability with git-shell"
|
||||||
|
] ++ commonOptions
|
||||||
|
|
||||||
|
header :: String
|
||||||
|
header = "Usage:\n" ++
|
||||||
|
"\tgit-annex-shell -c git-annex command [option ..]\n" ++
|
||||||
|
"\tgit-annex-shell -c shellcommand argument"
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
args <- getArgs
|
||||||
|
-- dispatch git-annex commands to builtin versions,
|
||||||
|
-- and pass everything else to git-shell
|
||||||
|
case args of
|
||||||
|
("git-annex":as) -> builtin as
|
||||||
|
[] -> builtin []
|
||||||
|
_ -> external args
|
||||||
|
where
|
||||||
|
builtin l = dispatch l cmds options header
|
||||||
|
external l = do
|
||||||
|
ret <- boolSystem "git-shell" l
|
||||||
|
when (not ret) $
|
||||||
|
error "git-shell failed"
|
27
git-annex.hs
27
git-annex.hs
|
@ -5,10 +5,11 @@
|
||||||
- Licensed under the GNU GPL version 3 or higher.
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import System.Console.GetOpt
|
import System.Environment
|
||||||
|
|
||||||
import CmdLine
|
import CmdLine
|
||||||
import Command
|
import Command
|
||||||
|
import Options
|
||||||
|
|
||||||
import qualified Command.Add
|
import qualified Command.Add
|
||||||
import qualified Command.Unannex
|
import qualified Command.Unannex
|
||||||
|
@ -57,25 +58,7 @@ cmds = concat
|
||||||
, Command.Find.command
|
, Command.Find.command
|
||||||
]
|
]
|
||||||
|
|
||||||
options :: [Option]
|
|
||||||
options = [
|
|
||||||
Option ['f'] ["force"] (NoArg (storeOptBool "force" True))
|
|
||||||
"allow actions that may lose annexed data"
|
|
||||||
, Option ['q'] ["quiet"] (NoArg (storeOptBool "quiet" True))
|
|
||||||
"avoid verbose output"
|
|
||||||
, Option ['v'] ["verbose"] (NoArg (storeOptBool "quiet" False))
|
|
||||||
"allow verbose output"
|
|
||||||
, Option ['b'] ["backend"] (ReqArg (storeOptString "backend") paramName)
|
|
||||||
"specify default key-value backend to use"
|
|
||||||
, Option ['k'] ["key"] (ReqArg (storeOptString "key") paramKey)
|
|
||||||
"specify a key to use"
|
|
||||||
, Option ['t'] ["to"] (ReqArg (storeOptString "torepository") paramRemote)
|
|
||||||
"specify to where to transfer content"
|
|
||||||
, Option ['f'] ["from"] (ReqArg (storeOptString "fromrepository") paramRemote)
|
|
||||||
"specify from where to transfer content"
|
|
||||||
, Option ['x'] ["exclude"] (ReqArg (storeOptString "exclude") paramGlob)
|
|
||||||
"skip files matching the glob pattern"
|
|
||||||
]
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = cmdLine cmds options "Usage: git-annex subcommand [option ..]"
|
main = do
|
||||||
|
args <- getArgs
|
||||||
|
dispatch args cmds commonOptions "Usage: git-annex command [option ..]"
|
||||||
|
|
Loading…
Reference in a new issue