int history (int argc, char **argv) { int i, c; const char *fname = NULL; List *flist; if (argc == -1) usage (history_usg); since_rev = xstrdup (""); since_tag = xstrdup (""); backto = xstrdup (""); rec_types = xstrdup (""); getoptreset (); while ((c = getopt (argc, argv, "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:")) != -1) { switch (c) { case 'T': /* Tag list */ report_count++; tag_report++; break; case 'a': /* For all usernames */ all_users++; break; case 'c': report_count++; modified = 1; break; case 'e': report_count++; extract_all++; free (rec_types); rec_types = xstrdup (ALL_HISTORY_REC_TYPES); break; case 'l': /* Find Last file record */ last_entry = 1; break; case 'o': report_count++; v_checkout = 1; break; case 'w': /* Match Working Dir (CurDir) fields */ working = 1; break; case 'X': /* Undocumented debugging flag */ #ifdef DEBUG fname = optarg; #endif break; case 'D': /* Since specified date */ if (*since_rev || *since_tag || *backto) { error (0, 0, "date overriding rev/tag/backto"); *since_rev = *since_tag = *backto = '\0'; } since_date = Make_Date (optarg); break; case 'b': /* Since specified file/Repos */ if (since_date || *since_rev || *since_tag) { error (0, 0, "backto overriding date/rev/tag"); *since_rev = *since_tag = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (backto); backto = xstrdup (optarg); break; case 'f': /* For specified file */ save_file (NULL, optarg, NULL); break; case 'm': /* Full module report */ if (!module_report++) report_count++; /* fall through */ case 'n': /* Look for specified module */ save_module (optarg); break; case 'p': /* For specified directory */ save_file (optarg, NULL, NULL); break; case 'r': /* Since specified Tag/Rev */ if (since_date || *since_tag || *backto) { error (0, 0, "rev overriding date/tag/backto"); *since_tag = *backto = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (since_rev); since_rev = xstrdup (optarg); break; case 't': /* Since specified Tag/Rev */ if (since_date || *since_rev || *backto) { error (0, 0, "tag overriding date/marker/file/repos"); *since_rev = *backto = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (since_tag); since_tag = xstrdup (optarg); break; case 'u': /* For specified username */ save_user (optarg); break; case 'x': report_count++; extract++; { char *cp; for (cp = optarg; *cp; cp++) if (!strchr (ALL_HISTORY_REC_TYPES, *cp)) error (1, 0, "%c is not a valid report type", *cp); } free (rec_types); rec_types = xstrdup (optarg); break; case 'z': tz_local = (optarg[0] == 'l' || optarg[0] == 'L') && (optarg[1] == 't' || optarg[1] == 'T') && !optarg[2]; if (tz_local) tz_name = optarg; else { /* * Convert a known time with the given timezone to time_t. * Use the epoch + 23 hours, so timezones east of GMT work. */ struct timespec t; char *buf = Xasprintf ("1/1/1970 23:00 %s", optarg); if (get_date (&t, buf, NULL)) { /* * Convert to seconds east of GMT, removing the * 23-hour offset mentioned above. */ tz_seconds_east_of_GMT = (time_t)23 * 60 * 60 - t.tv_sec; tz_name = optarg; } else error (0, 0, "%s is not a known time zone", optarg); free (buf); } break; case '?': default: usage (history_usg); break; } } argc -= optind; argv += optind; for (i = 0; i < argc; i++) save_file (NULL, argv[i], NULL); /* ================ Now analyze the arguments a bit */ if (!report_count) v_checkout++; else if (report_count > 1) error (1, 0, "Only one report type allowed from: \"-Tcomxe\"."); #ifdef CLIENT_SUPPORT if (current_parsed_root->isremote) { struct file_list_str *f1; char **mod; /* We're the client side. Fire up the remote server. */ start_server (); ign_setup (); if (tag_report) send_arg ("-T"); if (all_users) send_arg ("-a"); if (modified) send_arg ("-c"); if (last_entry) send_arg ("-l"); if (v_checkout) send_arg ("-o"); if (working) send_arg ("-w"); if (fname) option_with_arg ("-X", fname); if (since_date) client_senddate (since_date); if (backto[0] != '\0') option_with_arg ("-b", backto); for (f1 = file_list; f1 < &file_list[file_count]; ++f1) { if (f1->l_file[0] == '*') option_with_arg ("-p", f1->l_file + 1); else option_with_arg ("-f", f1->l_file); } if (module_report) send_arg ("-m"); for (mod = mod_list; mod < &mod_list[mod_count]; ++mod) option_with_arg ("-n", *mod); if (*since_rev) option_with_arg ("-r", since_rev); if (*since_tag) option_with_arg ("-t", since_tag); for (mod = user_list; mod < &user_list[user_count]; ++mod) option_with_arg ("-u", *mod); if (extract_all) send_arg ("-e"); if (extract) option_with_arg ("-x", rec_types); option_with_arg ("-z", tz_name); send_to_server ("history\012", 0); return get_responses_and_close (); } #endif if (all_users) save_user (""); if (mod_list) expand_modules (); if (tag_report) { if (!strchr (rec_types, 'T')) { rec_types = xrealloc (rec_types, strlen (rec_types) + 5); (void) strcat (rec_types, "T"); } } else if (extract || extract_all) { if (user_list) user_sort++; } else if (modified) { free (rec_types); rec_types = xstrdup ("MAR"); /* * If the user has not specified a date oriented flag ("Since"), sort * by Repository/file before date. Default is "just" date. */ if (last_entry || (!since_date && !*since_rev && !*since_tag && !*backto)) { repos_sort++; file_sort++; /* * If we are not looking for last_modified and the user specified * one or more users to look at, sort by user before filename. */ if (!last_entry && user_list) user_sort++; } } else if (module_report) { free (rec_types); rec_types = xstrdup (last_entry ? "OMAR" : ALL_HISTORY_REC_TYPES); module_sort++; repos_sort++; file_sort++; working = 0; /* User's workdir doesn't count here */ } else /* Must be "checkout" or default */ { free (rec_types); rec_types = xstrdup ("OF"); /* See comments in "modified" above */ if (!last_entry && user_list) user_sort++; if (last_entry || (!since_date && !*since_rev && !*since_tag && !*backto)) file_sort++; } /* If no users were specified, use self (-a saves a universal ("") user) */ if (!user_list) save_user (getcaller ()); /* If we're looking back to a Tag value, must consider "Tag" records */ if (*since_tag && !strchr (rec_types, 'T')) { rec_types = xrealloc (rec_types, strlen (rec_types) + 5); (void) strcat (rec_types, "T"); } if (fname) { Node *p; flist = getlist (); p = getnode (); p->type = FILES; p->key = Xasprintf ("%s/%s/%s", current_parsed_root->directory, CVSROOTADM, fname); addnode (flist, p); } else { char *pat; if (config->HistorySearchPath) pat = config->HistorySearchPath; else pat = Xasprintf ("%s/%s/%s", current_parsed_root->directory, CVSROOTADM, CVSROOTADM_HISTORY); flist = find_files (NULL, pat); if (pat != config->HistorySearchPath) free (pat); } read_hrecs (flist); if (hrec_count > 0) qsort (hrec_head, hrec_count, sizeof (struct hrec), sort_order); report_hrecs (); if (since_date != NULL) free (since_date); free (since_rev); free (since_tag); free (backto); free (rec_types); return 0; }
int ls (int argc, char **argv) { int c; int err = 0; is_rls = strcmp (cvs_cmd_name, "rls") == 0; if (argc == -1) usage (ls_usage); entries_format = false; long_format = false; show_tag = NULL; show_date = NULL; tag_validated = false; recurse = false; ls_prune_dirs = false; show_dead_revs = false; getoptreset (); while ((c = getopt (argc, argv, #ifdef SERVER_SUPPORT server_active ? "qdelr:D:PR" : #endif /* SERVER_SUPPORT */ "delr:D:RP" )) != -1) { switch (c) { #ifdef SERVER_SUPPORT case 'q': if (server_active) { error (0, 0, "`%s ls -q' is deprecated. Please use the global `-q' option instead.", program_name); quiet = true; } else usage (ls_usage); break; #endif /* SERVER_SUPPORT */ case 'd': show_dead_revs = true; break; case 'e': entries_format = true; break; case 'l': long_format = true; break; case 'r': parse_tagdate (&show_tag, &show_date, optarg); break; case 'D': if (show_date) free (show_date); show_date = Make_Date (optarg); break; case 'P': ls_prune_dirs = true; break; case 'R': recurse = true; break; case '?': default: usage (ls_usage); break; } } argc -= optind; argv += optind; if (entries_format && long_format) { error (0, 0, "`-e' & `-l' are mutually exclusive."); usage (ls_usage); } 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 (is_rls ? !(supported_request ("rlist") || supported_request ("ls")) : !supported_request ("list")) error (1, 0, "server does not support %s", cvs_cmd_name); if (quiet && !supported_request ("global-list-quiet")) send_arg ("-q"); if (entries_format) send_arg ("-e"); if (long_format) send_arg ("-l"); if (ls_prune_dirs) send_arg ("-P"); if (recurse) send_arg ("-R"); if (show_dead_revs) send_arg ("-d"); if (show_tag) option_with_arg ("-r", show_tag); if (show_date) client_senddate (show_date); send_arg ("--"); if (is_rls) { int i; for (i = 0; i < argc; i++) send_arg (argv[i]); if (supported_request ("rlist")) send_to_server ("rlist\012", 0); else /* For backwards compatibility with CVSNT... */ send_to_server ("ls\012", 0); } else { /* Setting this means, I think, that any empty directories created * by the server will be deleted by the client. Since any dirs * created at all by ls should remain empty, this should cause any * dirs created by the server for the ls command to be deleted. */ client_prune_dirs = 1; /* I explicitly decide not to send contents here. We *could* let * the user pull status information with this command, but why * don't they just use update or status? */ send_files (argc, argv, !recurse, 0, SEND_NO_CONTENTS); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("list\012", 0); } err = get_responses_and_close (); return err; } #endif if (is_rls) { 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; /* Frontends like to do 'ls -q /', so we support it explicitly. */ if (!strcmp (mod,"/")) { *mod='\0'; } err += do_module (db, mod, MISC, "Listing", ls_proc, NULL, 0, 0, 0, 0, NULL); free (mod); } } else { /* should be ".", but do_recursion() fails this: assert ( strstr ( repository, "/./" ) == NULL ); */ char *topmod = xstrdup (""); err += do_module (db, topmod, MISC, "Listing", ls_proc, NULL, 0, 0, 0, 0, NULL); free (topmod); } close_module (db); } else ls_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, 0, NULL, NULL); return err; }