cvs-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Cvs-cvs] Changes to ccvs/src/classify.c [signed-commits2]


From: Derek Robert Price
Subject: [Cvs-cvs] Changes to ccvs/src/classify.c [signed-commits2]
Date: Tue, 22 Nov 2005 20:46:57 -0500

Index: ccvs/src/classify.c
diff -u /dev/null ccvs/src/classify.c:1.37.4.1
--- /dev/null   Wed Nov 23 01:46:57 2005
+++ ccvs/src/classify.c Wed Nov 23 01:46:53 2005
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
+ *                                  and others.
+ *
+ * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
+ * Portions Copyright (C) 1989-1992, Brian Berliner
+ * 
+ * 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.
+ * 
+ */
+
+#include "cvs.h"
+
+static void sticky_ck (struct file_info *finfo, int aflag,
+                             Vers_TS * vers);
+
+/*
+ * Classify the state of a file.
+ *
+ * INPUTS
+ *   finfo             Information about the file to be classified.
+ *   tag
+ *   date
+ *   options           Keyword expansion options.  Can be either NULL or "" to
+ *                     indicate none are specified here.
+ *   force_tag_match
+ *   aflag
+ *   versp
+ *   pipeout           Did the user pass the "pipeout" flag to request that
+ *                     all output go to STDOUT rather than to a file or files?
+ *
+ * RETURNS
+ *   A Ctype (defined as an enum) describing the state of the file relative to
+ *   the repository.  See the definition of Ctype for more.
+ */
+Ctype
+Classify_File (struct file_info *finfo, char *tag, char *date, char *options,
+               int force_tag_match, int aflag, Vers_TS **versp, int pipeout)
+{
+    Vers_TS *vers;
+    Ctype ret;
+
+    TRACE (TRACE_FUNCTION, "classify_file (%s, %s, %s, %s)",
+          finfo->fullname, tag ? tag : "(null)", date ? date : "(null)",
+          options ? options : "(null)");
+
+    /* get all kinds of good data about the file */
+    vers = Version_TS (finfo, options, tag, date,
+                      force_tag_match, 0);
+
+    if (vers->vn_user == NULL)
+    {
+       /* No entry available, ts_rcs is invalid */
+       if (vers->vn_rcs == NULL)
+       {
+           /* there is no RCS file either */
+           if (vers->ts_user == NULL)
+           {
+               /* there is no user file */
+               /* FIXME: Why do we skip this message if vers->tag or
+                  vers->date is set?  It causes "cvs update -r tag98 foo"
+                  to silently do nothing, which is seriously confusing
+                  behavior.  "cvs update foo" gives this message, which
+                  is what I would expect.  */
+               if (!force_tag_match || !(vers->tag || vers->date))
+                   if (!really_quiet)
+                       error (0, 0, "nothing known about `%s'",
+                              finfo->fullname);
+               ret = T_UNKNOWN;
+           }
+           else
+           {
+               /* there is a user file */
+               /* FIXME: Why do we skip this message if vers->tag or
+                  vers->date is set?  It causes "cvs update -r tag98 foo"
+                  to silently do nothing, which is seriously confusing
+                  behavior.  "cvs update foo" gives this message, which
+                  is what I would expect.  */
+               if (!force_tag_match || !(vers->tag || vers->date))
+                   if (!really_quiet)
+                       error (0, 0, "use `%s add' to create an entry for `%s'",
+                              program_name, finfo->fullname);
+               ret = T_UNKNOWN;
+           }
+       }
+       else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
+       {
+           /* there is an RCS file, but it's dead */
+           if (vers->ts_user == NULL)
+               ret = T_UPTODATE;
+           else
+           {
+               error (0, 0, "use `%s add' to create an entry for `%s'",
+                      program_name, finfo->fullname);
+               ret = T_UNKNOWN;
+           }
+       }
+       else if (!pipeout && vers->ts_user && No_Difference (finfo, vers))
+       {
+           /* the files were different so it is a conflict */
+           if (!really_quiet)
+               error (0, 0, "move away `%s'; it is in the way",
+                      finfo->fullname);
+           ret = T_CONFLICT;
+       }
+       else
+           /* no user file or no difference, just checkout */
+           ret = T_CHECKOUT;
+    }
+    else if (strcmp (vers->vn_user, "0") == 0)
+    {
+       /* An entry for a new-born file; ts_rcs is dummy */
+
+       if (vers->ts_user == NULL)
+       {
+           if (pipeout)
+           {
+               ret = T_CHECKOUT;
+           }
+           else
+           {
+               /*
+                * There is no user file, but there should be one; remove the
+                * entry
+                */
+               if (!really_quiet)
+                   error (0, 0, "warning: new-born `%s' has disappeared",
+                          finfo->fullname);
+               ret = T_REMOVE_ENTRY;
+           }
+       }
+       else if (vers->vn_rcs == NULL ||
+                RCS_isdead (vers->srcfile, vers->vn_rcs))
+           /* No RCS file or RCS file revision is dead  */
+           ret = T_ADDED;
+       else
+       {
+           if (pipeout)
+           {
+               ret = T_CHECKOUT;
+           }
+           else
+           {
+               if (vers->srcfile->flags & INATTIC
+                   && vers->srcfile->flags & VALID)
+               {
+                   /* This file has been added on some branch other than
+                      the one we are looking at.  In the branch we are
+                      looking at, the file was already valid.  */
+                   if (!really_quiet)
+                       error (0, 0,
+                          "conflict: `%s' has been added, but already exists",
+                              finfo->fullname);
+               }
+               else
+               {
+                   /*
+                    * There is an RCS file, so someone else must have checked
+                    * one in behind our back; conflict
+                    */
+                   if (!really_quiet)
+                       error (0, 0,
+                               "conflict: `%s' created independently by"
+                              " second party",
+                              finfo->fullname);
+               }
+               ret = T_CONFLICT;
+           }
+       }
+    }
+    else if (vers->vn_user[0] == '-')
+    {
+       /* An entry for a removed file, ts_rcs is invalid */
+
+       if (vers->ts_user == NULL)
+       {
+           /* There is no user file (as it should be) */
+
+           if (vers->vn_rcs == NULL
+               || RCS_isdead (vers->srcfile, vers->vn_rcs))
+           {
+
+               /*
+                * There is no RCS file; this is all-right, but it has been
+                * removed independently by a second party; remove the entry
+                */
+               ret = T_REMOVE_ENTRY;
+           }
+           else if (strcmp (vers->vn_rcs, vers->vn_user + 1) == 0)
+               /*
+                * The RCS file is the same version as the user file was, and
+                * that's OK; remove it
+                */
+               ret = T_REMOVED;
+           else if (pipeout)
+               /*
+                * The RCS file doesn't match the user's file, but it doesn't
+                * matter in this case
+                */
+               ret = T_NEEDS_MERGE;
+           else
+           {
+
+               /*
+                * The RCS file is a newer version than the removed user file
+                * and this is definitely not OK; make it a conflict.
+                */
+               if (!really_quiet)
+                   error (0, 0,
+                          "conflict: removed `%s' was modified by"
+                          " second party",
+                          finfo->fullname);
+               ret = T_CONFLICT;
+           }
+       }
+       else
+       {
+           /* The user file shouldn't be there */
+           if (!really_quiet)
+               error (0, 0, "`%s' should be removed and is still there",
+                      finfo->fullname);
+           ret = T_REMOVED;
+       }
+    }
+    else
+    {
+       /* A normal entry, TS_Rcs is valid */
+       if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs))
+       {
+           /* There is no RCS file */
+
+           if (vers->ts_user == NULL)
+           {
+               /* There is no user file, so just remove the entry */
+               if (!really_quiet)
+                   error (0, 0, "warning: `%s' is not (any longer) pertinent",
+                          finfo->fullname);
+               ret = T_REMOVE_ENTRY;
+           }
+           else if (strcmp (vers->ts_user, vers->ts_rcs)
+                    && No_Difference (finfo, vers))
+           {
+               /* they are different -> conflict */
+               if (!really_quiet)
+                   error (0, 0,
+                           "conflict: `%s' is modified but no longer in the"
+                          " repository",
+                          finfo->fullname);
+               ret = T_CONFLICT;
+           }
+           else
+           {
+
+               /*
+                * The user file is still unmodified, so just remove it from
+                * the entry list
+                */
+               if (!really_quiet)
+                   error (0, 0, "`%s' is no longer in the repository",
+                          finfo->fullname);
+               ret = T_REMOVE_ENTRY;
+           }
+       }
+       else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
+       {
+           /* The RCS file is the same version as the user file */
+
+           if (vers->ts_user == NULL)
+           {
+
+               /*
+                * There is no user file, so note that it was lost and
+                * extract a new version
+                */
+               /* Comparing the cvs_cmd_name against "update", in
+                  addition to being an ugly way to operate, means
+                  that this message does not get printed by the
+                  server.  That might be considered just a straight
+                  bug, although there is one subtlety: that case also
+                  gets hit when a patch fails and the client fetches
+                  a file.  I'm not sure there is currently any way
+                  for the server to distinguish those two cases.  */
+               if (strcmp (cvs_cmd_name, "update") == 0)
+                   if (!really_quiet)
+                       error (0, 0, "warning: `%s' was lost", finfo->fullname);
+               ret = T_CHECKOUT;
+           }
+           else if (!strcmp (vers->ts_user,
+                             vers->ts_conflict
+                             ? vers->ts_conflict : vers->ts_rcs))
+           {
+
+               /*
+                * The user file is still unmodified, so nothing special at
+                * all to do -- no lists updated, unless the sticky -k option
+                * has changed.  If the sticky tag has changed, we just need
+                * to re-register the entry
+                */
+               /* TODO: decide whether we need to check file permissions
+                  for a mismatch, and return T_CONFLICT if so. */
+               if (vers->entdata->options &&
+                   strcmp (vers->entdata->options, vers->options) != 0)
+                   ret = T_CHECKOUT;
+               else if (vers->ts_conflict)
+                   ret = T_CONFLICT;
+               else
+               {
+                   sticky_ck (finfo, aflag, vers);
+                   ret = T_UPTODATE;
+               }
+           }
+           else if (No_Difference (finfo, vers))
+           {
+
+               /*
+                * they really are different; modified if we aren't
+                * changing any sticky -k options, else needs merge
+                */
+#ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
+               if (strcmp (vers->entdata->options ?
+                      vers->entdata->options : "", vers->options) == 0)
+                   ret = T_MODIFIED;
+               else
+                   ret = T_NEEDS_MERGE;
+#else
+               /* Files with conflict markers and new timestamps fall through
+                * here, but they need to.  T_CONFLICT is an error in
+                * commit_fileproc, whereas T_MODIFIED with conflict markers
+                * is caught but only warned about.  Similarly, update_fileproc
+                * currently reregisters a file that was conflicted but lost
+                * its markers.
+                */
+               ret = T_MODIFIED;
+               sticky_ck (finfo, aflag, vers);
+#endif
+           }
+           else if (strcmp (vers->entdata->options ?
+                      vers->entdata->options : "", vers->options) != 0)
+           {
+               /* file has not changed; check out if -k changed */
+               ret = T_CHECKOUT;
+           }
+           else
+           {
+
+               /*
+                * else -> note that No_Difference will Register the
+                * file already for us, using the new tag/date. This
+                * is the desired behaviour
+                */
+               ret = T_UPTODATE;
+           }
+       }
+       else
+       {
+           /* The RCS file is a newer version than the user file */
+
+           if (vers->ts_user == NULL)
+           {
+               /* There is no user file, so just get it */
+
+               /* See comment at other "update" compare, for more
+                  thoughts on this comparison.  */
+               if (strcmp (cvs_cmd_name, "update") == 0)
+                   if (!really_quiet)
+                       error (0, 0, "warning: `%s' was lost", finfo->fullname);
+               ret = T_CHECKOUT;
+           }
+           else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
+           {
+
+               /*
+                * The user file is still unmodified, so just get it as well
+                */
+               if (strcmp (vers->entdata->options ?
+                           vers->entdata->options : "", vers->options) != 0
+                   || (vers->srcfile != NULL
+                       && (vers->srcfile->flags & INATTIC) != 0))
+                   ret = T_CHECKOUT;
+               else
+                   ret = T_PATCH;
+           }
+           else if (No_Difference (finfo, vers))
+               /* really modified, needs to merge */
+               ret = T_NEEDS_MERGE;
+           else if ((strcmp (vers->entdata->options ?
+                             vers->entdata->options : "", vers->options)
+                     != 0)
+                    || (vers->srcfile != NULL
+                        && (vers->srcfile->flags & INATTIC) != 0))
+               /* not really modified, check it out */
+               ret = T_CHECKOUT;
+           else
+               ret = T_PATCH;
+       }
+    }
+
+    /* free up the vers struct, or just return it */
+    if (versp != NULL)
+       *versp = vers;
+    else
+       freevers_ts (&vers);
+
+    /* return the status of the file */
+    return (ret);
+}
+
+static void
+sticky_ck (struct file_info *finfo, int aflag, Vers_TS *vers)
+{
+    if (aflag || vers->tag || vers->date)
+    {
+       char *enttag = vers->entdata->tag;
+       char *entdate = vers->entdata->date;
+
+       if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
+           ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
+           (entdate && vers->date && strcmp (entdate, vers->date)) ||
+           ((entdate && !vers->date) || (!entdate && vers->date)))
+       {
+           Register (finfo->entries, finfo->file, vers->vn_user, vers->ts_rcs,
+                     vers->options, vers->tag, vers->date, vers->ts_conflict);
+
+#ifdef SERVER_SUPPORT
+           if (server_active)
+           {
+               /* We need to update the entries line on the client side.
+                  It is possible we will later update it again via
+                  server_updated or some such, but that is OK.  */
+               server_update_entries
+                 (finfo->file, finfo->update_dir, finfo->repository,
+                  strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
+                  SERVER_UPDATED : SERVER_MERGED);
+           }
+#endif
+       }
+    }
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]