Improved parsing of common errors (such as unknown revision)
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 08 Feb 2018 09:09:51 +0000
changeset 807 ef00a1303f73
parent 805 b890f24db9f0
child 808 ae9fdbfa8ba4
Improved parsing of common errors (such as unknown revision) The generic error [arsing methods not recognize these common errors and handle them, so individual commands do not need to override and specialize error parsing. Store more details (such as the id if unknown revision) in parameter of an exception.
mercurial/HGChangesetId.st
mercurial/HGCommand.st
mercurial/HGCommandParser.st
mercurial/HGCommandParserTests.st
--- a/mercurial/HGChangesetId.st	Mon Jan 01 20:27:19 2018 +0000
+++ b/mercurial/HGChangesetId.st	Thu Feb 08 09:09:51 2018 +0000
@@ -262,16 +262,19 @@
     ]
 
     "
-    HGNodeId fromString:'4:6f88e1f44d9eb86e0b56ca15e30e5d786acd83c7'
+    HGChangesetId fromString:'4:6f88e1f44d9eb86e0b56ca15e30e5d786acd83c7'
+    HGChangesetId readFrom: '96DB65258808720D8D5EA6CB7A6A4D4F4E467325''!!' readStream
 
     Bad ones:
 
-    HGNodeId fromString:'4:6f88e1f44d9eb86e0b56ca15e30e5d786acd' 
-    HGNodeId fromString:'4:6f88Z1f44d9eb86e0b56ca15e30e5d786acd83c7' 
+    HGChangesetId fromString:'4:6f88e1f44d9eb86e0b56ca15e30e5d786acd' 
+    HGChangesetId fromString:'4:6f88Z1f44d9eb86e0b56ca15e30e5d786acd83c7' 
+
     "
 
     "Created: / 13-11-2012 / 16:49:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 13-07-2016 / 18:15:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (comment): / 08-02-2018 / 08:41:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGChangesetId class methodsFor:'accessing'!
--- a/mercurial/HGCommand.st	Mon Jan 01 20:27:19 2018 +0000
+++ b/mercurial/HGCommand.st	Thu Feb 08 09:09:51 2018 +0000
@@ -2040,15 +2040,6 @@
     "Modified: / 25-03-2016 / 17:25:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-parseError:stream
-    "Parses output of 'hg' command, i.e. commit, log, update, checkout,
-     etc."
-
-    ^ (self parserOn: stream) parseErrorLog.
-
-    "Created: / 09-02-2014 / 10:22:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
 parseOutput:stream
     "Parses output of 'hg' command, i.e. commit, log, update, checkout,
      etc."
--- a/mercurial/HGCommandParser.st	Mon Jan 01 20:27:19 2018 +0000
+++ b/mercurial/HGCommandParser.st	Thu Feb 08 09:09:51 2018 +0000
@@ -1113,76 +1113,6 @@
     "Created: / 04-02-2013 / 12:21:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-parseError1: parseBlock
