cvs-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Cvs-cvs] Changes to ccvs/src/watch.c [signed-commits]


From: Derek Robert Price
Subject: [Cvs-cvs] Changes to ccvs/src/watch.c [signed-commits]
Date: Tue, 11 Oct 2005 22:46:57 -0400

Index: ccvs/src/watch.c
diff -u /dev/null ccvs/src/watch.c:1.45.2.1
--- /dev/null   Wed Oct 12 02:46:57 2005
+++ ccvs/src/watch.c    Wed Oct 12 02:46:38 2005
@@ -0,0 +1,542 @@
+/* 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|add|remove} [-lR] [-a <action>]... [<path>]...\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",
+    "-R (on/off/add/remove): Process directories recursively (default).\n",
+    "-a (add/remove): Specify what actions, one of: `edit', `unedit',\n",
+    "                 `commit', `all', or `none' (defaults to `all').\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, 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;
+
+    TRACE( TRACE_FUNCTION, "modify_watchers ( %s )", file );
+
+    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 (void *callerdat,
+                                     struct file_info *finfo);
+
+static int
+addremove_fileproc (void *callerdat, struct file_info *finfo)
+{
+    watch_modify_watchers (finfo->file, &the_args);
+    return 0;
+}
+
+static int addremove_filesdoneproc (void * callerdat, int err, const char * 
repository,
+                                           const char *update_dir, List * 
entries)
+{
+    int set_default = the_args.setting_default;
+    int dir_check = 0;
+
+    while ( !set_default && dir_check < the_args.num_dirs )
+    {
+       /* If we are recursing, then just see if the first part of update_dir 
+          matches any of the specified directories. Otherwise, it must be an 
exact
+          match. */
+       if ( the_args.local )
+           set_default = strcmp( update_dir, the_args.dirs[ dir_check ] )==0;
+       else 
+           set_default = strncmp( update_dir, the_args.dirs[ dir_check ], 
strlen( the_args.dirs[ dir_check ] ) ) == 0;
+       dir_check++;
+    }
+
+    if (set_default)
+       watch_modify_watchers (NULL, &the_args);
+    return err;
+}
+
+
+static int
+watch_addremove (int argc, char **argv)
+{
+    int c;
+    int err;
+    int a_omitted;
+    int arg_index;
+    int max_dirs;
+
+    a_omitted = 1;
+    the_args.commit = 0;
+    the_args.edit = 0;
+    the_args.unedit = 0;
+    the_args.num_dirs = 0;
+    the_args.dirs = NULL;
+    the_args.local = 0;
+
+    optind = 0;
+    while ((c = getopt (argc, argv, "+lRa:")) != -1)
+    {
+       switch (c)
+       {
+           case 'l':
+               the_args.local = 1;
+               break;
+           case 'R':
+               the_args.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;
+
+    the_args.num_dirs = 0;
+    max_dirs = 4; /* Arbitrary choice. */
+    the_args.dirs = xmalloc( sizeof( const char * ) * max_dirs );
+
+    TRACE (TRACE_FUNCTION, "watch_addremove (%d)", argc);
+    for ( arg_index=0; arg_index<argc; ++arg_index )
+    {
+       TRACE( TRACE_FUNCTION, "\t%s", argv[ arg_index ]);
+       if ( isdir( argv[ arg_index ] ) )
+       {
+           if ( the_args.num_dirs >= max_dirs )
+           {
+               max_dirs *= 2;
+               the_args.dirs = (const char ** )xrealloc( (void 
*)the_args.dirs, max_dirs );
+           }
+           the_args.dirs[ the_args.num_dirs++ ] = argv[ arg_index ];
+       }
+    }
+
+    if (a_omitted)
+    {
+       the_args.edit = 1;
+       the_args.unedit = 1;
+       the_args.commit = 1;
+    }
+
+#ifdef CLIENT_SUPPORT
+    if (current_parsed_root->isremote)
+    {
+       start_server ();
+       ign_setup ();
+
+       if (the_args.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)
+           option_with_arg ("-a", "edit");
+       if (the_args.unedit)
+           option_with_arg ("-a", "unedit");
+       if (the_args.commit)
+           option_with_arg ("-a", "commit");
+       if (!the_args.edit && !the_args.unedit && !the_args.commit)
+           option_with_arg ("-a", "none");
+       send_arg ("--");
+       send_files (argc, argv, the_args.local, 0, SEND_NO_CONTENTS,
+                   SIGN_NEVER, NULL, NULL);
+       send_file_names (argc, argv, SEND_EXPAND_WILD);
+       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_promotably (argc, argv, the_args.local, W_LOCAL, 0);
+
+    err = start_recursion
+       (addremove_fileproc, addremove_filesdoneproc, NULL, NULL, NULL,
+        argc, argv, the_args.local, W_LOCAL, 0, CVS_LOCK_WRITE,
+        NULL, 1, NULL);
+
+    Lock_Cleanup ();
+    free( (void *)the_args.dirs );
+    the_args.dirs = NULL;
+
+    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") == 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 [-lR] [<file>]...\n",
+    "-l\tProcess this directory only (not recursive).\n",
+    "-R\tProcess directories recursively (default).\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);
+
+static int
+watchers_fileproc (void *callerdat, struct file_info *finfo)
+{
+    char *them;
+    char *p;
+
+    them = fileattr_get0 (finfo->file, "_watchers");
+    if (them == NULL)
+       return 0;
+
+    cvs_output (finfo->fullname, 0);
+
+    p = them;
+    while (1)
+    {
+       cvs_output ("\t", 1);
+       while (*p != '>' && *p != '\0')
+           cvs_output (p++, 1);
+       if (*p == '\0')
+       {
+           /* Only happens if attribute is misformed.  */
+           cvs_output ("\n", 1);
+           break;
+       }
+       ++p;
+       cvs_output ("\t", 1);
+       while (1)
+       {
+           while (*p != '+' && *p != ',' && *p != '\0')
+               cvs_output (p++, 1);
+           if (*p == '\0')
+           {
+               cvs_output ("\n", 1);
+               goto out;
+           }
+           if (*p == ',')
+           {
+               ++p;
+               break;
+           }
+           ++p;
+           cvs_output ("\t", 1);
+       }
+       cvs_output ("\n", 1);
+    }
+  out:;
+    free (them);
+    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;
+
+#ifdef CLIENT_SUPPORT
+    if (current_parsed_root->isremote)
+    {
+       start_server ();
+       ign_setup ();
+
+       if (local)
+           send_arg ("-l");
+       send_arg ("--");
+       send_files (argc, argv, local, 0, SEND_NO_CONTENTS, SIGN_NEVER, NULL,
+                   NULL);
+       send_file_names (argc, argv, SEND_EXPAND_WILD);
+       send_to_server ("watchers\012", 0);
+       return get_responses_and_close ();
+    }
+#endif /* CLIENT_SUPPORT */
+
+    return start_recursion (watchers_fileproc, NULL, NULL,
+                           NULL, NULL, argc, argv, local, W_LOCAL, 0,
+                           CVS_LOCK_READ, NULL, 1, NULL);
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]