Exemple #1
0
static int
ls_print_dir (Node *p, void *closure)
{
    static bool printed = false;

    if (recurse && !(ls_prune_dirs && list_isempty (p->data)))
    {
        /* Keep track of whether we've printed.  If we have, then put a blank
         * line before directory headers, to separate the header from the
         * listing of the previous directory.
         */
        if (printed)
            cvs_output ("\n", 1);
        else
            printed = true;

        if (!strcmp (p->key, ""))
            cvs_output (".", 1);
        else
	    cvs_output (p->key, 0);
        cvs_output (":\n", 2);
    }
    walklist (p->data, ls_print, NULL);
    return 0;
}
Exemple #2
0
static void
RCS_output_diff_options (int diff_argc, char * const *diff_argv,
			 const char *rev1, const char *rev2,
                         const char *workfile)
{
    int i;
    
    cvs_output ("diff", 0);
    for (i = 0; i < diff_argc; i++)
    {
        cvs_output (" ", 1);
	cvs_output (quotearg_style (shell_quoting_style, diff_argv[i]), 0);
    }
    cvs_output (" -r", 3);
    cvs_output (rev1, 0);

    if (rev2)
    {
	cvs_output (" -r", 3);
	cvs_output (rev2, 0);
    }
    else
    {
	assert (workfile != NULL);
	cvs_output (" ", 1);
	cvs_output (workfile, 0);
    }
    cvs_output ("\n", 1);
}
Exemple #3
0
static int
ls_print (Node *p, void *closure)
{
    if (long_format)
    {
	struct long_format_data *data = p->data;
	cvs_output_tagged ("text", data->header);
	if (data->time)
	    cvs_output_tagged ("date", data->time);
	if (data->footer)
	    cvs_output_tagged ("text", data->footer);
	cvs_output_tagged ("newline", NULL);
    }
    else
	cvs_output (p->data, 0);
    return 0;
}
Exemple #4
0
int
yesno ()
{
  int c;
  int rv;

#ifdef CVSGUI_PIPE
	char *response;

	cvs_output("\n", 1);
	response = getenv("CVSLIB_YESNO");
	if(response != 0L)
		return strcmp(response, "yes") == 0;
#endif /* CVSGUI_PIPE*/

  fflush (stderr);
  fflush (stdout);
  c = getchar ();
  rv = (c == 'y') || (c == 'Y');
  while (c != EOF && c != '\n')
    c = getchar ();

  return rv;
}
Exemple #5
0
/* ARGSUSED */
static int diff_fileproc (void *callerdat, struct file_info *finfo)
{
    int status, err = 2;		/* 2 == trouble, like rcsdiff */
    Vers_TS *vers;
    enum diff_file empty_file = DIFF_DIFFERENT;
    char *tmp;
    char *fname;
    char *label1;
    char *label2;
    char *default_branch;

    /* Initialize these solely to avoid warnings from gcc -Wall about
       variables that might be used uninitialized.  */
    tmp = NULL;
    fname = NULL;

    user_file_rev = 0;
    vers = Version_TS (finfo, NULL, NULL, NULL, 1, 0, 0);
    if(vers->tag && RCS_isbranch(finfo->rcs, vers->tag))
        default_branch = vers->tag;
    else
        default_branch = NULL;

    if (diff_rev2 != NULL || diff_date2 != NULL)
    {
        /* Skip all the following checks regarding the user file; we're
           not using it.  */
    }
    else if (vers->vn_user == NULL)
    {
        /* The file does not exist in the working directory.  */
        if ((diff_rev1 != NULL || diff_date1 != NULL)
                && vers->srcfile != NULL)
        {
            /* The file does exist in the repository.  */
            if (empty_files)
                empty_file = DIFF_REMOVED;
            else
            {
                int exists;

                exists = 0;
                /* special handling for TAG_HEAD */
                if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
                {
                    char *head =
                        (vers->vn_rcs == NULL
                         ? NULL
                         : RCS_branch_head (vers->srcfile, vers->vn_rcs));
                    exists = head != NULL;
                    if (head != NULL)
                        xfree (head);
                }
                else
                {
                    Vers_TS *xvers;

                    xvers = Version_TS (finfo, NULL, diff_rev1?diff_rev1:default_branch, diff_date1,
                                        1, 0, 0);
                    exists = xvers->vn_rcs != NULL;
                    freevers_ts (&xvers);
                }
                if (exists)
                    error (0, 0,
                           "%s no longer exists, no comparison available",
                           fn_root(finfo->fullname));
                freevers_ts (&vers);
                diff_mark_errors (err);
                return (err);
            }
        }
        else
        {
            error (0, 0, "I know nothing about %s", fn_root(finfo->fullname));
            freevers_ts (&vers);
            diff_mark_errors (err);
            return (err);
        }
    }
    else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
    {
        if (empty_files)
            empty_file = DIFF_ADDED;
        else
        {
            error (0, 0, "%s is a new entry, no comparison available",
                   fn_root(finfo->fullname));
            freevers_ts (&vers);
            diff_mark_errors (err);
            return (err);
        }
    }
    else if (vers->vn_user[0] == '-')
    {
        if (empty_files)
            empty_file = DIFF_REMOVED;
        else
        {
            error (0, 0, "%s was removed, no comparison available",
                   fn_root(finfo->fullname));
            freevers_ts (&vers);
            diff_mark_errors (err);
            return (err);
        }
    }
    else
    {
        if (vers->vn_rcs == NULL && vers->srcfile == NULL)
        {
            error (0, 0, "cannot find revision control file for %s",
                   fn_root(finfo->fullname));
            freevers_ts (&vers);
            diff_mark_errors (err);
            return (err);
        }
        else
        {
            if (vers->ts_user == NULL)
            {
                error (0, 0, "cannot find %s", fn_root(finfo->fullname));
                freevers_ts (&vers);
                diff_mark_errors (err);
                return (err);
            }
            else if (!strcmp (vers->ts_user, vers->ts_rcs))
            {
                /* The user file matches some revision in the repository
                   Diff against the repository (for remote CVS, we might not
                   have a copy of the user file around).  */
                user_file_rev = vers->vn_user;
            }
        }
    }
    empty_file = diff_file_nodiff (finfo, vers, empty_file, default_branch);
    if (empty_file == DIFF_SAME || empty_file == DIFF_ERROR)
    {
        freevers_ts (&vers);
        if (empty_file == DIFF_SAME)
        {
            /* In the server case, would be nice to send a "Checked-in"
               response, so that the client can rewrite its timestamp.
               server_checked_in by itself isn't the right thing (it
               needs a server_register), but I'm not sure what is.
               It isn't clear to me how "cvs status" handles this (that
               is, for a client which sends Modified not Is-modified to
               "cvs status"), but it does.  */
            return (0);
        }
        else
        {
            diff_mark_errors (err);
            return (err);
        }
    }

    if (empty_file == DIFF_DIFFERENT)
    {
        int dead1, dead2;

        if (use_rev1 == NULL)
            dead1 = 0;
        else
            dead1 = RCS_isdead (vers->srcfile, use_rev1);
        if (use_rev2 == NULL)
            dead2 = 0;
        else
            dead2 = RCS_isdead (vers->srcfile, use_rev2);

        if (dead1 && dead2)
        {
            freevers_ts (&vers);
            return (0);
        }
        else if (dead1)
        {
            if (empty_files)
                empty_file = DIFF_ADDED;
            else
            {
                error (0, 0, "%s is a new entry, no comparison available",
                       fn_root(finfo->fullname));
                freevers_ts (&vers);
                diff_mark_errors (err);
                return (err);
            }
        }
        else if (dead2)
        {
            if (empty_files)
                empty_file = DIFF_REMOVED;
            else
            {
                error (0, 0, "%s was removed, no comparison available",
                       fn_root(finfo->fullname));
                freevers_ts (&vers);
                diff_mark_errors (err);
                return (err);
            }
        }
    }

    /* Output an "Index:" line for patch to use */
    if(!is_rcs)
    {
        cvs_output ("Index: ", 0);
        cvs_output (fn_root(finfo->fullname), 0);
        cvs_output ("\n", 1);
    }

    /* Set up file labels appropriate for compatibility with the Larry Wall
     * implementation of patch if the user didn't specify.  This is irrelevant
     * according to the POSIX.2 specification.
     */
    label1 = NULL;
    label2 = NULL;
    if (!have_rev1_label)
    {
        if (empty_file == DIFF_ADDED)
        {
            TRACE(3,"diff_fileproc(); !have_rev1_label; empty_file == DIFF_ADDED make_file_label(is_rcs=%d)",is_rcs);

            label1 =
                make_file_label (DEVNULL, NULL, NULL, is_rcs);
        }
        else
        {
            TRACE(3,"diff_fileproc(); !have_rev1_label; empty_file != DIFF_ADDED make_file_label(is_rcs=%d)",is_rcs);

            label1 =
                make_file_label (is_rcs?fn_root(finfo->file):fn_root(finfo->fullname), use_rev1, vers ? vers->srcfile : NULL, is_rcs);
        }
    }

    if (!have_rev2_label)
    {
        if (empty_file == DIFF_REMOVED)
        {
            TRACE(3,"diff_fileproc(); !have_rev2_label; empty_file == DIFF_REMOVED make_file_label(is_rcs=%d)",is_rcs);

            label2 =
                make_file_label (DEVNULL, NULL, NULL, is_rcs);
        }
        else
        {
            TRACE(3,"diff_fileproc(); !have_rev2_label; empty_file != DIFF_REMOVED make_file_label(is_rcs=%d)",is_rcs);

            label2 =
                make_file_label (is_rcs?fn_root(finfo->file):fn_root(finfo->fullname), use_rev2, vers ? vers->srcfile : NULL, is_rcs);
        }
    }

    if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
    {
        /* This is fullname, not file, possibly despite the POSIX.2
         * specification, because that's the way all the Larry Wall
         * implementations of patch (are there other implementations?) want
         * things and the POSIX.2 spec appears to leave room for this.
         */
        cvs_output ("\
===================================================================\n\
RCS file: ", 0);
        cvs_output (fn_root(finfo->fullname), 0);
        cvs_output ("\n", 1);

        cvs_output ("diff -N ", 0);
        cvs_output (fn_root(finfo->fullname), 0);
        cvs_output ("\n", 1);

        if (empty_file == DIFF_ADDED)
        {
            if (use_rev2 == NULL)
                status = diff_exec (DEVNULL, finfo->file, label1, label2, opts, RUN_TTY);
            else
            {
                int retcode;

                tmp = cvs_temp_name ();
                retcode = RCS_checkout (vers->srcfile, (char *) NULL,
                                        use_rev2, (char *) NULL,
                                        vers->options,
                                        tmp, (RCSCHECKOUTPROC) NULL,
                                        (void *) NULL, NULL);
                if (retcode != 0)
                {
                    diff_mark_errors (err);
                    return err;
                }

                status = diff_exec (DEVNULL, tmp, label1, label2, opts, RUN_TTY);
            }
        }
        else
        {
            int retcode;

            tmp = cvs_temp_name ();
            retcode = RCS_checkout (vers->srcfile, (char *) NULL,
                                    use_rev1, (char *) NULL,
                                    *options ? options : vers->options,
                                    tmp, (RCSCHECKOUTPROC) NULL,
                                    (void *) NULL, NULL);
            if (retcode != 0)
            {
                diff_mark_errors (err);
                return err;
            }

            status = diff_exec (tmp, DEVNULL, label1, label2, opts, RUN_TTY);
        }
    }
Exemple #6
0
/* Diff revisions and/or files.  OPTS controls the format of the diff
   (it contains options such as "-w -c", &c), or "" for the default.
   OPTIONS controls keyword expansion, as a string starting with "-k",
   or "" to use the default.  REV1 is the first revision to compare
   against; it must be non-NULL.  If REV2 is non-NULL, compare REV1
   and REV2; if REV2 is NULL compare REV1 with the file in the working
   directory, whose name is WORKFILE.  LABEL1 and LABEL2 are default
   file labels, and (if non-NULL) should be added as -L options
   to diff.  Output goes to stdout.

   Return value is 0 for success, -1 for a failure which set errno,
   or positive for a failure which printed a message on stderr.

   This used to exec rcsdiff, but now calls RCS_checkout and diff_exec.

   An issue is what timezone is used for the dates which appear in the
   diff output.  rcsdiff uses the -z flag, which is not presently
   processed by CVS diff, but I'm not sure exactly how hard to worry
   about this--any such features are undocumented in the context of
   CVS, and I'm not sure how important to users.  */
int
RCS_exec_rcsdiff (RCSNode *rcsfile, int diff_argc,
		  char * const *diff_argv, const char *options,
                  const char *rev1, const char *rev1_cache, const char *rev2,
                  const char *label1, const char *label2, const char *workfile)
{
    char *tmpfile1 = NULL;
    char *tmpfile2 = NULL;
    const char *use_file1, *use_file2;
    int status, retval;


    cvs_output ("\
===================================================================\n\
RCS file: ", 0);
    cvs_output (rcsfile->print_path, 0);
    cvs_output ("\n", 1);

    /* Historically, `cvs diff' has expanded the $Name keyword to the
       empty string when checking out revisions.  This is an accident,
       but no one has considered the issue thoroughly enough to determine
       what the best behavior is.  Passing NULL for the `nametag' argument
       preserves the existing behavior. */

    cvs_output ("retrieving revision ", 0);
    cvs_output (rev1, 0);
    cvs_output ("\n", 1);

    if (rev1_cache != NULL)
	use_file1 = rev1_cache;
    else
    {
	tmpfile1 = cvs_temp_name();
	status = RCS_checkout (rcsfile, NULL, rev1, NULL, options, tmpfile1,
	                       NULL, NULL);
	if (status > 0)
	{
	    retval = status;
	    goto error_return;
	}
	else if (status < 0)
	{
	    error( 0, errno,
	           "cannot check out revision %s of %s", rev1, rcsfile->path );
	    retval = 1;
	    goto error_return;
	}
	use_file1 = tmpfile1;
    }

    if (rev2 == NULL)
    {
	assert (workfile != NULL);
	use_file2 = workfile;
    }
    else
    {
	tmpfile2 = cvs_temp_name ();
	cvs_output ("retrieving revision ", 0);
	cvs_output (rev2, 0);
	cvs_output ("\n", 1);
	status = RCS_checkout (rcsfile, NULL, rev2, NULL, options,
			       tmpfile2, NULL, NULL);
	if (status > 0)
	{
	    retval = status;
	    goto error_return;
	}
	else if (status < 0)
	{
	    error (0, errno,
		   "cannot check out revision %s of %s", rev2, rcsfile->path);
	    return 1;
	}
	use_file2 = tmpfile2;
    }

    RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile);
    status = diff_exec (use_file1, use_file2, label1, label2,
			diff_argc, diff_argv, RUN_TTY);
    if (status >= 0)
    {
	retval = status;
	goto error_return;
    }
    else if (status < 0)
    {
	error (0, errno,
	       "cannot diff %s and %s", use_file1, use_file2);
	retval = 1;
	goto error_return;
    }

 error_return:
    {
	/* Call CVS_UNLINK() below rather than unlink_file to avoid the check
	 * for noexec.
	 */
	if( tmpfile1 != NULL )
	{
	    if( CVS_UNLINK( tmpfile1 ) < 0 )
	    {
		if( !existence_error( errno ) )
		    error( 0, errno, "cannot remove temp file %s", tmpfile1 );
	    }
	    free( tmpfile1 );
	}
	if( tmpfile2 != NULL )
	{
	    if( CVS_UNLINK( tmpfile2 ) < 0 )
	    {
		if( !existence_error( errno ) )
		    error( 0, errno, "cannot remove temp file %s", tmpfile2 );
	    }
	    free (tmpfile2);
	}
    }

    return retval;
}
Exemple #7
0
int
RCS_merge (RCSNode *rcs, const char *path, const char *workfile,
           const char *options, const char *rev1, const char *rev2)
{
    char *xrev1, *xrev2;
    char *tmp1, *tmp2;
    char *diffout = NULL;
    int retval;

    if (options != NULL && options[0] != '\0')
      assert (options[0] == '-' && options[1] == 'k');

    cvs_output ("RCS file: ", 0);
    cvs_output (rcs->print_path, 0);
    cvs_output ("\n", 1);

    /* Calculate numeric revision numbers from rev1 and rev2 (may be
       symbolic).
       FIXME - No they can't.  Both calls to RCS_merge are passing in
       numeric revisions.  */
    xrev1 = RCS_gettag (rcs, rev1, 0, NULL);
    xrev2 = RCS_gettag (rcs, rev2, 0, NULL);
    assert (xrev1 && xrev2);

    /* Check out chosen revisions.  The error message when RCS_checkout
       fails is not very informative -- it is taken verbatim from RCS 5.7,
       and relies on RCS_checkout saying something intelligent upon failure. */
    cvs_output ("retrieving revision ", 0);
    cvs_output (xrev1, 0);
    cvs_output ("\n", 1);

    tmp1 = cvs_temp_name();
    if (RCS_checkout (rcs, NULL, xrev1, rev1, options, tmp1, NULL, NULL))
    {
	cvs_outerr ("rcsmerge: co failed\n", 0);
	exit (EXIT_FAILURE);
    }

    cvs_output ("retrieving revision ", 0);
    cvs_output (xrev2, 0);
    cvs_output ("\n", 1);

    tmp2 = cvs_temp_name();
    if (RCS_checkout (rcs, NULL, xrev2, rev2, options, tmp2, NULL, NULL))
    {
	cvs_outerr ("rcsmerge: co failed\n", 0);
	exit (EXIT_FAILURE);
    }

    /* Merge changes. */
    cvs_output ("Merging differences between ", 0);
    cvs_output (xrev1, 0);
    cvs_output (" and ", 0);
    cvs_output (xrev2, 0);
    cvs_output (" into ", 0);
    cvs_output (workfile, 0);
    cvs_output ("\n", 1);

    /* Remember that the first word in the `call_diff_setup' string is used now
       only for diagnostic messages -- CVS no longer forks to run diff3. */
    diffout = cvs_temp_name();
    call_diff_setup ("diff3", 0, NULL);
    call_diff_add_arg ("-E");
    call_diff_add_arg ("-am");

    call_diff_add_arg ("-L");
    call_diff_add_arg (workfile);
    call_diff_add_arg ("-L");
    call_diff_add_arg (xrev1);
    call_diff_add_arg ("-L");
    call_diff_add_arg (xrev2);

    call_diff_add_arg ("--");
    call_diff_add_arg (workfile);
    call_diff_add_arg (tmp1);
    call_diff_add_arg (tmp2);

    retval = call_diff3 (diffout);

    if (retval == 1)
	cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);
    else if (retval == 2)
	exit (EXIT_FAILURE);

    if (diffout)
	copy_file (diffout, workfile);

    /* Clean up. */
    {
	int save_noexec = noexec;
	noexec = 0;
	if (unlink_file (tmp1) < 0)
	{
	    if (!existence_error (errno))
		error (0, errno, "cannot remove temp file %s", tmp1);
	}
	free (tmp1);
	if (unlink_file (tmp2) < 0)
	{
	    if (!existence_error (errno))
		error (0, errno, "cannot remove temp file %s", tmp2);
	}
	free (tmp2);
	if (diffout)
	{
	    if (unlink_file (diffout) < 0)
	    {
		if (!existence_error (errno))
		    error (0, errno, "cannot remove temp file %s", diffout);
	    }
	    free (diffout);
	}
	free (xrev1);
	free (xrev2);
	noexec = save_noexec;
    }

    return retval;
}
Exemple #8
0
static void
call_diff_write_stdout (const char *text)
{
    cvs_output (text, 0);
}
Exemple #9
0
static void
call_diff_write_output (const char *text, size_t len)
{
    if (len > 0)
	cvs_output (text, len);
}
Exemple #10
0
/* Runs the user-defined verification script as part of the commit or import 
   process.  This verification is meant to be run whether or not the user 
   included the -m atribute.  unlike the do_editor function, this is 
   independant of the running of an editor for getting a message.
 */