-    "/ Parse at most one error from stream and returs.
-
-    | c word line |
-
-    c := stream peek.
-    c isNil ifTrue:[ ^ self ]. "/ stream closed / already at end
-
-    "/ Care for "*** failed to import extension" messages...
-    c == $* ifTrue:[ 
-        stream next.
-        c := stream peek.
-        c == $* ifTrue:[ 
-            stream next.
-            c := stream peek.
-            c == $* ifTrue:[ 
-                stream next.
-                self notify: stream nextLine.
-                ^ self.
-            ].
-        ].
-        self notify: stream nextLine.
-        ^ self.
-    ].
-    "/ parse `abort: some error messsage` error format
-    c == $a ifTrue:[
-        word := stream upTo: $:.
-        stream next. "/eat space
-        word = 'abort' ifTrue:[
-            parseBlock value: stream nextLine.
-            ^ self.
-        ].
-    ].
-    "/ parse `hg: parse error: some error messsage` error format introduced in Mercurial 4.3
-    c == $h ifTrue:[
-        word := stream upTo: $:.
-        word = 'hg' ifTrue:[
-            stream next. "/eat space
-            c := stream peek.
-            c == $p ifTrue:[
-                self expect: 'parse error: '.
-                parseBlock value: stream nextLine.                
-                ^ self.
-            ].
-        ].
-    ].
-
-
-    "/ Special hack for mercurial_keyring extension, sigh...
-    line := stream nextLine.
-    "/ If c == $a we may have already read some data. In that case,
-    "/ word is not nil and we have to preprend it to line read just above...
-    word notNil ifTrue:[ 
-        line := word , (line ? '')
-    ].
-
-    (line includesSubString: 'mercurial_keyring.py') ifTrue:[
-        (line endsWith: 'UserWarning: Basic Auth Realm was unquoted') ifTrue:[
-            stream nextLine.
-        ].
-        ^ self.
-    ].
-    self notify: 'Unexpected error output: ', line.
-    ^ self.
-
-    "Created: / 06-11-2014 / 00:28:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 07-11-2014 / 23:47:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 17-10-2017 / 09:55:50 / jv"
-!
-
 parseError: parseBlock
     [ stream atEnd ] whileFalse:[
         self parseError1: parseBlock.  
@@ -1251,21 +1181,6 @@
     "Created: / 04-02-2013 / 12:21:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-parseErrorLog
-    ^self parseError: [:msg |
-        | errCls |
-
-        (msg startsWith: 'unknown revision ''') ifTrue:[
-            errCls := HGUnknownRevisionError.
-        ] ifFalse:[
-            errCls := HGPushError
-        ].
-        self propagate: errCls message: msg
-    ].
-
-    "Created: / 09-02-2014 / 10:21:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
 parseErrorPush
     ^self parseError: [:msg |
         (msg startsWith: 'push creates new remote head ') ifTrue:[
@@ -1287,6 +1202,97 @@
     "Modified: / 26-03-2014 / 15:39:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!HGCommandParser methodsFor:'parsing - errors - private'!
+
+parseError1: parseBlock
+    "/ Parse at most one error from stream and returs.
+
+    | c word line |
+
+    c := stream peek.
+    c isNil ifTrue:[ ^ self ]. "/ stream closed / already at end
+
+    "/ Care for "*** failed to import extension" messages...
+    c == $* ifTrue:[ 
+        stream next.
+        c := stream peek.
+        c == $* ifTrue:[ 
+            stream next.
+            c := stream peek.
+            c == $* ifTrue:[ 
+                stream next.
+                self notify: stream nextLine.
+                ^ self.
+            ].
+        ].
+        self notify: stream nextLine.
+        ^ self.
+    ].
+    "/ parse `abort: some error messsage` error format
+    c == $a ifTrue:[
+        word := stream upTo: $:.
+        stream next. "/eat space
+        word = 'abort' ifTrue:[
+            self parseError1: parseBlock message: stream nextLine.              
+            ^ self.
+        ].
+    ].
+    "/ parse `hg: parse error: some error messsage` error format introduced in Mercurial 4.3
+    c == $h ifTrue:[
+        word := stream upTo: $:.
+        word = 'hg' ifTrue:[
+            stream next. "/eat space
+            c := stream peek.
+            c == $p ifTrue:[
+                self expect: 'parse error: '.
+                self parseError1: parseBlock message: stream nextLine.                
+                ^ self.
+            ].
+        ].
+    ].
+
+
+    "/ Special hack for mercurial_keyring extension, sigh...
+    line := stream nextLine.
+    "/ If c == $a we may have already read some data. In that case,
+    "/ word is not nil and we have to preprend it to line read just above...
+    word notNil ifTrue:[ 
+        line := word , (line ? '')
+    ].
+
+    (line includesSubString: 'mercurial_keyring.py') ifTrue:[
+        (line endsWith: 'UserWarning: Basic Auth Realm was unquoted') ifTrue:[
+            stream nextLine.
+        ].
+        ^ self.
+    ].
+    self notify: 'Unexpected error output: ', line.
+    ^ self.
+
+    "Created: / 06-11-2014 / 00:28:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 17-10-2017 / 09:55:50 / jv"
+    "Modified: / 08-02-2018 / 08:51:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+parseError1: parseBlock message: errorMessage
+    "Parse given `errorMmessage` using `parseBlock`. Handle common errors here,
+     pass the rest to the parseBlock to handle."
+
+    (errorMessage startsWith: 'unknown revision ''') ifTrue:[
+        | rev err |
+
+        rev := HGChangesetId readFrom: (errorMessage readStream skip: 'unknown revision ''' size) onError:[ nil ].
+        err := HGUnknownRevisionError newException
+                    parameter: rev;
+                    messageText: errorMessage; yourself.
+        self propagate: err.
+        ^ self.
+    ].
+    parseBlock value: errorMessage
+
+    "Created: / 08-02-2018 / 08:51:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !HGCommandParser methodsFor:'parsing - files'!
 
 parseDotHgBookmarks
--- a/mercurial/HGCommandParserTests.st	Mon Jan 01 20:27:19 2018 +0000
+++ b/mercurial/HGCommandParserTests.st	Thu Feb 08 09:09:51 2018 +0000
@@ -722,6 +722,16 @@
 ') parseErrorCommit ] raise: HGCommitError
 
     "Created: / 17-10-2017 / 09:46:09 / jv"
+!
+
+test_error_04
+    "Test for Mercurial >= 4.3 that introduced new format of errors (see below).
+     Sigh."
+
+    self should:[ (HGCommandParser on: 'abort: unknown revision ''96DB65258808720D8D5EA6CB7A6A4D4F4E467325''!!\' withCRs) parseError ] 
+         raise: HGUnknownRevisionError suchThat:[ :ex | ex parameter = '96DB65258808720D8D5EA6CB7A6A4D4F4E467325' asHGChangesetId ]
+
+    "Created: / 08-02-2018 / 08:32:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !HGCommandParserTests methodsFor:'tests - misc'!