bug-cvs
[Top][All Lists]
Advanced

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

Re: Proposed branch tag performance patch for feature


From: Mark D. Baushke
Subject: Re: Proposed branch tag performance patch for feature
Date: Wed, 03 Jan 2007 13:50:50 -0800

Hi Kelly,

Kelly F. Hickel <kfh@mqsoftware.com> writes:

> Mark,
>       I finally got around to completing this
> change, attached is a unified diff (I attached
> it because the last patch was corrupted by
> outlook) against cvs 1.11.21.

Thanks for the resend.

There are still a number of coding-style problems,
but at least this one applied to the top-of-tree
sources.

>       This patch is only for the stable release,
> once it's been looked over and approved, I'll do
> the feature release, I just didn't want to get
> it all done and then find out the approach was
> flawed.

Okay.

>       I've included ChangeLog and sanity.sh
> changes, I believe the sanity.sh tests are
> sufficiently paranoid, they did point out
> failures with the previous patch.

Hmmm... My test had a problems with a number of
the branches3 tests... The first was branches3-4b.

I appled your patch to the head of the cvs 1.11.x
branch and fixed what I could of the coding style
and sanity.sh to get the tests to pass.

>       The previous patch improved my repo's
> branch time from 115 minutes to 8 minutes, this
> patch only gets it down to 12 minutes, but since
> it's correct, I won't worry about the 4 "extra"
> minutes! ;>

I like the performance numbers you are sharing
very much.

>       Let me know if there's anything that I
> missed, or if I can help in any way to get this
> patch accepted.

I'm sending you back the patches that I might
consider committing (modulo the ChangeLog entry
which I did not touch).

Please look it over to make sure that I did not
make any bad changes during the reformatting.

        -- Mark

