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: `edit', `unedit',\n",
26 " `commit', `all', or `none' (defaults to `all').\n",
27 "(Specify the --help global option for a list of other help options.)\n",
31 static struct addremove_args the_args;
34 watch_modify_watchers (file, what)
36 struct addremove_args *what;
38 char *curattr = fileattr_get0 (file, "_watchers");
46 size_t mynewattr_size;
49 int add_unedit_pending;
50 int add_commit_pending;
51 int remove_edit_pending;
52 int remove_unedit_pending;
53 int remove_commit_pending;
54 int add_tedit_pending;
55 int add_tunedit_pending;
56 int add_tcommit_pending;
59 who_len = strlen (who);
61 /* Look for current watcher types for this user. */
67 if (strncmp (who, p, who_len) == 0
70 /* Found this user. */
71 mycurattr = p + who_len + 1;
79 if (mycurattr != NULL)
81 mycurattr = xstrdup (mycurattr);
82 p = strchr (mycurattr, ',');
87 /* Now copy mycurattr to mynewattr, making the requisite modifications.
88 Note that we add a dummy '+' to the start of mynewattr, to reduce
89 special cases (but then we strip it off when we are done). */
91 mynewattr_size = sizeof "+edit+unedit+commit+tedit+tunedit+tcommit";
92 if (mycurattr != NULL)
93 mynewattr_size += strlen (mycurattr);
94 mynewattr = xmalloc (mynewattr_size);
97 add_edit_pending = what->adding && what->edit;
98 add_unedit_pending = what->adding && what->unedit;
99 add_commit_pending = what->adding && what->commit;
100 remove_edit_pending = !what->adding && what->edit;
101 remove_unedit_pending = !what->adding && what->unedit;
102 remove_commit_pending = !what->adding && what->commit;
103 add_tedit_pending = what->add_tedit;
104 add_tunedit_pending = what->add_tunedit;
105 add_tcommit_pending = what->add_tcommit;
107 /* Copy over existing watch types, except those to be removed. */
111 pend = strchr (p, '+');
114 pend = p + strlen (p);
120 /* Process this item. */
121 if (pend - p == 4 && strncmp ("edit", p, 4) == 0)
123 if (!remove_edit_pending)
124 strcat (mynewattr, "+edit");
125 add_edit_pending = 0;
127 else if (pend - p == 6 && strncmp ("unedit", p, 6) == 0)
129 if (!remove_unedit_pending)
130 strcat (mynewattr, "+unedit");
131 add_unedit_pending = 0;
133 else if (pend - p == 6 && strncmp ("commit", p, 6) == 0)
135 if (!remove_commit_pending)
136 strcat (mynewattr, "+commit");
137 add_commit_pending = 0;
139 else if (pend - p == 5 && strncmp ("tedit", p, 5) == 0)
141 if (!what->remove_temp)
142 strcat (mynewattr, "+tedit");
143 add_tedit_pending = 0;
145 else if (pend - p == 7 && strncmp ("tunedit", p, 7) == 0)
147 if (!what->remove_temp)
148 strcat (mynewattr, "+tunedit");
149 add_tunedit_pending = 0;
151 else if (pend - p == 7 && strncmp ("tcommit", p, 7) == 0)
153 if (!what->remove_temp)
154 strcat (mynewattr, "+tcommit");
155 add_tcommit_pending = 0;
161 /* Copy over any unrecognized watch types, for future
163 mp = mynewattr + strlen (mynewattr);
165 strncpy (mp, p, pend - p);
166 *(mp + (pend - p)) = '\0';
169 /* Set up for next item. */
173 /* Add in new watch types. */
174 if (add_edit_pending)
175 strcat (mynewattr, "+edit");
176 if (add_unedit_pending)
177 strcat (mynewattr, "+unedit");
178 if (add_commit_pending)
179 strcat (mynewattr, "+commit");
180 if (add_tedit_pending)
181 strcat (mynewattr, "+tedit");
182 if (add_tunedit_pending)
183 strcat (mynewattr, "+tunedit");
184 if (add_tcommit_pending)
185 strcat (mynewattr, "+tcommit");
191 fileattr_modify (curattr,
193 mynewattr[0] == '\0' ? NULL : mynewattr + 1,
196 /* If the attribute is unchanged, don't rewrite the attribute file. */
197 if (!((curattr_new == NULL && curattr == NULL)
198 || (curattr_new != NULL
200 && strcmp (curattr_new, curattr) == 0)))
204 if (curattr_new != NULL)
210 if (mycurattr != NULL)
212 if (mynewattr != NULL)
216 static int addremove_fileproc PROTO ((void *callerdat,
217 struct file_info *finfo));
220 addremove_fileproc (callerdat, finfo)
222 struct file_info *finfo;
224 watch_modify_watchers (finfo->file, &the_args);
230 static int addremove_filesdoneproc PROTO ((void *, int, const char *,
231 const char *, List *));
234 addremove_filesdoneproc (callerdat, err, repository, update_dir, entries)
237 const char *repository;
238 const char *update_dir;
241 if (the_args.setting_default)
242 watch_modify_watchers (NULL, &the_args);
246 static int watch_addremove PROTO ((int argc, char **argv));
249 watch_addremove (argc, argv)
263 while ((c = getopt (argc, argv, "+lRa:")) != -1)
275 if (strcmp (optarg, "edit") == 0)
277 else if (strcmp (optarg, "unedit") == 0)
279 else if (strcmp (optarg, "commit") == 0)
281 else if (strcmp (optarg, "all") == 0)
287 else if (strcmp (optarg, "none") == 0)
312 #ifdef CLIENT_SUPPORT
313 if (current_parsed_root->isremote)
320 /* FIXME: copes poorly with "all" if server is extended to have
321 new watch types and client is still running an old version. */
323 option_with_arg ("-a", "edit");
325 option_with_arg ("-a", "unedit");
327 option_with_arg ("-a", "commit");
328 if (!the_args.edit && !the_args.unedit && !the_args.commit)
329 option_with_arg ("-a", "none");
331 send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
332 send_file_names (argc, argv, SEND_EXPAND_WILD);
333 send_to_server (the_args.adding ?
334 "watch-add\012" : "watch-remove\012",
336 return get_responses_and_close ();
338 #endif /* CLIENT_SUPPORT */
340 the_args.setting_default = (argc <= 0);
342 lock_tree_for_write (argc, argv, local, W_LOCAL, 0);
344 err = start_recursion (addremove_fileproc, addremove_filesdoneproc,
345 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
346 argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
347 (char *) NULL, 1, (char *) NULL);
354 watch_add (argc, argv)
359 return watch_addremove (argc, argv);
363 watch_remove (argc, argv)
368 return watch_addremove (argc, argv);
378 if (strcmp (argv[1], "on") == 0)
382 return watch_on (argc, argv);
384 else if (strcmp (argv[1], "off") == 0)
388 return watch_off (argc, argv);
390 else if (strcmp (argv[1], "add") == 0)
394 return watch_add (argc, argv);
396 else if (strcmp (argv[1], "remove") == 0)
400 return watch_remove (argc, argv);
407 static const char *const watchers_usage[] =
409 "Usage: %s %s [-lR] [<file>]...\n",
410 "-l\tProcess this directory only (not recursive).\n",
411 "-R\tProcess directories recursively (default).\n",
412 "(Specify the --help global option for a list of other help options.)\n",
416 static int watchers_fileproc PROTO ((void *callerdat,
417 struct file_info *finfo));
420 watchers_fileproc (callerdat, finfo)
422 struct file_info *finfo;
427 them = fileattr_get0 (finfo->file, "_watchers");
431 cvs_output (finfo->fullname, 0);
436 cvs_output ("\t", 1);
437 while (*p != '>' && *p != '\0')
441 /* Only happens if attribute is misformed. */
442 cvs_output ("\n", 1);
446 cvs_output ("\t", 1);
449 while (*p != '+' && *p != ',' && *p != '\0')
453 cvs_output ("\n", 1);
462 cvs_output ("\t", 1);
464 cvs_output ("\n", 1);
472 watchers (argc, argv)
480 usage (watchers_usage);
483 while ((c = getopt (argc, argv, "+lR")) != -1)
495 usage (watchers_usage);
502 #ifdef CLIENT_SUPPORT
503 if (current_parsed_root->isremote)
511 send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
512 send_file_names (argc, argv, SEND_EXPAND_WILD);
513 send_to_server ("watchers\012", 0);
514 return get_responses_and_close ();
516 #endif /* CLIENT_SUPPORT */
518 return start_recursion (watchers_fileproc, (FILESDONEPROC) NULL,
519 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
520 argc, argv, local, W_LOCAL, 0, CVS_LOCK_READ,
521 (char *) NULL, 1, (char *) NULL);