On Fri February 23 2007 10:33, Tailor wrote:
> #97: Monotone to SVN fails
> ----------------------+------------------------------------------
>----------- Reporter:  stelios  |       Owner:  lele
>       Type:  defect   |      Status:  new
>   Priority:  major    |   Milestone:  VersionOne
>  Component:  tailor   |     Version:  0.9
> Resolution:           |    Keywords:
> ----------------------+------------------------------------------
>----------- Comment (by stelios):
>
>  Has anyone been able to look into this ?

I see this as well, it is apparently triggered by a "Revisions: ..."
string in a ChangeLog body.

The patch below seems to fix this precise problem but I am not a regular
monotone user so it might break something else I am not aware of.

Robin

-------------------------------------------------------------------
monotone: restrict order of headers in revision logs

Since monotone does not indent the user provided log message that
follows a ChangeLog header, collisions can happen between a monotone
header and a line in the log message.

According to monotone's sources, the last two headers in a revision
log are, in order, ChangeLog and Comments. Hence, while parsing the
log message, we can consider any line not starting with Comments: as
part of the log message.

diff --git a/vcpx/repository/monotone.py b/vcpx/repository/monotone.py
--- a/vcpx/repository/monotone.py
+++ b/vcpx/repository/monotone.py
@@ -251,12 +251,9 @@ class MonotoneLogParser:
 
     # logfile states
     SINGLE = 0  # single line state
-    ADD = 1 # in add file/dir listing
-    MOD = 2 # in mod file/dir listing
-    DEL = 3 # in delete file/dir listing
-    REN = 4 # in renamed file/dir listing
-    LOG = 5 # in changelog listing
-    CMT = 6 # in comment listing
+    MOD = 1     # in modification file/dir listing
+    LOG = 2     # in changelog listing
+    CMT = 3     # in comment listing
 
     def __init__(self, repository, working_dir):
         self.working_dir = working_dir
@@ -304,65 +301,61 @@ class MonotoneLogParser:
         state = self.SINGLE
         loglines = outstr[0].getvalue().splitlines()
         for curline in loglines:
-
+            if state == self.MOD:
+                # skip dir/file add/remove/rename information
+                if curline[:1].isspace():
+                    continue
+                state = self.SINGLE
             pr = self.PrefixRemover(curline)
+            if state == self.LOG:
+                # only a Comment section can follow a ChangeLog section
+                if pr("Comments:"):
+                    comments = comments + "Note:\n"
+                    state = self.CMT
+                else:
+                    # log line, accumulate string
+                    logs = logs + curline + "\n"
+                continue
+            if state == self.CMT:
+                # comment line, accumulate string
+                comments = comments + curline + "\n"
+                continue
+            # state == self.SINGLE
             if pr("Revision:"):
                 if pr.value != revision:
                     raise GetUpstreamChangesetsFailure(
-                        "Revision doesn't match. Expected %s, found %s" % 
(revision, pr.value))
-                state = self.SINGLE
+                        "Revision doesn't match. Expected %s, found %s" %
+                        (revision, pr.value))
             elif pr("Ancestor:"):
                 if pr.value:
-                    self.ancestors.append(pr.value) # cset could be a merge 
and have multiple ancestors
-                state = self.SINGLE
+                    # cset could be a merge and have multiple ancestors
+                    self.ancestors.append(pr.value)
             elif pr("Author:"):
                 self.authors.append(pr.value)
-                state = self.SINGLE
             elif pr("Date:"):
-                    # monotone dates are expressed in ISO8601, always UTC
-                    dateparts = pr.value.split('T')
-                    assert len(dateparts) >= 2, `dateparts`
-                    day = dateparts[0]
-                    time = dateparts[1]
-                    y,m,d = map(int, day.split(day[4]))
-                    hh,mm,ss = map(int, time.split(':'))
-                    date = datetime(y,m,d,hh,mm,ss,0,UTC)
-                    self.dates.append(date)
-                    state = self.SINGLE
+                # monotone dates are expressed in ISO8601, always UTC
+                dateparts = pr.value.split('T')
+                assert len(dateparts) >= 2, `dateparts`
+                day = dateparts[0]
+                time = dateparts[1]
+                y,m,d = map(int, day.split(day[4]))
+                hh,mm,ss = map(int, time.split(':'))
+                date = datetime(y,m,d,hh,mm,ss,0,UTC)
+                self.dates.append(date)
             elif pr("Branch:"):
                 # branch data
                 self.branches.append(pr.value)
-                state = self.SINGLE
-            elif pr("Tag"):
-                # unused data, just resetting state
-                state = self.SINGLE
-            elif pr("Deleted files:") or pr("Deleted directories:") or 
pr("Deleted entries"):
-                state=self.DEL
-            elif pr("Renamed files:") or pr("Renamed directories:") or 
pr("Renamed entries"):
-                state=self.REN
-            elif pr("Added files:") or pr("Added directories:"):
-                state=self.ADD
-            elif pr("Modified files:"):
-                state=self.ADD
+            elif pr("Added files:") or pr("Added directories:") or \
+                 pr("Deleted files:") or pr("Deleted directories:") or \
+                 pr("Deleted entries:") or pr("Renamed files:") or \
+                 pr("Renamed directories:") or pr("Renamed entries:") or \
+                 pr("Modified files:"):
+                state = self.MOD
             elif pr("ChangeLog:"):
-                state=self.LOG
+                state = self.LOG
             elif pr("Comments:"):
-                comments=comments + "Note:\n"
-                state=self.CMT
-            else:
-                # otherwise, it must be a log/comment/changeset entry, or an 
unknown cert line
-                if state == self.SINGLE:
-                    # line coming from an unknown cert
-                    pass
-                elif state == self.LOG:
-                    # log line, accumulate string
-                    logs = logs + curline + "\n"
-                elif state == self.CMT:
-                    # comment line, accumulate string
-                    comments = comments + curline + "\n"
-                else:
-                    # parse_cset_entry(mode, chset, curline.strip()) # cset 
entry, handle
-                    pass # we ignore cset info
+                comments = comments + "Note:\n"
+                state = self.CMT
 
         # parsing terminated, verify the data
         if len(self.authors)<1 or len(self.dates)<1 or revision=="":
_______________________________________________
Tailor mailing list
[email protected]
http://lists.zooko.com/mailman/listinfo/tailor

Reply via email to