> 
> Thanks,
> 
> -- 
> 
> Kelly F. Hickel
> Senior Software Architect
> MQSoftware, Inc
> 952.345.8677
> kfh@mqsoftware.com
> 
> > -----Original Message-----
> > From: mdb@juniper.net (Mark D. Baushke)
> > Sent: Wednesday, May 10, 2006 10:33 AM
> > To: Kelly F. Hickel
> > Cc: bug-cvs@nongnu.org
> > Subject: Re: Proposed branch tag performance
> >  patch for feature and stable releases
> > 
> > Hi Kelly,
> > 
> > Point #1 of this has been communicated
> > privately, but it occurs to me that the
> > bug-cvs list may be interested in knowing what
> > is happening.
> > 
> > There are some problems with the proposed patch:
> > 
> >   1) It is finding the the highest revision
> >      across all branches with the right number
> >      of dots, not just the branches rooted at
> >      the same revision. So, if you have a
> >      number of branches off 1.1 -- 1.1.0.2,
> >      1.1.0.4, and 1.1.0.6, for example -- and
> >      then create a new branch off of 1.2 you
> >      will get 1.2.0.8 instead of 1.2.0.2 as
> >      you should. It is also checking all tags
> >      with the right number of dots, not just
> >      magic branch tags.
> > 
> >   2) For the FEATURE branch (1.12.x), there is
> >      an added problem in that the file may be
> >      using a mixture of the
> >      CVS_LOCAL_BRANCH_NUM feature along with
> >      regular branches. In this case, it is a
> >      good bet that the user is using CVSup to
> >      make sure that revisions that are above
> >      the CVS_LOCAL_BRANCH_NUM starting number
> >      will NOT be propagated to mirrors of the
> >      repository and are thus not generally
> >      available.
> > 
> >      So, if you have a number of global
> >      branches off 1.1 -- 1.1.0.2, 1.1.0.4,
> >      1.1.0.6 as well as a few local branches
> >      1.1.0.1000 and 1.1.0.1002, then the next
> >      global branch created off of 1.1 will
> >      incorrectly be set to 1.1.0.1004 instead
> >      of 1.1.0.8 as expected.
> > 
> >      Of course, this may not be that big a
> >      deal as in the normal course of things
> >      new global branches are created on the
> >      master repository and CVSup'd to the
> >      mirrors and the global will typically not
> >      have a good reason to create a
> >      CVS_LOCAL_BRANCH_NUM, however, it has
> >      happened that master repositories become
> >      dead and a new master is elected from one
> >      of the mirrors which could lead to the
> >      above problem.
> > 
> >   3) The patch provided did pass our sanity.sh
> >      regression tests and should not have.
> >      This means that we likely need to have a
> >      more rigorous set of tests that the
> >      correct revisions are being created by
> >      the cvs tag code. So, the proposed patch
> >      will probably also need to include some
> >      sanity.sh tests to exercise it.
> > 
> > Thank you for your consideration of this
> > problem.
> > 
> >     -- Mark
> > 
> > -----BEGIN PGP SIGNATURE-----
> > Version: GnuPG v1.4.3 (FreeBSD)
> > 
> > iD8DBQFEYgevCg7APGsDnFERAomSAKDMWgJWcmOByJRv0h2J1kZrW3fGvwCfZjkR
> > jtI9cRWSisG6ORRlK0CVQvE=
> > =jvvC
> > -----END PGP SIGNATURE-----
> diff -ru cvs-1.11.21_orig/src/ChangeLog cvs-1.11.21/src/ChangeLog
> --- cvs-1.11.21_orig/src/ChangeLog    2005-09-26 09:31:33.000000000 -0500
> +++ cvs-1.11.21/src/ChangeLog 2007-01-03 13:54:28.000000000 -0600
> @@ -1,3 +1,13 @@
> +2007-01-03  Kelly F. Hickel <kfh@mqsoftware.com>
> +
> +        * rcs.c (findnextmagicrev_proc): New function to find the
> +     all rev numbers with the required number of dots and matching
> +     initial substring.
> +     (findnextmagicrev): New function to walk the symbolic tag list
> +     calling findnextmagicrev_proc() to get a list of used rev numbers
> +     and choose the highest suitable one.
> +     (RCS_magicrev): Use findnextmagicrev().
> +     
>  2005-09-26  Conrad T. Pino  <Conrad@Pino.com>
>  
>       * rcs.c: Use "#ifdef HAVE_FSYNC" just like every where else.
> diff -ru cvs-1.11.21_orig/src/rcs.c cvs-1.11.21/src/rcs.c
> --- cvs-1.11.21_orig/src/rcs.c        2005-09-26 09:31:36.000000000 -0500
> +++ cvs-1.11.21/src/rcs.c     2007-01-03 13:56:27.000000000 -0600
> @@ -133,6 +133,8 @@
>  static FILE *rcs_internal_lockfile PROTO ((char *));
>  static void rcs_internal_unlockfile PROTO ((FILE *, char *));
>  static char *rcs_lockfilename PROTO ((const char *));
> +static int findnextmagicrev PROTO ((RCSNode *rcs, char *rev, int 
> default_rv));
> +static int findnextmagicrev_proc PROTO((Node *p, void *closure));
>  
>  /* The RCS file reading functions are called a lot, and they do some
>     string comparisons.  This macro speeds things up a bit by skipping
> @@ -2549,8 +2551,13 @@
>      xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
>      check_rev = xrev;
>  
> +    /* prime the pump by finding the next unused magic rev,
> +     * if none are found, it should return 2.
> +     */
> +    rev_num = findnextmagicrev (rcs, rev, 2);
> +    
>      /* only look at even numbered branches */
> -    for (rev_num = 2; ; rev_num += 2)
> +    for (; ; rev_num += 2)
>      {
>       /* see if the physical branch exists */
>       (void) sprintf (xrev, "%s.%d", rev, rev_num);
> @@ -8818,3 +8825,181 @@
>      }
>      return label;
>  }
> +
> +/* closure structure to communicate through walklist */
> +struct findnextmagicrev_info {
> +  char *target_rev;
> +  int target_rev_dots;
> +  int target_rev_len;
> +  List *rev_list;
> +};
> +
> +/* sort a list assuming that the data members are integers */
> +static int
> +findnextmagicrev_sortfunc(p, q)
> +     const Node *p;
> +     const Node *q;
> +{
> +  /* We want the highest value sorted first, to make it easy to find */
> +  return ((int)q->data - (int)p->data);
> +}
> +
> +/* free a list node where the data member is an integer */
> +static void
> +findnextmagicrev_delproc(Node *p)