int do_verify (char **message, const char *repository)
{
    FILE *fp;
    char *fname = NULL;
    int retcode = 0;
    int len;
	char boughtsuite[100];

    if (current_parsed_root->isremote)
	/* The verification will happen on the server.  */
		return 0;

    /* FIXME? Do we really want to skip this on noexec?  What do we do
       for the other administrative files?  */
    if (noexec)
		return 0;
	
    /* If there's no message, then we have nothing to verify.  Can this
       case happen?  And if so why would we print a message?  */
    if (message == NULL)
    {
		cvs_output ("No message to verify\n", 0);
		return 0;
    }

    /* open a temporary file, write the message to the 
       temp file, and close the file.  */

    if ((fp = cvs_temp_file (&fname)) == NULL)
		error (1, errno, "cannot create temporary file %s", fname);
    else
    {
		fprintf (fp, "%s", *message);
		if ((*message)[0] == '\0' ||
			(*message)[strlen (*message) - 1] != '\n')
			fprintf (fp, "%s", "\n");
		if (fclose (fp) == EOF)
			error (1, errno, "%s", fname);

		/* Run the verify message  */

		if (repository != NULL)
		{
			verifymsg_param_t args;
			args.directory = Short_Repository(repository);
			args.filename = fname;

			TRACE(3,"run verifymsg trigger");
			retcode = run_trigger(&args,verifymsg_proc);

			if(!retcode && reread_log_after_verify)
			{
				if((fp=fopen(fname,"r"))==NULL)
					error(1, errno, "Couldn't reread message file");
				fseek(fp,0,SEEK_END);
				len = ftell(fp);
				fseek(fp,0,SEEK_SET);
				*message = (char*)xmalloc(len+1);
				if(!*message)
					error(1,errno,"Out of memory rereading message");
				len = fread(*message, 1, len, fp);
				if(len < 0)
					error(1, errno, "Couldn't reread message file");
				(*message)[len]='\0';
				if (fclose (fp) == EOF)
	    				error (1, errno, "Couldn't close %s", fname);
			}
#ifdef _WIN32
#if (CVSNT_SPECIAL_BUILD_FLAG != 0)
	if (strcasecmp(CVSNT_SPECIAL_BUILD,"Suite")!=0)
#endif
	{
			if (message!=NULL)
			{
				if (strstr(*message,"Committed on the Free edition of March Hare Software CVSNT")==NULL)
				{
				    if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","HaveBoughtSuite",boughtsuite,sizeof(boughtsuite)))
						strcpy(boughtsuite,"no");
					if (strcasecmp(boughtsuite,"yes"))
					{
						len=strlen(*message);
						*message=(char *)xrealloc(*message,len+400);
						strcat(*message,"\nCommitted on the Free edition of March Hare Software CVSNT Server.\nUpgrade to CVS Suite for more features and support:\nhttp://march-hare.com/cvsnt/");
					}
				}
			}
    }
#endif
		}

		/* Delete the temp file  */

		if (unlink_file (fname) < 0)
			error (0, errno, "cannot remove %s", fname);
		xfree (fname);
    }
	return retcode;
}