[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.
+@c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+@node ls
+@appendixsec ls
+@cindex ls (subcommand)
+
+@itemize @bullet
+@item
+ls [-q][-e][-l][-r rev][-D date][modules@dots{}]
+@item
+Requires: repository.
+@item
+Changes: nothing.
+@item
+Synonym: dir
+@item
+Synonym: list
+@end itemize
+
+@menu
+* ls options:: ls options
+* ls examples: ls examples
+@end menu
+
+@node ls options
+@appendixsubsec ls options
+
+These stardared optoins are supported by @code{ls}:
+
+@table @code
+@item -q
+Quieter output.
+
+@item -e
+Display in CVS/Entries format.
+
+@item -l
+Display all details.
+
+@item -R
+List recusively.
+
+@item -r @var{rev}
+Show files with revision or tag.
+
+@item -D @var{date}
+Show files from date.
+@end table
+
+@c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+@node ls examples
+@appendixsubsec ls examples
+
+@example
+$ cvs ls
+Listing module:
+
+CVSROOT
+first-dir
+@end example
+
+@example
+$ cvs ls CVSROOT
+Listing module:
+
+
+Directory CVSROOT
+
+checkoutlist
+commitinfo
+config
+cvswrappers
+loginfo
+modules
+notify
+rcsinfo
+taginfo
+verifymsg
+
+@end 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),
- CvsNt port of 'cvs ls' subcommand,
Mark D. Baushke <=