In cvs 1.11.x, we use K&R declarations everywhere.

  static void
  findnextmagicrev_delproc(p)
      Node *p;

in cvs 1.12.x, we should be using ANSI C89
prototypes everywhere...

> +{
> +  /* Do nothing, it's not a pointer */
> +  p->data = 0;
> +}
> +
> +/*
> + * Go through the symbolic tag list, find the next unused magic
> + * branch revision.
> + *
> + * Returns defaultrv if it can't figure anything out, then the caller
> + * will end up doing a linear search.
> + */
> +static int
> +findnextmagicrev (rcs, rev, defaultrv)
> +     RCSNode *rcs;
> +     char *rev;
> +     int defaultrv;
> +{
> +  int rv = defaultrv;
> +  struct findnextmagicrev_info info;
> +  
> +  /* Tell the walklist proc how many dots we're looking for,
> +   * which is the number of dots in the existing rev, plus
> +   * 2.  one for RCS_MAGIC_BRANCH and one for the new rev number.
> +   */
> +  info.target_rev = rev;
> +  info.target_rev_dots = numdots (rev) + 2;
> +  info.target_rev_len = strlen(rev);
> +  info.rev_list = getlist();

The coding standard wants spaces between function
names and argument lists:

  info.target_rev_len = strlen (rev);
  info.rev_list = getlist ();

Generally, there are style problems thoughout this function.

After my .signature is the patch I have (not yet fully tested).

        -- Mark

Index: src/rcs.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/rcs.c,v
retrieving revision 1.262.4.58
diff -u -p -r1.262.4.58 rcs.c
--- src/rcs.c   8 Sep 2006 13:24:34 -0000       1.262.4.58
+++ src/rcs.c   3 Jan 2007 21:47:32 -0000
@@ -133,6 +133,8 @@ static void putdeltatext PROTO ((FILE *,
 static FILE *rcs_internal_lockfile PROTO ((char *));
 static void rcs_internal_unlockfile PROTO ((FILE *, char *));
 static char *rcs_lockfilename PROTO ((const char *));
+static int findnextmagicrev PROTO ((RCSNode *rcs, char *rev, int default_rv));
+static int findnextmagicrev_proc PROTO((Node *p, void *closure));
 
 /* The RCS file reading functions are called a lot, and they do some
    string comparisons.  This macro speeds things up a bit by skipping
@@ -2544,8 +2546,13 @@ RCS_magicrev (rcs, rev)
     xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
     check_rev = xrev;
 
+    /* Prime the pump by finding the next unused magic rev,
+     * if none are found, it should return 2.
+     */
+    rev_num = findnextmagicrev (rcs, rev, 2);
+    
     /* only look at even numbered branches */
-    for (rev_num = 2; ; rev_num += 2)
+    for (; ; rev_num += 2)
     {
        /* see if the physical branch exists */
        (void) sprintf (xrev, "%s.%d", rev, rev_num);
@@ -8939,3 +8946,198 @@ make_file_label (path, rev, rcs)
     }
     return label;
 }
+
+/* closure structure to communicate through walklist */
+struct findnextmagicrev_info
+{
+    char *target_rev;
+    int target_rev_dots;
+    int target_rev_len;
+    List *rev_list;
+};
+
+/* sort a list assuming that the data members are integers */
+static int
+findnextmagicrev_sortfunc(p, q)
+     const Node *p;
+     const Node *q;
+{
+    /* We want the highest value sorted first, to make it easy to find */
+    return ((int)q->data - (int)p->data);
+}
+
+/* free a list node where the data member is an integer */
+static void
+findnextmagicrev_delproc (p)
+    Node *p;
+{
+    /* Do nothing, it's not a pointer */
+    p->data = 0;
+}
+
+/*
+ * Go through the symbolic tag list, find the next unused magic
+ * branch revision.
+ *
+ * Returns defaultrv if it can't figure anything out, then the caller
+ * will end up doing a linear search.
+ */
+static int
+findnextmagicrev (rcs, rev, defaultrv)
+     RCSNode *rcs;
+     char *rev;
+     int defaultrv;
+{
+    int rv = defaultrv;
+    struct findnextmagicrev_info info;
+  
+    /* Tell the walklist proc how many dots we're looking for,
+     * which is the number of dots in the existing rev, plus
+     * 2.  one for RCS_MAGIC_BRANCH and one for the new rev number.
+     */
+    info.target_rev = rev;
+    info.target_rev_dots = numdots (rev) + 2;
+    info.target_rev_len = strlen (rev);
+    info.rev_list = getlist ();
+  
+    /* walk the symbols list to find the highest revision. */
+    (void) walklist (RCS_symbols (rcs), findnextmagicrev_proc, &info);
+
+    if (! list_isempty (info.rev_list))
+    {
+       int i = 0;
+
+       /* sort the list that came back */
+       sortlist(info.rev_list, findnextmagicrev_sortfunc);
+
+       /* Get the highest numeric value */
+       rv = (int)info.rev_list->list->next->data;  
+
+       /* adjust to next even number if we found something */
+       if (rv != defaultrv)
+       {
+           if ((rv % 2) != 0)
+               rv++;
+           else
+               rv += 2;
+       }
+    }
+
+    dellist (&(info.rev_list));
+    return rv;
+}
+
+/*
+ * walklist proc to find all "interesting" revs,
+ * and put them in a list for the caller to look through.
+ * Interesting is defined as having numdots+2 and same initial
+ * substring (up to the dot of numdots+1), or the second to last
+ * term indicates this is a magic branch.
+ */
+static int
+findnextmagicrev_proc (p, closure)
+     Node *p;
+     void *closure;
+{
+    struct findnextmagicrev_info *pinfo = (struct findnextmagicrev_info 
*)closure;
+    int sym_dots = numdots(p->data);
+
+    /*
+     * Quick first level screen, if the number of dots isn't right, then we
+     * don't care about this revision.
+     */
+    if (sym_dots == pinfo->target_rev_dots) 
+    {
+       /*
+        * We can't rely on being able to find the magic branch tag to
+        * find all existing branches, as that may have been deleted.
+        * So, here we're looking for revisions where the initial
+        * substring matches our target, and that have the same number
+        * of dots that revisions in the new branch will have in this
+        * case we record atoi of the second to last term in the list.
+        *
+        * We're also looking at revisions with RCS_MAGIC_BRANCH as
+        * the second to last term, for those, we record atoi of the
+        * last term in the list.
+        *
+        * Example:
+        * We're about to create a branch from 1.1, if we see
+        * revisions like 1.1.2.1, or 1.1.6.1, then we know we can't
+        * use either 2 or 6 as the new rev term, even if we don't see
+        * the symbols 1.1.0.2 and 1.1.0.6.
+        *
+        * If we see revisions like 1.1.0.8 or 1.1.0.12, we know that
+        * we can't use 8 or 12.
+        *
+        * Simply put, for revistions that have the same initial
+        * substring as our target, if the second to last term is
+        * RCS_MAGIC_BRANCH, take atoi of the last term and put it in
+        * the list, if not, take atoi of the second to last term, put
+        * it in the list.
+        */
+    
+       /*
+        * Second screen, make sure that target_rev is an initial substring
+        * of the rev we're considering.  This means doing a strncmp, then if
+        * it's the same, making sure that the one under consideration has a
+        * dot after the target rev.
+        *
+        * Check the dot first, since that's faster.
+        */
+       char *ver_str = (char*)(p->data);
+       if ((ver_str[pinfo->target_rev_len] == '.') && 
+           (strncmp(pinfo->target_rev, p->data, pinfo->target_rev_len) == 0))
+       {
+           char *plast_dot = 0;
+           char *psecond_to_last_dot = 0;
+           int i = strlen (ver_str);
+
+           /* Get pointers in this revision to the last and second to
+            * last dots
+            */
+           while((i>0) && ((plast_dot == 0) || (psecond_to_last_dot == 0)))
+           {
+               if (ver_str[i] == '.')
+               {
+                   if (plast_dot == 0)
+                       plast_dot = &(ver_str[i]);
+                   else
+                       psecond_to_last_dot = &(ver_str[i]);
+               }
+               i--;
+           }
+           if ((plast_dot != 0) && (psecond_to_last_dot != 0))
+           {
+               int term_to_add = 0;
+               int second_to_last_term = atoi (psecond_to_last_dot + 1);
+               if(second_to_last_term == RCS_MAGIC_BRANCH)
+               {
+                   /* We want to put the value of the last term into
+                    * the list
+                    */
+                   term_to_add = atoi (plast_dot + 1);
+               }
+               else
+               {
+                   /* We want to put the value of the second to last
+                    * term into the list
+                    */
+
+                   term_to_add = atoi (psecond_to_last_dot + 1);
+               }
+               if (term_to_add != 0)
+               {
+                   Node *n = getnode ();
+                   n->type = VARIABLE;
+                   n->key = 0;
+                   n->data = (void*)term_to_add;
+                   n->delproc = findnextmagicrev_delproc;
+
+                   /* dupe insert won't fail because we aren't using a hash */
+                   addnode (pinfo->rev_list, n); 
+               }
+           }
+       }
+    }
+    return 1;
+}
Index: src/sanity.sh
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/sanity.sh,v
retrieving revision 1.752.2.207
diff -u -p -r1.752.2.207 sanity.sh
--- src/sanity.sh       14 Sep 2006 15:26:16 -0000      1.752.2.207
+++ src/sanity.sh       3 Jan 2007 21:47:33 -0000
@@ -1108,7 +1108,8 @@ if test x"$*" = x; then
        tests="${tests} rdiff rdiff-short"
        tests="${tests} rdiff2 diff diffnl death death2 death-rtag"
        tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
-       tests="${tests} dirs dirs2 branches branches2 tagc tagf tag-space"
+       tests="${tests} dirs dirs2 branches branches2 branches3"
+       tests="${tests} tagc tagf tag-space"
        tests="${tests} rcslib multibranch import importb importc import-CVS"
        tests="$tests import-quirks"
        tests="${tests} update-p import-after-initial branch-after-import"
@@ -7113,6 +7114,208 @@ File: file5             Status: Up-to-da
          rm -r trunk b1a b1b
          ;;
 
+       branches3)
+         # test new faster branching code to make sure it doesn't
+         # reuse a previously used magic branch tag.
+          # Set up a repo, files, etc.
+         mkdir ${CVSROOT_DIRNAME}/first-dir
+         dotest branches3-1 "${testcvs} -q co first-dir" ''
+         cd first-dir
+         echo 1:ancest >file1
+         echo 2:ancest >file2
+         dotest branches3-2 "${testcvs} add file1 file2" \
+"${PROG}"' add: scheduling file `file1'\'' for addition
+'"${PROG}"' add: scheduling file `file2'\'' for addition
+'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
+         dotest_lit branches3-3a "${testcvs} -q ci -m add-it" <<HERE
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
+done
+Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+initial revision: 1.1
+done
+RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
+done
+Checking in file2;
+${CVSROOT_DIRNAME}/first-dir/file2,v  <--  file2
+initial revision: 1.1
+done
+HERE
+         dotest branches3-3b "${testcvs} update -d " \
+"${PROG} update: Updating \."
+
+         # First branch gets a commit, then the branch gets deleted.
+         # The purpose of this test is to make sure that even if the 
+          # magic branch tag is missing, we see the commits and don't
+          # consider the missing branch tag as eligible for reuse.
+         dotest branches3-4a "${testcvs} -q tag -b br3br1" \
+'T file1
+T file2'
+         dotest branches3-4b "${testcvs} -q update -r br3br1" \
+'[UP] file1
+[UP] file2'
+         echo 1:br3br1 >file1
+         dotest branches3-4c "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+         dotest branches3-4d "${testcvs} tag -d -B br3br1 file1 file2" \
+'D file1
+D file2'
+
+
+         # Second branch gets no commits.
+         # The purpose of this test is to make sure we respect branches
+         # that don't (yet) have any changes on them.
+         dotest branches3-5a "${testcvs} -q update -r HEAD" \
+'[UP] file1
+[UP] file2'
+         echo "about to issue:${testcvs} -q tag -b br3br2" >>$LOGFILE
+         dotest branches3-5b "${testcvs} -q tag -b br3br2" \
+'T file1
+T file2'
+
+         # Third branch gets several commits so that the 4th 
+         # digit of it's revision number is 10 to test that
+         # we don't just consider the highest number in the 4th position.
+         dotest branches3-6a "${testcvs} -q update -r HEAD" ''
+         dotest branches3-6b "${testcvs} -q tag -b br3br3" \
+'T file1
+T file2'
+
+         dotest branches3-6c "${testcvs} -q update -r br3br3" \
+'[UP] file1
+[UP] file2'
+         echo 1:br3br3.1 >file1
+         dotest branches3-6d "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.1; previous revision: 1\.1
+done"
+         echo 1:br3br3.2 >file1
+         dotest branches3-6e "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.2; previous revision: 1\.1\.6\.1
+done"
+         echo 1:br3br3.3 >file1
+         dotest branches3-6f "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.3; previous revision: 1\.1\.6\.2
+done"
+         echo 1:br3br3.4 >file1
+         dotest branches3-6g "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.4; previous revision: 1\.1\.6\.3
+done"
+         echo 1:br3br3.5 >file1
+         dotest branches3-6h "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.5; previous revision: 1\.1\.6\.4
+done"
+         echo 1:br3br3.6 >file1
+         dotest branches3-6i "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.6; previous revision: 1\.1\.6\.5
+done"
+         echo 1:br3br3.7 >file1
+         dotest branches3-6i "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.7; previous revision: 1\.1\.6\.6
+done"
+         echo 1:br3br3.8 >file1
+         dotest branches3-6k "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.8; previous revision: 1\.1\.6\.7
+done"
+         echo 1:br3br3.9 >file1
+         dotest branches3-6l "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.9; previous revision: 1\.1\.6\.8
+done"
+         echo 1:br3br3.10 >file1
+         dotest branches3-6m "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.6\.10; previous revision: 1\.1\.6\.9
+done"
+         # Create a tag on revision 1.1.6.10 so it shows up in RCS symbols
+         dotest branches3-6n "${testcvs} -q tag br3br3_rev_10" \
+'T file1
+T file2'
+
+         # Create the fourth branch, ensure that it gets the correct magic
+         # branch tag.
+         dotest branches3-7a "${testcvs} -q update -r HEAD" \
+'[UP] file1
+[UP] file2'
+         dotest branches3-7b "${testcvs} -q tag -b br3br4" \
+'T file1
+T file2'
+         dotest branches3-7c "${testcvs} -q update -r br3br4" \
+'[UP] file1
+[UP] file2'
+         echo 1:br3br4 >file1
+         dotest branches3-7d "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.1\.8\.1; previous revision: 1\.1
+done"
+
+         # Make a commit on the trunk, then create the fifth branch,
+         # make sure we get the correct revision.
+         #
+         # The purpose of this test is to make sure that we're only
+         # looking at the revisions we should be. If we didn't, this
+         # branch would end up being 1.2.0.10 instead of 1.2.0.2
+         cd ..
+         rm -rf first-dir
+         dotest branches3-8a "${testcvs} -q co first-dir" \
+'U first-dir/file1
+U first-dir/file2'
+         cd first-dir
+         echo 1:HEAD.2 >file1
+         dotest branches3-8b "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.2; previous revision: 1\.1
+done"
+         dotest branches3-8c "${testcvs} -q tag -b br3br5" \
+'T file1
+T file2'
+         dotest branches3-8d "${testcvs} -q update -r br3br5" \
+'[UP] file1
+[UP] file2'
+         echo 1:br3br5 >file1
+         dotest branches3-8e "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${CVSROOT_DIRNAME}/first-dir/file1,v  <--  file1
+new revision: 1\.2\.2\.1; previous revision: 1\.2
+done"
+
+
+
+         # clean up after this test
+         cd ..
+
+         if $keep; then
+           echo Keeping ${TESTDIR} and exiting due to --keep
+           exit 0
+         fi
+
+         rm -rf ${CVSROOT_DIRNAME}/first-dir
+         rm -r first-dir
+         ;;
+
+
        tagc)
          # Test the tag -c option.
          mkdir 1; cd 1




reply via email to

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