bug-cvs
[Top][All Lists]
Advanced

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

CvsNt port of 'cvs ls' subcommand


From: Mark D. Baushke
Subject: CvsNt port of 'cvs ls' subcommand
Date: Sat, 20 Dec 2003 18:58:58 -0800

Hi Folks,

Have you any comments on this patch? 

It is a port of the 'cvs ls' functionality from CvsNt.

        -- Mark

Log message:

* NEWS: Note new cvs ls subcommand.

* doc/cvs.texinfo (ls, ls options, ls examples): Document
new ls command.

* src/ls.c (ls, ls_proc, ls_fileproc, ls_direntproc): New
file and new functions.
src/cvs.h (ls): Add prototype.
src/main.c (cmds): Add ls entry.
src/server.c (serve_ls): New function.
(requests): Add new entry for ls.
src/sanity.sh (branches2): Test new cvs ls command.

Index: NEWS
===================================================================
RCS file: /cvs/ccvs/NEWS,v
retrieving revision 1.176
diff -u -p -r1.176 NEWS
--- NEWS        18 Dec 2003 23:13:16 -0000      1.176
+++ NEWS        21 Dec 2003 02:52:43 -0000
@@ -1,6 +1,8 @@
 Changes since 1.12.5:
 *********************
 
+* Directory browsing via 'cvs ls' command.
+
 Changes between 1.12.4 and 1.12.5:
 **********************************
 
Index: doc/cvs.texinfo
===================================================================
RCS file: /cvs/ccvs/doc/cvs.texinfo,v
retrieving revision 1.590
diff -u -p -r1.590 cvs.texinfo
--- doc/cvs.texinfo     9 Dec 2003 20:23:56 -0000       1.590
+++ doc/cvs.texinfo     21 Dec 2003 02:52:43 -0000
@@ -10683,6 +10683,86 @@ selected by @samp{-b} and @samp{-r}.
 
 Contributed examples are gratefully accepted.
 
