Ticket #305: libscm_fix_1_of_1_rev_935264ad298a_Rework_and_fix_HGSourceCodeManager_____revisionLogOf____directory_module__.patch

File libscm_fix_1_of_1_rev_935264ad298a_Rework_and_fix_HGSourceCodeManager_____revisionLogOf____directory_module__.patch, 11.5 KB (added by jan vrany, 3 years ago)
  • mercurial/HGSourceCodeManager.st

    # HG changeset patch
    # User Jan Vrany <jan.vrany@labware.com>
    # Date 1613723381 0
    #      Fri Feb 19 08:29:41 2021 +0000
    # Node ID 935264ad298af5260a0e566cdbad4a5cb341ccbe
    # Parent  ed037226b5684fc4017d4948a5700a3931bb0dc3
    Rework and fix HGSourceCodeManager >> #revisionLogOf:...directory:module:`
    
    This commit changes the logic in two ways:
    
     1. #newestRevision is now the newest revision in the branch that
        *contains* given file (not necesarily modidfes it). If there are
        multiple heads in that branch, pretty much random one is returned.
    
        This changes old behavior and therefore this commit updates
        tests.
    
     2. If a specific single revision is requested, i.e., both from and to revisions
        are the same, revision log with that single revision is returned
        no matter whether it modifies the file or even contains that file
        at all. This is essentially a workaround to fix issue #305.
    
    Moreover, this commit simplifies the code a lot by delegating all the
    changeset searching and filtering to mercurial using revset expressions.
    
    See https://swing.fit.cvut.cz/projects/stx-jv/ticket/305#comment:3
    
    diff -r ed037226b568 -r 935264ad298a mercurial/HGSourceCodeManager.st
    a b  
    11"
    22stx:libscm - a new source code management library for Smalltalk/X
    33Copyright (C) 2012-2015 Jan Vrany
    4 Copyright (C) 2020 LabWare
     4Copyright (C) 2020-2021 LabWare
    55
    66This library is free software; you can redistribute it and/or
    77modify it under the terms of the GNU Lesser General Public
     
    3434"
    3535stx:libscm - a new source code management library for Smalltalk/X
    3636Copyright (C) 2012-2015 Jan Vrany
    37 Copyright (C) 2020 LabWare
     37Copyright (C) 2020-2021 LabWare
    3838
    3939This library is free software; you can redistribute it and/or
    4040modify it under the terms of the GNU Lesser General Public
     
    297297    "Actually do return a revisionLog. The main worker method. This must be implemented by a
    298298     concrete source-code manager. The interface of this method is just crazy!!
    299299
    300      If numRevisionsOrNil is notNil, it limits the number of revision records returned -
    301      only numRevions of the newest revision infos will be collected.
     300     If `limitOrNil` is notNil, it limits the number of revision records returned -
     301     only `limitOrNil` of the newest revision infos will be collected.
    302302
    303303     The returned information is a structure (IdentityDictionary)
    304304     filled with:
     
    330330            revisions are ordered newest first
    331331            (i.e. the last entry is for the initial revision; the first for the most recent one)
    332332            Attention: if state = 'dead' that revision is no longer valid.
     333
     334     WARNING: The interface, apart from being crazy, is also designed upon assumption
     335     that file has been changed in all revisions. This is essentially true only for
     336     CVS (per-file versioning) and does not hold for any modern SCM. Also, it does to take
     337     branches into an account. And so on.
     338
     339     Therefore here we do some really nasty hacks to make sure we answer what's expected
     340     by various and many callers and hope it will appear to work. There's little else to
     341     do here, the problem is the *broken-by-design* interface of source code manager API.     
    333342    "
    334343
    335     | pkg repo path wcentry info newest oldest startRev stopRev limit log revs startRevIndex stopRevIndex revIndex |
     344    | pkg repo path wcentry info newestRev log revs |
    336345
    337346    info := IdentityDictionary new.
    338347    pkg := HGPackageWorkingCopy named: (moduleDir , ':' , packageDir).
     
    343352        self breakPoint: #jv info: 'Ooops, could not found given file in working copy. Changeset scanning not yet implemented. You may proceed wot'.
    344353        ^ nil
    345354    ].
    346     revs := (rev1OrNil == 0 and:[rev2OrNil == 0])
    347         ifTrue:[((wcentry changeset / path / classFileName) newer: true) collect:[:f|f changeset]]
    348         ifFalse:[wcentry revisions collect:[:f|f changeset]].
    349     revs isEmpty ifTrue:[revs add: wcentry changeset].
    350     newest := revs first.
    351     oldest := revs last.
     355
     356    "/ Here, the newest revision for 'header' is always the newest revision
     357    "/ in the same branch that contains (not neccesarrily modifies!!) the class.
     358    "/ Does not care about multiple heads within branch, just return "some", but
     359    "/ there's not much else to do due to the method interface.
     360    "/
     361    "/ Hope that's okay with callers.
     362    revs := repo changesetsMatching: ('last(contains("%1") and branch("%2"),1)'
     363                                                bindWith: wcentry pathNameRelative
     364                                                    with: repo workingCopy branch name).
     365    self assert: revs size == 1.
     366    newestRev := revs first.
    352367
    353368    info at:#container          put: classFileName.         "/ -> the revision string
    354369    info at:#cvsRoot            put: repo pathName.         "/ -> the CVS root (repository)
    355370    info at:#filename           put: classFileName.         "/ -> the actual source file name
    356     info at:#newestRevision     put: newest id printString. "/-> the revisionString of the newest revision
    357     info at:#numberOfRevisions  put: newest id revno.
     371    info at:#newestRevision     put: newestRev id printString. "/ -> the revisionString of the newest revision
     372    info at:#numberOfRevisions  put: newestRev id revno.
     373
     374"/    (rev1OrNil == 0 and:[rev2OrNil == 0]) ifTrue:[
     375"/        ^ info
     376"/    ].
     377
     378    (rev1OrNil notNil and:[ rev1OrNil = rev2OrNil ]) ifTrue: [
     379        "/ If we're asked for specific revision, return just that one
     380        "/ *NO MATTER* whether it modifies the class or not.
     381        revs := Array with: repo @ rev1OrNil.
     382    ] ifFalse: [
     383        "/ If we're asked for revision range, only return those in that
     384        "/ range that *ACTUALLY MODIFIES* the file.
    358385
    359     (rev1OrNil == 0 and:[rev2OrNil == 0]) ifTrue:[
    360         limit := 1.
    361         startRev := newest.
    362         stopRev := newest.
    363     ] ifFalse:[
    364         limit := limitOrNil ? (revs size) .
    365         startRev := rev1OrNil isNil ifTrue:[newest] ifFalse:[repo @ rev1OrNil].
    366         stopRev  := rev2OrNil isNil ifTrue:[oldest] ifFalse:[repo @ rev2OrNil].
     386        | from to revset |
     387
     388        from := rev2OrNil isNil ifTrue:['0'] ifFalse:[rev2OrNil].
     389        to  := rev1OrNil isNil ifTrue:['tip'] ifFalse:[rev1OrNil].
     390
     391        revset := '%1:%2 and file("%3") and branch("%4")'
     392                                                bindWith: from
     393                                                    with: to
     394                                                    with: wcentry pathNameRelative
     395                                                    with: repo workingCopy branch name.
     396        limitOrNil notNil ifTrue: [
     397            revset := 'last(%1, %2)' bindWith: revset with: limitOrNil
     398        ].
     399
     400        revs := repo changesetsMatching: revset.
    367401    ].
     402
    368403    log := OrderedCollection new.
    369404
    370     startRevIndex := revs indexOf: startRev.
    371     stopRevIndex := revs indexOf: stopRev.
    372     limit := limit min: (stopRevIndex - startRevIndex + 1).
     405    revs reverseDo: [:rev |
     406        | entry |
    373407
    374     revIndex := startRevIndex.
    375     limit timesRepeat:[
    376         | entry rev |
    377         rev := revs at: revIndex.
    378         entry :=  IdentityDictionary new.
     408        entry := IdentityDictionary new.
    379409        entry at:#revision              put: rev id printString."/ -> the revision string
    380410        entry at:#author                put: rev author."/ -> who checked that revision into the repository
    381411        entry at:#date                  put: rev timestamp printString."/ -> when was it checked in
     
    383413        entry at:#numberOfChangedLines  put: 'N/A'. "/ -> the number of changed line w.r.t the previous
    384414        entry at:#logMessage            put: rev message."/ -> the checkIn log message.
    385415        log add: entry.
    386 
    387         revIndex := revIndex + 1.
    388416    ].
    389417    info at: #revisions put: log.
    390418
    391419    ^info
    392420
    393421    "Modified: / 24-04-2016 / 13:19:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     422    "Modified: / 19-02-2021 / 07:54:22 / Jan Vrany <jan.vrany@labware.com>"
    394423! !
    395424
    396425!HGSourceCodeManager class methodsFor:'queries'!
  • mercurial/HGStXTests.st

    diff -r ed037226b568 -r 935264ad298a mercurial/HGStXTests.st
    a b  
    42654265
    42664266!HGStXTests methodsFor:'tests - manager API'!
    42674267
     4268test_issue_305a
     4269    | rev log |
     4270
     4271    rev := HGSourceCodeManager newestRevisionOf: HGTestCase. 
     4272    log := HGSourceCodeManager revisionLogOf:HGTestCase fromRevision:rev toRevision: rev.
     4273
     4274    "Created: / 18-02-2021 / 20:45:30 / Jan Vrany <jan.vrany@labware.com>"
     4275!
     4276
    42684277test_log_01
    42694278
    42704279    | log repo |
     
    44624471
    44634472    self assert: (log at: #container) = 'MocksHGP6Bar.st'.
    44644473    self assert: (log at: #cvsRoot) = repo pathName.
    4465     self assert: (log at: #newestRevision) = '4:f71dfc6c6f9b'.
     4474    self assert: (log at: #newestRevision) = '6:7d0045fb7dba'.
    44664475    self assert: (log at: #revisions) size == 1.
    44674476    self assert: ((log at: #revisions) first at:#revision) = '0:c76faa501252'.
    44684477
    44694478    "Created: / 11-02-2014 / 11:31:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    44704479    "Modified: / 11-02-2014 / 12:58:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4480    "Modified: / 19-02-2021 / 07:55:27 / Jan Vrany <jan.vrany@labware.com>"
    44714481!
    44724482
    44734483test_log_05b
     
    44914501
    44924502    self assert: (log at: #container) = 'MocksHGP6Foo.st'.
    44934503    self assert: (log at: #cvsRoot) = repo pathName.
    4494     self assert: (log at: #newestRevision) = '0:c76faa501252'.
     4504    self assert: (log at: #newestRevision) = '6:7d0045fb7dba'.
    44954505    self assert: (log at: #revisions) size == 1.
    44964506    self assert: ((log at: #revisions) first at:#revision) = '0:c76faa501252'.
    44974507
    44984508    "Created: / 11-02-2014 / 11:34:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    44994509    "Modified: / 11-02-2014 / 13:55:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4510    "Modified: / 19-02-2021 / 07:55:45 / Jan Vrany <jan.vrany@labware.com>"
    45004511!
    45014512
    45024513test_newestRevisionOf_01
     
    45074518
    45084519    rev := HGSourceCodeManager newestRevisionOf: (Smalltalk at: #MocksHGP6Bar).
    45094520
    4510     self assert: rev = '4:f71dfc6c6f9b'.
     4521    self assert: rev = '6:7d0045fb7dba'.
    45114522
    45124523    "Created: / 24-04-2016 / 11:41:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4524    "Modified: / 19-02-2021 / 07:11:46 / Jan Vrany <jan.vrany@labware.com>"
    45134525!
    45144526
    45154527test_newestRevisionOf_02
     
    45204532
    45214533    rev := HGSourceCodeManager newestRevisionOf: (Smalltalk at: #MocksHGP6Bar).
    45224534
    4523     self assert: rev = '4:f71dfc6c6f9b'.
     4535    self assert: rev = '6:7d0045fb7dba'.
    45244536
    45254537    "Created: / 24-04-2016 / 11:46:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4538    "Modified: / 19-02-2021 / 07:14:03 / Jan Vrany <jan.vrany@labware.com>"
    45264539!
    45274540
    45284541test_newestRevisionOf_03a
     
    45334546
    45344547    rev := HGSourceCodeManager newestRevisionOf: (Smalltalk at: #MocksHGP6Foo).
    45354548
    4536     self assert: rev = '2:581b3cabbf8f'.
     4549    self assert: rev = '6:7d0045fb7dba'.
    45374550
    45384551    "Created: / 24-04-2016 / 11:47:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4552    "Modified: / 19-02-2021 / 07:12:32 / Jan Vrany <jan.vrany@labware.com>"
    45394553!
    45404554
    45414555test_newestRevisionOf_03b
     
    45514565        package: 'mocks:hg/p6'.
    45524566    rev := HGSourceCodeManager newestRevisionOf: (Smalltalk at: #MocksHGP6Foo).
    45534567
    4554     self assert: rev = '4:f71dfc6c6f9b'.
     4568    self assert: rev = '6:7d0045fb7dba'.
    45554569
    45564570    "Created: / 24-04-2016 / 11:48:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     4571    "Modified: / 19-02-2021 / 07:13:11 / Jan Vrany <jan.vrany@labware.com>"
    45574572!
    45584573
    45594574test_newestRevisionOf_03c