Exemplo n.º 1
0
int diff (int argc, char **argv)
{
    char tmp[50];
    int c, err = 0;
    int local = 0;
    int which;
    int option_index;

    is_rcs = (strcmp (command_name, "rcsfile") == 0);

    if (argc == -1)
        usage (diff_usage);

    have_rev1_label = have_rev2_label = 0;

    /*
     * Note that we catch all the valid arguments here, so that we can
     * intercept the -r arguments for doing revision diffs; and -l/-R for a
     * non-recursive/recursive diff.
     */

    /* Clean out our global variables (multiroot can call us multiple
       times and the server can too, if the client sends several
       diff commands).  */
    if (opts == NULL)
    {
        opts_allocated = 1;
        opts = (char*)xmalloc (opts_allocated);
    }
    opts[0] = '\0';
    diff_rev1 = NULL;
    diff_rev2 = NULL;
    diff_date1 = NULL;
    diff_date2 = NULL;

    optind = 0;
    while ((c = getopt_long (argc, argv,
                             "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:",
                             longopts, &option_index)) != -1)
    {
        switch (c)
        {
        case 'a':
        case 'b':
        case 'c':
        case 'd':
        case 'e':
        case 'f':
        case 'h':
        case 'i':
        case 'n':
        case 'p':
        case 's':
        case 't':
        case 'u':
        case 'w':
        case 'y':
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case 'B':
        case 'H':
        case 'T':
            (void) sprintf (tmp, " -%c", (char) c);
            allocate_and_strcat (&opts, &opts_allocated, tmp);
            break;
        case 'L':
            if (have_rev1_label++)
                if (have_rev2_label++)
                {
                    error (0, 0, "extra -L arguments ignored");
                    break;
                }

            allocate_and_strcat (&opts, &opts_allocated, " -L");
            allocate_and_strcat (&opts, &opts_allocated, optarg);
            break;
        case 'C':
        case 'F':
        case 'I':
        case 'U':
        case 'V':
        case 'W':
            (void) sprintf (tmp, " -%c", (char) c);
            allocate_and_strcat (&opts, &opts_allocated, tmp);
            allocate_and_strcat (&opts, &opts_allocated, optarg);
            break;
        case 131:
            /* --ifdef.  */
            allocate_and_strcat (&opts, &opts_allocated, " --ifdef=");
            allocate_and_strcat (&opts, &opts_allocated, optarg);
            break;
        case 129:
        case 130:
        case 132:
        case 133:
        case 134:
        case 135:
        case 136:
        case 137:
        case 138:
        case 139:
        case 140:
        case 141:
        case 142:
        case 143:
        case 144:
        case 145:
        case 146:
            allocate_and_strcat (&opts, &opts_allocated, " --");
            allocate_and_strcat (&opts, &opts_allocated,
                                 longopts[option_index].name);
            if (longopts[option_index].has_arg == 1
                    || (longopts[option_index].has_arg == 2
                        && optarg != NULL))
            {
                allocate_and_strcat (&opts, &opts_allocated, "=");
                allocate_and_strcat (&opts, &opts_allocated, optarg);
            }
            break;
        case 'R':
            local = 0;
            break;
        case 'l':
            local = 1;
            break;
        case 'k':
            if (options)
                xfree (options);
            options = RCS_check_kflag (optarg,true,true);
            break;
        case 'r':
            if (diff_rev2 != NULL || diff_date2 != NULL)
                error (1, 0,
                       "no more than two revisions/dates can be specified");
            if (diff_rev1 != NULL || diff_date1 != NULL)
                diff_rev2 = optarg;
            else
                diff_rev1 = optarg;
            break;
        case 'D':
            if (diff_rev2 != NULL || diff_date2 != NULL)
                error (1, 0,
                       "no more than two revisions/dates can be specified");
            if (diff_rev1 != NULL || diff_date1 != NULL)
                diff_date2 = Make_Date (optarg);
            else
                diff_date1 = Make_Date (optarg);
            break;
        case 'N':
            empty_files = 1;
            break;
        case '?':
        default:
            usage (diff_usage);
            break;
        }
    }
    argc -= optind;
    argv += optind;

    /* make sure options is non-null */
    if (!options)
        options = xstrdup ("");

    if (!is_rcs && current_parsed_root->isremote)
    {
        if (local)
            send_arg("-l");
        if (empty_files)
            send_arg("-N");
        send_option_string (opts);
        if (options[0] != '\0')
            option_with_arg ("-k", options);
        if (diff_rev1)
            option_with_arg ("-r", diff_rev1);
        if (diff_date1)
            client_senddate (diff_date1);
        if (diff_rev2)
            option_with_arg ("-r", diff_rev2);
        if (diff_date2)
            client_senddate (diff_date2);

        send_arg("--");
        /* Send the current files unless diffing two revs from the archive */
        if (diff_rev2 == NULL && diff_date2 == NULL)
            send_files (argc, argv, local, 0, 0);
        else
            send_files (argc, argv, local, 0, SEND_NO_CONTENTS);

        send_file_names (argc, argv, SEND_EXPAND_WILD);

        send_to_server ("diff\n", 0);
        err = get_responses_and_close ();
        xfree (options);
        options = NULL;
        return (err);
    }

    if(is_rcs)
    {
        int n;

        if(!argc)
            usage(diff_usage);

        for(n=0; n<argc; n++)
        {
            struct file_info finfo = {0};
            const char *name;
            char *tmp = find_rcs_filename(argv[n]);

            if(!tmp)
                error(1,ENOENT,"%s",argv[n]);

            finfo.fullname=fullpathname(tmp, &name);
            finfo.file = xstrdup(name);
            char *ff = xstrdup(finfo.fullname);
            finfo.update_dir = ff;
            ff[(name-finfo.fullname)-1]='\0';

            finfo.rcs = RCS_fopen(finfo.fullname);
            if(finfo.rcs)
            {
                ff = (char*)finfo.fullname;
                ff[strlen(finfo.fullname)-2]='\0';
                ff = (char*)finfo.file;
                ff[strlen(finfo.file)-2]='\0';
                err+=diff_fileproc(NULL,&finfo);
                freercsnode(&finfo.rcs);
            }
            else
            {
                error(1,ENOENT,"%s",tmp);
                err++;
            }
            xfree(finfo.fullname);
            xfree(finfo.file);
            xfree(finfo.update_dir);
            xfree(tmp);
        }
    }
    else
    {
        if (diff_rev1 != NULL)
            tag_check_valid (diff_rev1, argc, argv, local, 0, "");
        if (diff_rev2 != NULL)
            tag_check_valid (diff_rev2, argc, argv, local, 0, "");

        which = W_LOCAL;
        if (diff_rev1 != NULL || diff_date1 != NULL)
            which |= W_REPOS;

        /* start the recursion processor */
        err = start_recursion (diff_fileproc, diff_filesdoneproc, (PREDIRENTPROC) NULL, diff_dirproc,
                               diff_dirleaveproc, NULL, argc, argv, local,
                               which, 0, 1, (char *) NULL, NULL, 1, verify_read, diff_rev1);
    }

    /* clean up */
    xfree (options);
    options = NULL;

    if (diff_date1 != NULL)
        xfree (diff_date1);
    if (diff_date2 != NULL)
        xfree (diff_date2);

    return (err);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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;
}