address@hidden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
. .
address@hidden ls
address@hidden ls
address@hidden ls (subcommand)
+
address@hidden @bullet
address@hidden
+ls [-q][-e][-l][-r rev][-D address@hidden
address@hidden
+Requires: repository.
address@hidden
+Changes: nothing.
address@hidden
+Synonym: dir
address@hidden
+Synonym: list
address@hidden itemize
+
address@hidden
+* ls options::               ls options
+* ls examples:               ls examples
address@hidden menu
+
address@hidden ls options
address@hidden ls options
+
+These stardared optoins are supported by @code{ls}:
+
address@hidden @code
address@hidden -q
+Quieter output.
+
address@hidden -e
+Display in CVS/Entries format.
+
address@hidden -l
+Display all details.
+
address@hidden -R
+List recusively.
+
address@hidden -r @var{rev}
+Show files with revision or tag.
+
address@hidden -D @var{date}
+Show files from date.
address@hidden table
+
address@hidden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
. .
address@hidden ls examples
address@hidden ls examples
+
address@hidden
+$ cvs ls
+Listing module: 
+
+CVSROOT
+first-dir
address@hidden example
+
address@hidden
+$ cvs ls CVSROOT
+Listing module: 
+
+
+Directory CVSROOT
+
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+rcsinfo
+taginfo
+verifymsg
+
address@hidden example
+
 @c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 @node rdiff
 @appendixsec rdiff---'patch' format diffs between releases
Index: src/Makefile.in
===================================================================
RCS file: /cvs/ccvs/src/Makefile.in,v
retrieving revision 1.105
diff -u -p -r1.105 Makefile.in
--- src/Makefile.in     25 Nov 2003 10:59:51 -0000      1.105
+++ src/Makefile.in     21 Dec 2003 02:52:43 -0000
@@ -204,6 +204,7 @@ cvs_SOURCES = \
        log-buffer.c log-buffer.h \
        login.c \
        logmsg.c \
+       ls.c \
        main.c \
        mkmodules.c \
        modules.c \
Index: src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.275
diff -u -p -r1.275 cvs.h
--- src/cvs.h   9 Dec 2003 20:18:10 -0000       1.275
+++ src/cvs.h   21 Dec 2003 02:52:43 -0000
@@ -486,6 +486,7 @@ FILE *cvs_temp_file (char **filename);
 int numdots (const char *s);
 char *increment_revnum (const char *);
 int compare_revnums (const char *, const char *);
+int ls (int argc, char *argv[]);
 int unlink_file (const char *f);
 int unlink_file_dir (const char *f);
 int update (int argc, char *argv[]);
Index: src/ls.c
===================================================================
RCS file: src/ls.c
diff -N src/ls.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/ls.c    21 Dec 2003 02:52:43 -0000
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 1992, Brian Berliner and Jeff Polk
+ * Copyright (c) 1989-1992, Brian Berliner
+ * Copyright (c) 2001, Tony Hoyle
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS source distribution.
+ *
+ * Query CVS/Entries from server
+ */
+
+#include "cvs.h"
+
+static int ls_proc (int argc, char **argv, char *xwhere, char *mwhere, char 
*mfile, int shorten, int local, char *mname, char *msg);
+static int ls_fileproc(void *callerdat, struct file_info *finfo);
+static Dtype ls_direntproc(void *callerdat, char *dir,
+                                     char *repos, char *update_dir,
+                                     List *entries);
+
+static RCSNode *xrcsnode;
+
+static const char *const ls_usage[] =
+{
+    "Usage: %s %s [-q] [-e] [-l] [-R] [-r rev] [-D date] [modules...]\n",
+       "\t-q\tQuieter output.\n",
+    "\t-e\tDisplay in CVS/Entries format.\n",
+    "\t-l\tDisplay all details.\n",
+       "\t-R\tList recursively.\n",
+    "\t-r rev\tShow files with revision or tag.\n",
+    "\t-D date\tShow files from date.\n",
+    "(Specify the --help global option for a list of other help options)\n",
+    NULL
+};
+
+static int entries_format;
+static int long_format;
+static int quiet;
+static char *show_tag;
+static char *show_date;
+static int tag_validated;
+static int recurse;
+static char *regexp_match;
+
+int
+ls(int argc, char **argv)
+{
+    int c;
+    int err = 0;
+
+    if (argc == -1)
+       usage (ls_usage);
+
+    entries_format = 0;
+    long_format = 0;
+    show_tag = NULL;
+    show_date = NULL;
+    tag_validated = 0;
+    quiet = 0;
+    recurse = 0;
+
+    optind = 0;
+    while ((c = getopt (argc, argv, "qelr:D:R")) != -1)
+    {
+       switch (c)
+       {
+           case 'q':
+               quiet = 1;
+               break;
+           case 'e':
+               entries_format = 1;
+               break;
+           case 'l':
+               long_format = 1;
+               break;
+           case 'r':
+               show_tag = optarg;
+               break;
+           case 'D':
+               show_date = Make_Date (optarg);
+               break;
+           case 'R':
+               recurse = 1;
+               break;
+           case '?':
+           default:
+               usage (ls_usage);
+               break;
+       }
+    }
+    argc -= optind;
+    argv += optind;
+
+    wrap_setup ();
+
+#ifdef CLIENT_SUPPORT
+    if (current_parsed_root->isremote)
+    {
+       /* We're the local client.  Fire up the remote server.  */
+       start_server ();
+
+       ign_setup ();
+
+       if (!supported_request ("ls"))
+           error (1, 0, "server does not support %s",command_name);
+
+       if(quiet)
+           send_arg("-q");
+       if(entries_format)
+           send_arg("-e");
+       if(long_format)
+           send_arg("-l");
+       if(recurse)
+           send_arg("-R");
+       if(show_tag)
+           option_with_arg("-r",show_tag);
+       if(show_date)
+           option_with_arg("-D",show_date);
+
+       send_arg("--");
+       {
+           int i;
+           for (i = 0; i < argc; i++)
+               send_arg (argv[i]);
+       }
+
+       send_to_server ("ls\012", 0);
+
+       err = get_responses_and_close ();
+       return err;
+    }
+#endif
+
+    {
+       DBM *db;
+       int i;
+       db = open_module ();
+       if(argc)
+       {
+           for (i = 0; i < argc; i++)
+           {
+               char *mod = xstrdup(argv[i]);
+               char *p;
+
+               for(p=strchr(mod,'\\'); p; p=strchr(p,'\\'))
+                   *p='/';
+
+               p = strrchr(mod,'/');
+               if(p && (strchr(p,'?') || strchr(p,'*')))
+               {
+                   *p='\0';
+                   regexp_match = p+1;
+               }
+               else
+                   regexp_match = NULL;
+
+               err += do_module (db, mod, MISC,
+                                 "Listing",
+                                 ls_proc, (char *) NULL, 0, 0, 0, 0, 
(char*)NULL);
+
+               free(mod);
+           }
+       }
+       else
+       {
+           err += do_module (db, "", MISC,
+                             "Listing",
+                             ls_proc, (char *) NULL, 0, 0, 0, 0, (char*)NULL);
+       }
+       close_module (db);
+    }
+
+    return (err);
+}
+
+static int
+ls_proc (int argc, char **argv, char *xwhere, char *mwhere, char *mfile,
+                int shorten, int local, char *mname, char *msg)
+{
+    /* Begin section which is identical to patch_proc--should this
+       be abstracted out somehow?  */
+    char *myargv[2];
+    int err = 0;
+    int which;
+    char *repository = NULL;
+    char *where;
+
+    if(!quiet)
+    {
+       if(strcmp(mname,"."))
+       {
+           cvs_outerr("Listing module: ", 0);
+           cvs_outerr(mname, 0);
+           cvs_outerr("\n\n", 0);
+       }
+       else
+           cvs_outerr("Listing modules on server\n\n", 0);
+       }
+
+       repository = xmalloc (strlen (current_parsed_root->directory) + strlen 
(argv[0])
+                             + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
+       (void) sprintf (repository, "%s/%s", current_parsed_root->directory, 
argv[0]);
+       where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) 
+ 1)
+                        + 1);
+       (void) strcpy (where, argv[0]);
+
+       /* if mfile isn't null, we need to set up to do only part of the module 
*/
+       if (mfile != NULL)
+       {
+           char *cp;
+           char *path;
+
+           /* if the portion of the module is a path, put the dir part on 
repos */
+           if ((cp = strrchr (mfile, '/')) != NULL)
+           {
+               *cp = '\0';
+               (void) strcat (repository, "/");
+               (void) strcat (repository, mfile);
+               (void) strcat (where, "/");
+               (void) strcat (where, mfile);
+               mfile = cp + 1;
+           }
+
+           /* take care of the rest */
+           path = xmalloc (strlen (repository) + strlen (mfile) + 5);
+           (void) sprintf (path, "%s/%s", repository, mfile);
+           if (isdir (path))
+           {
+               /* directory means repository gets the dir tacked on */
+               (void) strcpy (repository, path);
+               (void) strcat (where, "/");
+               (void) strcat (where, mfile);
+           }
+           else
+           {
+               myargv[0] = argv[0];
+               myargv[1] = mfile;
+               argc = 2;
+               argv = myargv;
+           }
+           free (path);
+       }
+
+       /* cd to the starting repository */
+       if ( CVS_CHDIR (repository) < 0)
+       {
+           error (0, errno, "cannot chdir to %s", repository);
+           free (repository);
+           free( where );
+           return (1);
+       }
+       /* End section which is identical to patch_proc.  */
+
+       if (show_tag)
+           which = W_REPOS | W_ATTIC;
+       else
+           which = W_REPOS;
+
+    if (show_tag != NULL && !tag_validated)
+    {
+       tag_check_valid (show_tag, argc - 1, argv + 1, local, 0, repository);
+       tag_validated = 1;
+    }
+
+    err = start_recursion ( ls_fileproc, (FILESDONEPROC) NULL,
+                           ls_direntproc, (DIRLEAVEPROC) NULL, NULL,
+                           argc - 1, argv + 1, local, which, 0, CVS_LOCK_READ,
+                           where, 1, repository );
+
+    if ( !( which & W_LOCAL ) ) free ( repository );
+    if ( where ) free ( where );
+
+    if(!strcmp(mname,"."))
+    {
+       DBM *db;
+       if (db = open_module ())
+       {
+           datum key = dbm_firstkey(db);
+           if(key.dptr)
+           {
+               cvs_outerr("\n",1);
+               if(!quiet)
+                   cvs_outerr("Virtual modules on server (CVSROOT/modules 
file)\n\n",0);
+               cat_module(0);
+           }
+           close_module(db);
+       }
+    }
+    return err;
+}
+
+
+/*
+ * display the status of a file
+ */
+/* ARGSUSED */
+static int
+ls_fileproc(void *callerdat, struct file_info *finfo)
+{
+    Vers_TS *vers;
+    char outdate[32],tag[64];
+    time_t t;
+    char *regex_err;
+
+    if(regexp_match)
+    {
+#ifdef FILENAMES_CASE_INSENSITIVE
+         re_set_syntax(REG_ICASE|RE_SYNTAX_EGREP);
+#else
+         re_set_syntax(RE_SYNTAX_EGREP);
+#endif
+         if ((regex_err = re_comp (regexp_match)) != NULL)
+         {
+             error (1, 0, "bad regular expression passed to 'ls': %s", 
regex_err);
+         }
+         if (re_exec (finfo->file) == 0)
+             return 0;                         /* no match */
+    }
+
+    vers = Version_TS (finfo, NULL, show_tag, show_date, 1, 0);
+    if(!vers->vn_rcs)
+       return 0;
+
+    t=RCS_getrevtime (finfo->rcs, vers->vn_rcs, 0, 0);
+    strcpy(outdate,asctime(gmtime(&t)));
+    outdate[strlen(outdate)-1]='\0';
+
+    if(entries_format)
+    {
+       tag[0]='\0';
+       if(show_tag)
+           sprintf(tag,"T%s",show_tag);
+
+       
printf("/%s/%s/%s/%s/%s\n",finfo->file,vers->vn_rcs,outdate,vers->options,tag);
+    }
+    else if(long_format)
+    {
+       printf("%-32.32s%-8.8s%s 
%s\n",finfo->file,vers->vn_rcs,outdate,vers->options);
+    }
+    else
+       printf("%s\n",finfo->file);
+
+    freevers_ts(&vers);
+    return 0;
+}
+
+Dtype
+ls_direntproc ( void *callerdat, char *dir,
+               char *repos, char *update_dir,
+               List *entries)
+{
+    if(!strcasecmp(dir,"."))
+       return R_PROCESS;
+    if(recurse)
+    {
+       printf("\nDirectory %s\n\n",update_dir);
+       return R_PROCESS;
+    }
+    if(entries_format)
+    {
+       printf("D/%s////\n",dir);
+    }
+    else if(long_format)
+    {
+       printf("%-32.32s(directory)\n",dir);
+    }
+    else
+       printf("%s\n",dir);
+    return R_SKIP_ALL;
+}
Index: src/main.c
===================================================================
RCS file: /cvs/ccvs/src/main.c,v
retrieving revision 1.201
diff -u -p -r1.201 main.c
--- src/main.c  24 Nov 2003 21:27:07 -0000      1.201
+++ src/main.c  21 Dec 2003 02:52:43 -0000
@@ -125,6 +125,7 @@ static const struct cmd
     { "login",    "logon",    "lgn",       login,     0 },
     { "logout",   NULL,       NULL,        logout,    0 },
 #endif /* AUTH_CLIENT_SUPPORT */
+    { "ls",      "dir",      "list",      ls,        0 },
 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && 
defined(SERVER_SUPPORT)
     { "pserver",  NULL,       NULL,        server,    
CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
 #endif
@@ -216,6 +217,7 @@ static const char *const cmd_usage[] =
     "        login        Prompt for password for authenticating server\n",
     "        logout       Removes entry in .cvspass for remote repository\n",
 #endif /* AUTH_CLIENT_SUPPORT */
+    "        ls           List files in the repository\n",
 #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && 
defined(SERVER_SUPPORT)
     "        pserver      Password server mode\n",
 #endif
Index: src/sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.862
diff -u -p -r1.862 sanity.sh
--- src/sanity.sh       18 Dec 2003 17:45:35 -0000      1.862
+++ src/sanity.sh       21 Dec 2003 02:52:44 -0000
@@ -6467,6 +6467,118 @@ File: file3             Status: Up-to-da
    Sticky Date:                (none)
    Sticky Options:     (none)"
 
+          dotest branches2-14-ls-1 "${testcvs} ls" \
+"Listing module: 
+
+CVSROOT
+first-dir"
+          dotest branches2-14-ls-2 "${testcvs} ls -R; echo endit" \
+"Listing module: 
+
+
+Directory CVSROOT
+
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+rcsinfo
+taginfo
+verifymsg
+
+Directory CVSROOT/Emptydir
+
+
+Directory first-dir
+
+file1
+
+Directory first-dir/dir1
+
+endit"
+          dotest branches2-14-ls-3 "${testcvs} ls -l -R; echo endit" \
+"Listing module: 
+
+
+Directory CVSROOT
+
+checkoutlist                    1\.1     ${DATE} *
+commitinfo                      1\.1     ${DATE} *
+config                          1\.1     ${DATE} *
+cvswrappers                     1\.1     ${DATE} *
+loginfo                         1\.1     ${DATE} *
+modules                         1\.1     ${DATE} *
+notify                          1\.1     ${DATE} *
+rcsinfo                         1\.1     ${DATE} *
+taginfo                         1\.1     ${DATE} *
+verifymsg                       1\.1     ${DATE} *
+
+Directory CVSROOT/Emptydir
+
+
+Directory first-dir
+
+file1                           1\.1     ${DATE} *
+
+Directory first-dir/dir1
+
+endit"
+          dotest branches2-14-ls-4 "${testcvs} ls -e -R; echo endit" \
+"Listing module: 
+
+
+Directory CVSROOT
+
+/checkoutlist/1\.1/${DATE}//
+/commitinfo/1\.1/${DATE}//
+/config/1\.1/${DATE}//
+/cvswrappers/1\.1/${DATE}//
+/loginfo/1\.1/${DATE}//
+/modules/1\.1/${DATE}//
+/notify/1\.1/${DATE}//
+/rcsinfo/1\.1/${DATE}//
+/taginfo/1\.1/${DATE}//
+/verifymsg/1\.1/${DATE}//
+
+Directory CVSROOT/Emptydir
+
+
+Directory first-dir
+
+/file1/1\.1/${DATE}//
+
+Directory first-dir/dir1
+
+endit"
+          dotest branches2-14-ls-4 "${testcvs} ls -q -R; echo endit" \
+"
+Directory CVSROOT
+
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+rcsinfo
+taginfo
+verifymsg
+
+Directory CVSROOT/Emptydir
+
+
+Directory first-dir
+
+file1
+
+Directory first-dir/dir1
+
+endit"
+
          # FIXME: Just clobbering the directory like this is a bit
          # tacky, although people generally expect it to work.  Maybe
          # we should release it instead.  We do it a few other places
@@ -6634,7 +6746,24 @@ File: file5              Status: Up-to-da
    Sticky Options:     (none)"
          dotest_fail branches2-38 "test -f CVS/status"
 
+          dotest branches2-39 "${testcvs} ls -rb1 -l -R first-dir" \
+"Listing module: first-dir
+
+file1                           1\.1     ${DATE} *
+file2                           1\.1\.2\.1 ${DATE} *
+
+Directory first-dir/dir1
+
+file3                           1\.1\.2\.1 ${DATE} *
+
+Directory first-dir/dir2
+
+file4                           1\.1\.2\.1 ${DATE} *"
+
          cd ../../..
+
+         dokeep
+
          rm -rf ${CVSROOT_DIRNAME}/first-dir
          rm -r trunk b1a b1b
          ;;
Index: src/server.c
===================================================================
RCS file: /cvs/ccvs/src/server.c,v
retrieving revision 1.333
diff -u -p -r1.333 server.c
--- src/server.c        18 Dec 2003 18:11:15 -0000      1.333
+++ src/server.c        21 Dec 2003 02:52:44 -0000
@@ -3544,6 +3544,12 @@ serve_rlog (char *arg)
 }
 
 static void
+serve_ls (char *arg)
+{
+  do_cvs_command ("ls", ls);
+}
+
+static void
 serve_add (char *arg)
 {
     do_cvs_command ("add", add);
@@ -4550,6 +4556,7 @@ struct request requests[] =
   REQ_LINE("diff", serve_diff, 0),
   REQ_LINE("log", serve_log, 0),
   REQ_LINE("rlog", serve_rlog, 0),
+  REQ_LINE("ls", serve_ls, 0),
   REQ_LINE("add", serve_add, 0),
   REQ_LINE("remove", serve_remove, 0),
   REQ_LINE("update-patches", serve_ignore, 0),





reply via email to

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