/* Implementation for "cvs watch add", "cvs watchers", and related commands
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. */
#include "cvs.h"
#include "edit.h"
#include "fileattr.h"
#include "watch.h"
const char *const watch_usage[] =
{
"Usage: %s %s [on|off|ro|rw|add|remove] [-lR] [-a action] [files...]\n",
"on/off/readonly/readwrite: turn on/off read-only checkouts of files\n",
"add/remove: add or remove notification on actions\n",
"-l (on/off/ro/rw/add/remove): Local directory only, not recursive\n",
"-R (on/off/ro/rw/add/remove): Process directories recursively\n",
"-a (add/remove): Specify what actions, one of\n",
" edit,unedit,commit,all,none\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
static struct addremove_args the_args;
void watch_modify_watchers (const char *file, const char *who, struct addremove_args *what)
{
XmlHandle_t filehandle;
TRACE(3,"watch_modify_watchers(%s,%s)",PATCH_NULL(file),PATCH_NULL(who));
if(file)
filehandle = fileattr_find(NULL,"file[@name=F'%s']/watcher[@name=U'%s']",file,who);
else
filehandle = fileattr_find(NULL,"directory/default/watcher[@name=U'%s']",who);
if(!filehandle && !what->adding)
return;
if(!filehandle)
{
if(file)
filehandle= fileattr_create(NULL,"file[@name=F'%s']/watcher[@name=U'%s']",file,who);
else
filehandle= fileattr_create(NULL,"directory/default/watcher[@name=U'%s']",who);
}
if(!filehandle)
error(0,0,"Couldn't create node in modify_watchers");
if(!what->adding)
{
if(what->edit)
fileattr_delete(filehandle,"edit");
if(what->commit)
fileattr_delete(filehandle,"commit");
if(what->unedit)
fileattr_delete(filehandle,"unedit");
if(what->remove_temp)
{
fileattr_delete(filehandle,"temp_edit");
fileattr_delete(filehandle,"temp_commit");
fileattr_delete(filehandle,"temp_unedit");
}
fileattr_prune(filehandle);
}
else
{
if(what->edit)
fileattr_create(filehandle,"edit");
if(what->commit)
fileattr_create(filehandle,"commit");
if(what->unedit)
fileattr_create(filehandle,"unedit");
if(what->add_tedit)
fileattr_create(filehandle,"temp_edit");
if(what->add_tcommit)
fileattr_create(filehandle,"temp_commit");
if(what->add_tunedit)
fileattr_create(filehandle,"temp_unedit");
}
}
static int addremove_fileproc(void *callerdat,
struct file_info *finfo)
{
watch_modify_watchers (finfo->file, CVS_Username, &the_args);
return 0;
}
static int addremove_filesdoneproc (void *callerdat, int err, char *repository,
char *update_dir, List *entries)
{
if (the_args.setting_default)
watch_modify_watchers (NULL, CVS_Username, &the_args);
return err;
}
static int watch_addremove(int argc, char **argv)
{
int c;
int local = 0;
int err;
int a_omitted;
a_omitted = 1;
the_args.commit = 0;
the_args.edit = 0;
the_args.unedit = 0;
optind = 0;
while ((c = getopt (argc, argv, "+lRa:")) != -1)
{
switch (c)
{
case 'l':
local = 1;
break;
case 'R':
local = 0;
break;
case 'a':
a_omitted = 0;
if (strcmp (optarg, "edit") == 0)
the_args.edit = 1;
else if (strcmp (optarg, "unedit") == 0)
the_args.unedit = 1;
else if (strcmp (optarg, "commit") == 0)
the_args.commit = 1;
else if (strcmp (optarg, "all") == 0)
{
the_args.edit = 1;
the_args.unedit = 1;
the_args.commit = 1;
}
else if (strcmp (optarg, "none") == 0)
{
the_args.edit = 0;
the_args.unedit = 0;
the_args.commit = 0;
}
else
usage (watch_usage);
break;
case '?':
default:
usage (watch_usage);
break;
}
}
argc -= optind;
argv += optind;
if (a_omitted)
{
the_args.edit = 1;
the_args.unedit = 1;
the_args.commit = 1;
}
if (current_parsed_root->isremote)
{
if (local)
send_arg ("-l");
/* FIXME: copes poorly with "all" if server is extended to have
new watch types and client is still running an old version. */
if (the_args.edit)
{
send_arg ("-a");
send_arg ("edit");
}
if (the_args.unedit)
{
send_arg ("-a");
send_arg ("unedit");
}
if (the_args.commit)
{
send_arg ("-a");
send_arg ("commit");
}
if (!the_args.edit && !the_args.unedit && !the_args.commit)
{
send_arg ("-a");
send_arg ("none");
}
send_arg("--");
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server (the_args.adding ?
"watch-add\n" : "watch-remove\n",
0);
return get_responses_and_close ();
}
the_args.setting_default = (argc <= 0);
lock_tree_for_write (argc, argv, local, W_LOCAL, 0);
err = start_recursion (addremove_fileproc, addremove_filesdoneproc,
(PREDIRENTPROC) NULL, (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
argc, argv, local, W_LOCAL, 0, 0, (char *)NULL, NULL,
1, verify_write);
Lock_Cleanup ();
return err;
}
int watch_add(int argc, char **argv)
{
the_args.adding = 1;
return watch_addremove (argc, argv);
}
int watch_remove (int argc, char **argv)
{
the_args.adding = 0;
return watch_addremove (argc, argv);
}
int watch (int argc, char **argv)
{
if (argc <= 1)
usage (watch_usage);
if (!strcmp(argv[1], "on") || !strcmp(argv[1],"ro"))
{
--argc;
++argv;
return watch_on (argc, argv);
}
else if(!strcmp(argv[1], "off") || !strcmp(argv[1],"rw"))
{
--argc;
++argv;
return watch_off (argc, argv);
}
else if (strcmp (argv[1], "add") == 0)
{
--argc;
++argv;
return watch_add (argc, argv);
}
else if (strcmp (argv[1], "remove") == 0)
{
--argc;
++argv;
return watch_remove (argc, argv);
}
else
usage (watch_usage);
return 0;
}
static const char *const watchers_usage[] =
{
"Usage: %s %s [-lR] [files...]\n",
"\t-l\tProcess this directory only (not recursive).\n",
"\t-R\tProcess directories recursively.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
static int watchers_fileproc (void *callerdat, struct file_info *finfo)
{
XmlHandle_t handle;
const char *name;
handle = fileattr_find(NULL,"file[@name=F'%s']/watcher",finfo->file);
if(!handle)
return 0;
cvs_output (fn_root(finfo->fullname), 0);
while (handle)
{
cvs_output ("\t", 1);
name=fileattr_getvalue(handle,"@name");
cvs_output(name,0);
if(fileattr_find(handle,"edit"))
cvs_output("\tedit",0);
if(fileattr_find(handle,"unedit"))
cvs_output("\tunedit",0);
if(fileattr_find(handle,"commit"))
cvs_output("\tcommit",0);
if(fileattr_find(handle,"temp_edit"))
cvs_output("\ttedit",0);
if(fileattr_find(handle,"temp_unedit"))
cvs_output("\ttunedit",0);
if(fileattr_find(handle,"temp_commit"))
cvs_output("\ttcommit",0);
cvs_output ("\n", 1);
handle = fileattr_next(handle);
}
return 0;
}
int watchers (int argc, char **argv)
{
int local = 0;
int c;
if (argc == -1)
usage (watchers_usage);
optind = 0;
while ((c = getopt (argc, argv, "+lR")) != -1)
{
switch (c)
{
case 'l':
local = 1;
break;
case 'R':
local = 0;
break;
case '?':
default:
usage (watchers_usage);
break;
}
}
argc -= optind;
argv += optind;
if (current_parsed_root->isremote)
{
if (local)
send_arg ("-l");
send_arg("--");
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("watchers\n", 0);
return get_responses_and_close ();
}
return start_recursion (watchers_fileproc, (FILESDONEPROC) NULL,
(PREDIRENTPROC) NULL, (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
argc, argv, local, W_LOCAL, 0, 1, (char *)NULL, NULL,
1, verify_write);
}
syntax highlighted by Code2HTML, v. 0.9.1