1 /* Implementation for "cvs watch add", "cvs watchers", and related commands
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details. */
18 const char *const watch_usage[] =
20 "Usage: %s %s {on|off|add|remove} [-lR] [-a <action>]... [<path>]...\n",
21 "on/off: turn on/off read-only checkouts of files\n",
22 "add/remove: add or remove notification on actions\n",
23 "-l (on/off/add/remove): Local directory only, not recursive\n",
24 "-R (on/off/add/remove): Process directories recursively (default)\n",
25 "-a (add/remove): Specify what actions, one of\n",
26 " edit,unedit,commit,all,none (defaults to all, multiple -a\n",
27 " options are permitted)\n",
28 "(Specify the --help global option for a list of other help options)\n",
32 static struct addremove_args the_args;
35 watch_modify_watchers (const char *file, struct addremove_args *what)
37 char *curattr = fileattr_get0 (file, "_watchers");
45 size_t mynewattr_size;
48 int add_unedit_pending;
49 int add_commit_pending;
50 int remove_edit_pending;
51 int remove_unedit_pending;
52 int remove_commit_pending;
53 int add_tedit_pending;
54 int add_tunedit_pending;
55 int add_tcommit_pending;
58 who_len = strlen (who);
60 /* Look for current watcher types for this user. */
66 if (strncmp (who, p, who_len) == 0
69 /* Found this user. */
70 mycurattr = p + who_len + 1;
78 if (mycurattr != NULL)
80 mycurattr = xstrdup (mycurattr);
81 p = strchr (mycurattr, ',');
86 /* Now copy mycurattr to mynewattr, making the requisite modifications.
87 Note that we add a dummy '+' to the start of mynewattr, to reduce
88 special cases (but then we strip it off when we are done). */
90 mynewattr_size = sizeof "+edit+unedit+commit+tedit+tunedit+tcommit";
91 if (mycurattr != NULL)
92 mynewattr_size += strlen (mycurattr);
93 mynewattr = xmalloc (mynewattr_size);
96 add_edit_pending = what->adding && what->edit;
97 add_unedit_pending = what->adding && what->unedit;
98 add_commit_pending = what->adding && what->commit;
99 remove_edit_pending = !what->adding && what->edit;
100 remove_unedit_pending = !what->adding && what->unedit;
101 remove_commit_pending = !what->adding && what->commit;
102 add_tedit_pending = what->add_tedit;
103 add_tunedit_pending = what->add_tunedit;
104 add_tcommit_pending = what->add_tcommit;
106 /* Copy over existing watch types, except those to be removed. */
110 pend = strchr (p, '+');
113 pend = p + strlen (p);
119 /* Process this item. */
120 if (pend - p == 4 && strncmp ("edit", p, 4) == 0)
122 if (!remove_edit_pending)
123 strcat (mynewattr, "+edit");
124 add_edit_pending = 0;
126 else if (pend - p == 6 && strncmp ("unedit", p, 6) == 0)
128 if (!remove_unedit_pending)
129 strcat (mynewattr, "+unedit");
130 add_unedit_pending = 0;
132 else if (pend - p == 6 && strncmp ("commit", p, 6) == 0)
134 if (!remove_commit_pending)
135 strcat (mynewattr, "+commit");
136 add_commit_pending = 0;
138 else if (pend - p == 5 && strncmp ("tedit", p, 5) == 0)
140 if (!what->remove_temp)
141 strcat (mynewattr, "+tedit");
142 add_tedit_pending = 0;
144 else if (pend - p == 7 && strncmp ("tunedit", p, 7) == 0)
146 if (!what->remove_temp)
147 strcat (mynewattr, "+tunedit");
148 add_tunedit_pending = 0;
150 else if (pend - p == 7 && strncmp ("tcommit", p, 7) == 0)
152 if (!what->remove_temp)
153 strcat (mynewattr, "+tcommit");
154 add_tcommit_pending = 0;
160 /* Copy over any unrecognized watch types, for future
162 mp = mynewattr + strlen (mynewattr);
164 strncpy (mp, p, pend - p);
165 *(mp + (pend - p)) = '\0';
168 /* Set up for next item. */
172 /* Add in new watch types. */
173 if (add_edit_pending)
174 strcat (mynewattr, "+edit");
175 if (add_unedit_pending)
176 strcat (mynewattr, "+unedit");
177 if (add_commit_pending)
178 strcat (mynewattr, "+commit");
179 if (add_tedit_pending)
180 strcat (mynewattr, "+tedit");
181 if (add_tunedit_pending)
182 strcat (mynewattr, "+tunedit");
183 if (add_tcommit_pending)
184 strcat (mynewattr, "+tcommit");
190 fileattr_modify (curattr,
192 mynewattr[0] == '\0' ? NULL : mynewattr + 1,
195 /* If the attribute is unchanged, don't rewrite the attribute file. */
196 if (!((curattr_new == NULL && curattr == NULL)
197 || (curattr_new != NULL
199 && strcmp (curattr_new, curattr) == 0)))
203 if (curattr_new != NULL)
209 if (mycurattr != NULL)
211 if (mynewattr != NULL)
215 static int addremove_fileproc (void *callerdat,
216 struct file_info *finfo);
219 addremove_fileproc (void *callerdat, struct file_info *finfo)
221 watch_modify_watchers (finfo->file, &the_args);
228 addremove_filesdoneproc (void *callerdat, int err, const char *repository,
229 const char *update_dir, List *entries)
231 if (the_args.setting_default)
232 watch_modify_watchers (NULL, &the_args);
238 static int watch_addremove (int argc, char **argv);
241 watch_addremove (int argc, char **argv)
253 while ((c = getopt (argc, argv, "+lRa:")) != -1)
265 if (strcmp (optarg, "edit") == 0)
267 else if (strcmp (optarg, "unedit") == 0)
269 else if (strcmp (optarg, "commit") == 0)
271 else if (strcmp (optarg, "all") == 0)
277 else if (strcmp (optarg, "none") == 0)
302 #ifdef CLIENT_SUPPORT
303 if (current_parsed_root->isremote)
310 /* FIXME: copes poorly with "all" if server is extended to have
311 new watch types and client is still running an old version. */
313 option_with_arg ("-a", "edit");
315 option_with_arg ("-a", "unedit");
317 option_with_arg ("-a", "commit");
318 if (!the_args.edit && !the_args.unedit && !the_args.commit)
319 option_with_arg ("-a", "none");
321 send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
322 send_file_names (argc, argv, SEND_EXPAND_WILD);
323 send_to_server (the_args.adding ?
324 "watch-add\012" : "watch-remove\012",
326 return get_responses_and_close ();
328 #endif /* CLIENT_SUPPORT */
330 the_args.setting_default = (argc <= 0);
332 lock_tree_promotably (argc, argv, local, W_LOCAL, 0);
334 err = start_recursion
335 (addremove_fileproc, addremove_filesdoneproc,
337 argc, argv, local, W_LOCAL, 0, CVS_LOCK_WRITE,
345 watch_add (int argc, char **argv)
348 return watch_addremove (argc, argv);
352 watch_remove (int argc, char **argv)
355 return watch_addremove (argc, argv);
359 watch (int argc, char **argv)
363 if (strcmp (argv[1], "on") == 0)
367 return watch_on (argc, argv);
369 else if (strcmp (argv[1], "off") == 0)
373 return watch_off (argc, argv);
375 else if (strcmp (argv[1], "add") == 0)
379 return watch_add (argc, argv);
381 else if (strcmp (argv[1], "remove") == 0)
385 return watch_remove (argc, argv);
392 static const char *const watchers_usage[] =
394 "Usage: %s %s [-lR] [files...]\n",
395 "\t-l\tProcess this directory only (not recursive).\n",
396 "\t-R\tProcess directories recursively.\n",
397 "(Specify the --help global option for a list of other help options)\n",
401 static int watchers_fileproc (void *callerdat,
402 struct file_info *finfo);
405 watchers_fileproc (void *callerdat, struct file_info *finfo)
410 them = fileattr_get0 (finfo->file, "_watchers");
414 cvs_output (finfo->fullname, 0);
419 cvs_output ("\t", 1);
420 while (*p != '>' && *p != '\0')
424 /* Only happens if attribute is misformed. */
425 cvs_output ("\n", 1);
429 cvs_output ("\t", 1);
432 while (*p != '+' && *p != ',' && *p != '\0')
436 cvs_output ("\n", 1);
445 cvs_output ("\t", 1);
447 cvs_output ("\n", 1);
455 watchers (int argc, char **argv)
461 usage (watchers_usage);
464 while ((c = getopt (argc, argv, "+lR")) != -1)
476 usage (watchers_usage);
483 #ifdef CLIENT_SUPPORT
484 if (current_parsed_root->isremote)
492 send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
493 send_file_names (argc, argv, SEND_EXPAND_WILD);
494 send_to_server ("watchers\012", 0);
495 return get_responses_and_close ();
497 #endif /* CLIENT_SUPPORT */
499 return start_recursion
500 ( watchers_fileproc, (FILESDONEPROC) NULL,
501 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
502 argc, argv, local, W_LOCAL, 0, CVS_LOCK_READ,
503 (char *) NULL, 1, (char *) NULL );