[Note that this doesn't send any information about the file, such as whether it is a file or a directory, whether it is alive or dead on the head revision of the trunk (or as of some tag), or any other such information. Trying to figure this out is probably the most important issue. Need to document +list/-list in cvsclient.texi Needs testsuite. Needs ChangeLog entries. Here is an example of accessing this. Translating this to something you can run from the command line is left as an exercise to the reader (for example, a ~20 line perl script). C: Root /home/kingdon/zwork/cvsroot C: list S: M CVSROOT S: M bar S: M dir224 S: M foo -kingdon] Index: doc/cvsclient.texi =================================================================== RCS file: /home2/cvsroot/ccvs/doc/cvsclient.texi,v retrieving revision 1.110 diff -u -r1.110 cvsclient.texi --- cvsclient.texi 1998/09/13 22:39:03 1.110 +++ cvsclient.texi 1998/09/15 22:17:39 @@ -1079,6 +1079,16 @@ requests for this command; they are not used. Arguments to these commands are module names, as described for @code{co}. +@item list @var{directory} +Response expected: yes. List files and subdirectories in +@var{directory} which is a filename relative to the repository. The +client should not send @code{Argument}, @code{Directory}, @code{Entry}, +or @code{Modified} requests for this command; they are not used. For +example, a client might send @samp{list .} to get a list of directories +and files at the top level of the repository and let the user click on +directories to get (which the client would then do with a @samp{co} +request). + @item init @var{root-name} \n Response expected: yes. If it doesn't already exist, create a @sc{cvs} repository @var{root-name}. Note that @var{root-name} is a local Index: src/server.c =================================================================== RCS file: /home2/cvsroot/ccvs/src/server.c,v retrieving revision 1.204 diff -u -r1.204 server.c --- server.c 1998/09/10 12:41:13 1.204 +++ server.c 1998/09/16 00:12:44 @@ -3554,6 +3554,103 @@ serve_co (arg); } +/* Handle the "list" request. Probably this could be done all in the + parent process, but getting all the error handling right and + everything is just a bit hairy (especially if we want to rely on + find_names.c). */ + +static int output_one PROTO ((Node *, void *)); + +static int +output_one (node, closure) + Node *node; + void *closure; +{ + cvs_output_tagged ("fname", node->key); + cvs_output_tagged ("newline", NULL); + return 0; +} + +static int list PROTO ((int, char **)); + +static int +list (argc, argv) + int argc; + char **argv; +{ + List *files; + List *dirs; + char *repository; + + assert (argc == 2); + + repository = xmalloc (strlen (CVSroot_directory) + + strlen (argv[1]) + + 80); + strcpy (repository, CVSroot_directory); + strcat (repository, "/"); + strcat (repository, argv[1]); + + lock_dir_for_write (repository); + + /* FIXME? although using find_names.c is clean in one sense, this + means we do all the readdir() stuff twice on the same + directory. If we had a variant of Find_Names which passes + back the nature of each item (directory or file), maybe in two + lists if that is the most convenient way, then I think + recurse.c could benefit from it too. + + Note that with this implementation, it would be trivial to tell + the client what is a directory and what is an RCS file. + With the ideas sketched above, we might have to stat() each + file to get that info (which might still be OK). */ + + /* The W_ATTIC is what we mean when we say that this doesn't tell + the client whether the revision is alive at any particular time + (e.g. head of trunk). */ + files = Find_Names (repository, + W_REPOS | W_ATTIC, + + /* AFLAG and OPTENTRIES only matter with W_LOCAL. */ + 0, + NULL); + dirs = Find_Directories (repository, W_REPOS | W_ATTIC, NULL); + + Lock_Cleanup (); + + cvs_output_tagged ("+list", NULL); + walklist (files, output_one, NULL); + walklist (dirs, output_one, NULL); + cvs_output_tagged ("-list", NULL); + + dellist (&files); + dellist (&dirs); + + return 0; +} + +static void serve_list PROTO ((char *)); + +static void +serve_list (arg) + char *arg; +{ + if (argument_count > 1) + { + if (alloc_pending (80)) + strcpy (pending_error_text, "\ +protocol error: \"Argument\" with \"list\" is illegal"); + } + else + { + /* The only real way to get data to the child process is + via the arguments (yes this is gross). */ + serve_argument (arg); + } + + do_cvs_command ("list", list); +} + void server_copy_file (file, update_dir, repository, newfile) char *file; @@ -4387,6 +4484,7 @@ REQ_LINE("expand-modules", serve_expand_modules, rq_optional), REQ_LINE("ci", serve_ci, rq_essential), REQ_LINE("co", serve_co, rq_essential), + REQ_LINE("list", serve_list, rq_optional), REQ_LINE("update", serve_update, rq_essential), REQ_LINE("diff", serve_diff, rq_optional), REQ_LINE("log", serve_log, rq_optional),