338 строки
6.4 KiB
Plaintext
Исполняемый файл
338 строки
6.4 KiB
Plaintext
Исполняемый файл
#!/usr/bin/env slsh
|
|
% This is a simple shell that allows one to interact with an SVN repository
|
|
% in a shell-like manner.
|
|
%
|
|
% The location of the repository may be specified either on the
|
|
% command line or via the SVN_REPOS environment variable, e.g.,
|
|
%
|
|
% svnsh $HOME/var/svn/repos
|
|
%
|
|
% Use it at your own risk!
|
|
%
|
|
|
|
private variable SVNSH_VERSION = "0.1.0-1";
|
|
|
|
private variable Repository;
|
|
private variable Repository_CWD;
|
|
private variable Echo_Commands = 0;
|
|
|
|
private variable Rline;
|
|
|
|
new_exception ("SVNError", AnyError, "svn error");
|
|
|
|
private define expand_path (path)
|
|
{
|
|
variable dir = Repository_CWD;
|
|
|
|
if (path[0] == '/')
|
|
dir = Repository;
|
|
|
|
foreach (strtok (path, "/"))
|
|
{
|
|
variable sdir = ();
|
|
if (sdir == "..")
|
|
{
|
|
if (dir == Repository)
|
|
{
|
|
vmessage ("Can't go up");
|
|
return NULL;
|
|
}
|
|
dir = path_dirname (dir);
|
|
continue;
|
|
}
|
|
if (sdir == ".")
|
|
continue;
|
|
|
|
dir = strcat (dir, "/", sdir);
|
|
}
|
|
return dir;
|
|
}
|
|
|
|
private define _svn_execute ()
|
|
{
|
|
variable args = __pop_args (_NARGS);
|
|
variable cmd = "svn " + sprintf (__push_args(args));
|
|
if (Echo_Commands)
|
|
() = fprintf (stdout, "%s\n", cmd);
|
|
variable status = system (cmd);
|
|
if (status != 0)
|
|
throw SVNError, sprintf ("%s returned %d", cmd, status);
|
|
}
|
|
|
|
private define _svn_path_exists (path)
|
|
{
|
|
if (path == NULL)
|
|
return 0;
|
|
try
|
|
{
|
|
_svn_execute ("ls %s >/dev/null 2>&1", path);
|
|
}
|
|
catch SVNError: return 0;
|
|
return 1;
|
|
}
|
|
|
|
private define _svn_cd (argv)
|
|
{
|
|
variable dir = expand_path (argv[0]);
|
|
if (0 == _svn_path_exists (dir))
|
|
{
|
|
vmessage ("%s does not exist", dir);
|
|
return;
|
|
}
|
|
Repository_CWD = dir;
|
|
}
|
|
|
|
private define get_opts (argv)
|
|
{
|
|
variable i;
|
|
variable opts = "";
|
|
variable args = String_Type[0];
|
|
variable n = length (argv);
|
|
i = 0;
|
|
while (i < n)
|
|
{
|
|
variable arg = argv[i];
|
|
if (arg[0] == '-')
|
|
{
|
|
if (arg == "-nc")
|
|
{
|
|
arg = "-m \"\"";
|
|
}
|
|
opts = strcat (opts, " ", arg);
|
|
i++;
|
|
continue;
|
|
}
|
|
args = argv[[i:]];
|
|
break;
|
|
}
|
|
|
|
return opts, args;
|
|
}
|
|
|
|
private define _svn_cp (argv)
|
|
{
|
|
variable opts, files;
|
|
|
|
(opts, files) = get_opts (argv);
|
|
if (length (files) != 2)
|
|
{
|
|
() = fprintf (stderr, "Usage: cp dir dir\n");
|
|
return;
|
|
}
|
|
variable from = expand_path (files[0]);
|
|
variable to = expand_path (files[1]);
|
|
if ((from == NULL) or (to == NULL))
|
|
return;
|
|
_svn_execute ("cp %s %s %s", opts, from, to);
|
|
}
|
|
|
|
private define _svn_ls (argv)
|
|
{
|
|
variable opts, files;
|
|
(opts, files) = get_opts (argv);
|
|
|
|
if (opts == "-l")
|
|
opts = "-v";
|
|
|
|
if (length (files) == 0)
|
|
{
|
|
_svn_execute ("ls %s %s", opts, Repository_CWD);
|
|
return;
|
|
}
|
|
|
|
foreach (files)
|
|
{
|
|
variable file = ();
|
|
file = expand_path (file);
|
|
if (file == NULL)
|
|
continue;
|
|
|
|
_svn_execute ("ls %s %s", opts, file);
|
|
}
|
|
}
|
|
|
|
private define _svn_mv (argv)
|
|
{
|
|
variable opts, files;
|
|
(opts, files) = get_opts (argv);
|
|
|
|
if (length (files) != 2)
|
|
{
|
|
() = fprintf (stderr, "Usage: mv FROM TO\n");
|
|
return;
|
|
}
|
|
|
|
variable from = expand_path (files[0]);
|
|
variable to = expand_path (files[1]);
|
|
|
|
if ((from == NULL) or (to == NULL))
|
|
{
|
|
() = fprintf (stderr, "*** mv failed\n");
|
|
return;
|
|
}
|
|
|
|
_svn_execute ("mv %s %s %s", opts, from, to);
|
|
}
|
|
|
|
private define _svn_mkdir (argv)
|
|
{
|
|
variable opts, files;
|
|
|
|
(opts, files) = get_opts (argv);
|
|
if (length (files) != 1)
|
|
{
|
|
() = fprintf (stderr, "Usage: mkdir DIR\n");
|
|
return;
|
|
}
|
|
variable dir = expand_path (files[0]);
|
|
if (dir == NULL)
|
|
return;
|
|
_svn_execute ("mkdir %s %s", opts, dir);
|
|
}
|
|
|
|
private define _svn_rm (argv)
|
|
{
|
|
variable opts, files;
|
|
|
|
(opts, files) = get_opts (argv);
|
|
if (length (files) != 1)
|
|
{
|
|
() = fprintf (stderr, "Usage: rm file\n");
|
|
return;
|
|
}
|
|
variable dir = expand_path (files[0]);
|
|
if (dir == NULL)
|
|
return;
|
|
_svn_execute ("rm %s %s", opts, dir);
|
|
}
|
|
|
|
private define _svn_most (argv)
|
|
{
|
|
if (length (argv) != 1)
|
|
{
|
|
() = fprintf (stderr, "Usage: most FILE\n");
|
|
return;
|
|
}
|
|
variable file = expand_path (argv[0]);
|
|
if (file == NULL)
|
|
return;
|
|
_svn_execute ("cat %s | most", file);
|
|
}
|
|
|
|
private define _svn_help (argv)
|
|
{
|
|
_svn_execute ("help %s", strjoin (argv, " "));
|
|
() = fprintf (stdout, "\nAlso use ? for a list of interractive commands\n");
|
|
}
|
|
|
|
private define _svn_quit (argv)
|
|
{
|
|
Rline = NULL;
|
|
exit (0);
|
|
}
|
|
|
|
private variable Cmd_Table = Assoc_Type [Ref_Type];
|
|
private define _svn_local_help (argv)
|
|
{
|
|
() = fprintf (stdout, "Local commands:\n");
|
|
foreach (assoc_get_keys (Cmd_Table))
|
|
{
|
|
variable key = ();
|
|
() = fprintf (stdout, "%s\n", key);
|
|
}
|
|
}
|
|
|
|
Cmd_Table["ls"] = &_svn_ls;
|
|
Cmd_Table["cd"] = &_svn_cd;
|
|
Cmd_Table["cp"] = &_svn_cp;
|
|
Cmd_Table["help"] = &_svn_help;
|
|
Cmd_Table["mv"] = &_svn_mv;
|
|
Cmd_Table["mkdir"] = &_svn_mkdir;
|
|
Cmd_Table["rmdir"] = &_svn_rm;
|
|
Cmd_Table["rm"] = &_svn_rm;
|
|
Cmd_Table["most"] = &_svn_most;
|
|
Cmd_Table["quit"] = &_svn_quit;
|
|
Cmd_Table["?"] = &_svn_local_help;
|
|
|
|
private define take_input ()
|
|
{
|
|
variable line;
|
|
forever
|
|
{
|
|
try
|
|
{
|
|
line = slsh_readline (Rline, sprintf ("%s> ", Repository_CWD));
|
|
}
|
|
catch UserBreakError: continue;
|
|
if (line == NULL)
|
|
break;
|
|
|
|
variable argv = strtok (line, " \t;\n");
|
|
if (length (argv) == 0)
|
|
continue;
|
|
|
|
variable cmd = argv[0];
|
|
if (length (argv) == 1)
|
|
argv = String_Type[0];
|
|
else
|
|
argv = argv[[1:]];
|
|
|
|
variable e;
|
|
|
|
try (e)
|
|
{
|
|
if (0 == assoc_key_exists (Cmd_Table, cmd))
|
|
{
|
|
() = fprintf (stderr, "%s not supported\n", cmd);
|
|
continue;
|
|
}
|
|
(@Cmd_Table[cmd])(argv);
|
|
}
|
|
catch AnyError:
|
|
{
|
|
() = fprintf (stderr, "%S:%d:%s *** Caught exception: %S\n",
|
|
e.file, e.line, e.descr, e.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
public define svn_set_repository (repos)
|
|
{
|
|
!if (_svn_path_exists (repos))
|
|
{
|
|
() = fprintf (stderr, "*** Repository %s does not exist\n", repos);
|
|
exit (1);
|
|
}
|
|
Repository = repos;
|
|
Repository_CWD = repos;
|
|
}
|
|
|
|
public define slsh_main ()
|
|
{
|
|
variable repos;
|
|
if (__argc == 2)
|
|
repos = __argv[1];
|
|
else
|
|
{
|
|
repos = getenv ("SVN_REPOS");
|
|
if (repos == NULL)
|
|
{
|
|
() = fprintf (stderr, "Usage: %s [file://]repository\n", __argv[0]);
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
() = fprintf (stdout, "svnsh version %s.\nUse this at your own risk!\n", SVNSH_VERSION);
|
|
() = fprintf (stdout, "Enter ? for a list of commands.\n");
|
|
|
|
!if (is_substr (repos, "://"))
|
|
repos = strcat ("file://", repos);
|
|
|
|
svn_set_repository (repos);
|
|
|
|
slsh_readline_init ("SVNSH");
|
|
Rline = slsh_readline_new ("svnsh");
|
|
|
|
take_input ();
|
|
}
|