# HG changeset patch # User Jan Vrany # Date 1518080991 0 # Node ID ef00a1303f735244d6b166e35857692a9e4ae8a2 # Parent b890f24db9f0155b1ef8ce7a4f3f47324c917dc8 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. diff -r b890f24db9f0 -r ef00a1303f73 mercurial/HGChangesetId.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 " "Modified: / 13-07-2016 / 18:15:12 / Jan Vrany " + "Modified (comment): / 08-02-2018 / 08:41:50 / Jan Vrany " ! ! !HGChangesetId class methodsFor:'accessing'! diff -r b890f24db9f0 -r ef00a1303f73 mercurial/HGCommand.st --- 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 " ! -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 " -! - parseOutput:stream "Parses output of 'hg' command, i.e. commit, log, update, checkout, etc." diff -r b890f24db9f0 -r ef00a1303f73 mercurial/HGCommandParser.st --- 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 " ! -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 " - "Modified: / 07-11-2014 / 23:47:52 / Jan Vrany " - "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 " ! -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 " -! - 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 " ! ! +!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 " + "Modified: / 17-10-2017 / 09:55:50 / jv" + "Modified: / 08-02-2018 / 08:51:24 / Jan Vrany " +! + +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 " +! ! + !HGCommandParser methodsFor:'parsing - files'! parseDotHgBookmarks diff -r b890f24db9f0 -r ef00a1303f73 mercurial/HGCommandParserTests.st --- 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 " ! ! !HGCommandParserTests methodsFor:'tests - misc'!