diff options
author | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
commit | 8982e501c77217c860f79bba431f46a62b607a21 (patch) | |
tree | 70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/src/watch.c | |
parent | 01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff) | |
download | FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.zip FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.tar.gz |
Import of slightly trimmed cvs-1.8 distribution. Generated files
and non-unix code has been left out.
Diffstat (limited to 'contrib/cvs/src/watch.c')
-rw-r--r-- | contrib/cvs/src/watch.c | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/contrib/cvs/src/watch.c b/contrib/cvs/src/watch.c new file mode 100644 index 0000000..0873489 --- /dev/null +++ b/contrib/cvs/src/watch.c @@ -0,0 +1,521 @@ +/* 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "cvs.h" +#include "edit.h" +#include "fileattr.h" +#include "watch.h" + +const char *const watch_usage[] = +{ + "Usage: %s %s [on|off|add|remove] [-l] [-a action] [files...]\n", + "on/off: turn on/off read-only checkouts of files\n", + "add/remove: add or remove notification on actions\n", + "-l (on/off/add/remove): Local directory only, not recursive\n", + "-a (add/remove): Specify what actions, one of\n", + " edit,unedit,commit,all,none\n", + NULL +}; + +static struct addremove_args the_args; + +void +watch_modify_watchers (file, what) + char *file; + struct addremove_args *what; +{ + char *curattr = fileattr_get0 (file, "_watchers"); + char *p; + char *pend; + char *nextp; + char *who; + int who_len; + char *mycurattr; + char *mynewattr; + size_t mynewattr_size; + + int add_edit_pending; + int add_unedit_pending; + int add_commit_pending; + int remove_edit_pending; + int remove_unedit_pending; + int remove_commit_pending; + int add_tedit_pending; + int add_tunedit_pending; + int add_tcommit_pending; + + who = getcaller (); + who_len = strlen (who); + + /* Look for current watcher types for this user. */ + mycurattr = NULL; + if (curattr != NULL) + { + p = curattr; + while (1) { + if (strncmp (who, p, who_len) == 0 + && p[who_len] == '>') + { + /* Found this user. */ + mycurattr = p + who_len + 1; + } + p = strchr (p, ','); + if (p == NULL) + break; + ++p; + } + } + if (mycurattr != NULL) + { + mycurattr = xstrdup (mycurattr); + p = strchr (mycurattr, ','); + if (p != NULL) + *p = '\0'; + } + + /* Now copy mycurattr to mynewattr, making the requisite modifications. + Note that we add a dummy '+' to the start of mynewattr, to reduce + special cases (but then we strip it off when we are done). */ + + mynewattr_size = sizeof "+edit+unedit+commit+tedit+tunedit+tcommit"; + if (mycurattr != NULL) + mynewattr_size += strlen (mycurattr); + mynewattr = xmalloc (mynewattr_size); + mynewattr[0] = '\0'; + + add_edit_pending = what->adding && what->edit; + add_unedit_pending = what->adding && what->unedit; + add_commit_pending = what->adding && what->commit; + remove_edit_pending = !what->adding && what->edit; + remove_unedit_pending = !what->adding && what->unedit; + remove_commit_pending = !what->adding && what->commit; + add_tedit_pending = what->add_tedit; + add_tunedit_pending = what->add_tunedit; + add_tcommit_pending = what->add_tcommit; + + /* Copy over existing watch types, except those to be removed. */ + p = mycurattr; + while (p != NULL) + { + pend = strchr (p, '+'); + if (pend == NULL) + { + pend = p + strlen (p); + nextp = NULL; + } + else + nextp = pend + 1; + + /* Process this item. */ + if (pend - p == 4 && strncmp ("edit", p, 4) == 0) + { + if (!remove_edit_pending) + strcat (mynewattr, "+edit"); + add_edit_pending = 0; + } + else if (pend - p == 6 && strncmp ("unedit", p, 6) == 0) + { + if (!remove_unedit_pending) + strcat (mynewattr, "+unedit"); + add_unedit_pending = 0; + } + else if (pend - p == 6 && strncmp ("commit", p, 6) == 0) + { + if (!remove_commit_pending) + strcat (mynewattr, "+commit"); + add_commit_pending = 0; + } + else if (pend - p == 5 && strncmp ("tedit", p, 5) == 0) + { + if (!what->remove_temp) + strcat (mynewattr, "+tedit"); + add_tedit_pending = 0; + } + else if (pend - p == 7 && strncmp ("tunedit", p, 7) == 0) + { + if (!what->remove_temp) + strcat (mynewattr, "+tunedit"); + add_tunedit_pending = 0; + } + else if (pend - p == 7 && strncmp ("tcommit", p, 7) == 0) + { + if (!what->remove_temp) + strcat (mynewattr, "+tcommit"); + add_tcommit_pending = 0; + } + else + { + char *mp; + + /* Copy over any unrecognized watch types, for future + expansion. */ + mp = mynewattr + strlen (mynewattr); + *mp++ = '+'; + strncpy (mp, p, pend - p); + *(mp + (pend - p)) = '\0'; + } + + /* Set up for next item. */ + p = nextp; + } + + /* Add in new watch types. */ + if (add_edit_pending) + strcat (mynewattr, "+edit"); + if (add_unedit_pending) + strcat (mynewattr, "+unedit"); + if (add_commit_pending) + strcat (mynewattr, "+commit"); + if (add_tedit_pending) + strcat (mynewattr, "+tedit"); + if (add_tunedit_pending) + strcat (mynewattr, "+tunedit"); + if (add_tcommit_pending) + strcat (mynewattr, "+tcommit"); + + { + char *curattr_new; + + curattr_new = + fileattr_modify (curattr, + who, + mynewattr[0] == '\0' ? NULL : mynewattr + 1, + '>', + ','); + /* If the attribute is unchanged, don't rewrite the attribute file. */ + if (!((curattr_new == NULL && curattr == NULL) + || (curattr_new != NULL + && curattr != NULL + && strcmp (curattr_new, curattr) == 0))) + fileattr_set (file, + "_watchers", + curattr_new); + if (curattr_new != NULL) + free (curattr_new); + } + + if (curattr != NULL) + free (curattr); + if (mycurattr != NULL) + free (mycurattr); + if (mynewattr != NULL) + free (mynewattr); +} + +static int addremove_fileproc PROTO ((struct file_info *finfo)); + +static int +addremove_fileproc (finfo) + struct file_info *finfo; +{ + watch_modify_watchers (finfo->file, &the_args); + return 0; +} + +static int addremove_filesdoneproc PROTO ((int, char *, char *)); + +static int +addremove_filesdoneproc (err, repository, update_dir) + int err; + char *repository; + char *update_dir; +{ + if (the_args.setting_default) + watch_modify_watchers (NULL, &the_args); + return err; +} + +static int watch_addremove PROTO ((int argc, char **argv)); + +static int +watch_addremove (argc, argv) + 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 = 1; + while ((c = getopt (argc, argv, "la:")) != -1) + { + switch (c) + { + case 'l': + local = 1; + 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; + } + +#ifdef CLIENT_SUPPORT + if (client_active) + { + start_server (); + ign_setup (); + + 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_file_names (argc, argv, SEND_EXPAND_WILD); + /* FIXME: We shouldn't have to send current files, but I'm not sure + whether it works. So send the files -- + it's slower but it works. */ + send_files (argc, argv, local, 0); + send_to_server (the_args.adding ? + "watch-add\012" : "watch-remove\012", + 0); + return get_responses_and_close (); + } +#endif /* CLIENT_SUPPORT */ + + the_args.setting_default = (argc <= 0); + + lock_tree_for_write (argc, argv, local, 0); + + err = start_recursion (addremove_fileproc, addremove_filesdoneproc, + (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, + argc, argv, local, W_LOCAL, 0, 0, (char *)NULL, + 1, 0); + + lock_tree_cleanup (); + return err; +} + +int +watch_add (argc, argv) + int argc; + char **argv; +{ + the_args.adding = 1; + return watch_addremove (argc, argv); +} + +int +watch_remove (argc, argv) + int argc; + char **argv; +{ + the_args.adding = 0; + return watch_addremove (argc, argv); +} + +int +watch (argc, argv) + int argc; + char **argv; +{ + if (argc <= 1) + usage (watch_usage); + if (strcmp (argv[1], "on") == 0) + { + --argc; + ++argv; + return watch_on (argc, argv); + } + else if (strcmp (argv[1], "off") == 0) + { + --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 [files...]\n", + NULL +}; + +static int watchers_fileproc PROTO ((struct file_info *finfo)); + +static int +watchers_fileproc (finfo) + struct file_info *finfo; +{ + char *them; + char *p; + + them = fileattr_get0 (finfo->file, "_watchers"); + if (them == NULL) + return 0; + + fputs (finfo->fullname, stdout); + + p = them; + while (1) + { + putc ('\t', stdout); + while (*p != '>' && *p != '\0') + putc (*p++, stdout); + if (*p == '\0') + { + /* Only happens if attribute is misformed. */ + putc ('\n', stdout); + break; + } + ++p; + putc ('\t', stdout); + while (1) + { + while (*p != '+' && *p != ',' && *p != '\0') + putc (*p++, stdout); + if (*p == '\0') + { + putc ('\n', stdout); + goto out; + } + if (*p == ',') + { + ++p; + break; + } + ++p; + putc ('\t', stdout); + } + putc ('\n', stdout); + } + out:; + return 0; +} + +int +watchers (argc, argv) + int argc; + char **argv; +{ + int local = 0; + int c; + + if (argc == -1) + usage (watchers_usage); + + optind = 1; + while ((c = getopt (argc, argv, "l")) != -1) + { + switch (c) + { + case 'l': + local = 1; + break; + case '?': + default: + usage (watchers_usage); + break; + } + } + argc -= optind; + argv += optind; + +#ifdef CLIENT_SUPPORT + if (client_active) + { + start_server (); + ign_setup (); + + if (local) + send_arg ("-l"); + send_file_names (argc, argv, SEND_EXPAND_WILD); + /* FIXME: We shouldn't have to send current files, but I'm not sure + whether it works. So send the files -- + it's slower but it works. */ + send_files (argc, argv, local, 0); + send_to_server ("watchers\012", 0); + return get_responses_and_close (); + } +#endif /* CLIENT_SUPPORT */ + + return start_recursion (watchers_fileproc, (FILESDONEPROC) NULL, + (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, + argc, argv, local, W_LOCAL, 0, 1, (char *)NULL, + 1, 0); +} |