Eskil

Check-in [20868060ad]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Reworked extraction of files from patch, to make it work in all supported systems.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:20868060adbbe6f893cc3dae99be913a746289bdef7fcca0b983cf281071fefe
User & Date: peter 2019-02-04 23:09:19
Context
2019-02-04
23:39
Better layout for file selection in commit. check-in: 9c39a2ca72 user: peter tags: trunk
23:09
Reworked extraction of files from patch, to make it work in all supported systems. check-in: 20868060ad user: peter tags: trunk
16:17
Bug fix in file select check-in: 433fedb7d2 user: peter tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/eskil.tcl.

1093
1094
1095
1096
1097
1098
1099
1100




1101










1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
....
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
    set leftLine 1
    set rightLine 1
    set leftLines {}
    set rightLines {}
    set state none
    set fname ""
    foreach line [split $data \n] {
        # Detect a new file




        if {[string match ======* $line] || [string match "diff *" $line]} {










            if {$state != "none"} {
                displayOnePatch $top $leftLines $rightLines $leftLine $rightLine
            }
            set leftLines {}
            set rightLines {}
            set state none
            continue
        }
        # Detect a file name
        if {[string match "Index: *" $line]} {

            # If fname is set, a file that had no contents has passed.
            # It could be a binary file or some other that the diffing source
            # could not handle.
            # Display the name to see that it is involved. 
            if {$fname ne ""} {
                foreach side {1 2} {
                    emptyLine $top $side
                    insertLine $top $side "" $divider patch
                    insertLine $top $side "" $fname   patch
                    insertLine $top $side "" $divider patch
                }
                addChange $top 4 change 0 0 0 0
            }
            set fname [string range $line 7 end]
            # Collect the files seen. Used by revision control for commit.
            if {[file isfile $fname]} {
                lappend ::eskil($top,patchFilelist) $fname
            }
        }
        # Detect the first line in a -c style diff
        if {[regexp {^\*\*\* } $line]} {
            if {$state eq "right"} {
                displayOnePatch $top $leftLines $rightLines $leftLine $rightLine
                set leftLines {}
                set rightLines {}
................................................................................
            emptyLine $top $side
            insertLine $top $side "" $divider patch
            insertLine $top $side "" $fname   patch
            insertLine $top $side "" $divider patch
        }
        addChange $top 4 change 0 0 0 0
    }

    # Cleanup detected files
    set ::eskil($top,patchFilelist) [lsort -dictionary -unique \
                                             $::eskil($top,patchFilelist)]
}

#####################################
# Main diff
#####################################

# Prepare for a diff by creating needed temporary files







|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>






<

<
<
>













|
|
|
|
<







 







<
<
<
<







1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122


1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143
1144
1145
1146
1147
....
1287
1288
1289
1290
1291
1292
1293




1294
1295
1296
1297
1298
1299
1300
    set leftLine 1
    set rightLine 1
    set leftLines {}
    set rightLines {}
    set state none
    set fname ""
    foreach line [split $data \n] {
        # Detect a new file or file name
        # "diff *" handles at least GIT and HG output
        # "Index:" and "=====*" handles at least FOSSIL and SVN output
        set newFile 0
        set newName ""
        if {[string match ======* $line]} {
            set newFile 1
        } elseif {[string match "diff *" $line]} {
            set newFile 1
            # Extract the last non-space. Works reasonably well.
            regexp {\S+\s*$} $line newName
        } elseif {[string match "Index: *" $line]} {
            set newName [string range $line 7 end]
        }

        if {$newFile} {
            if {$state != "none"} {
                displayOnePatch $top $leftLines $rightLines $leftLine $rightLine
            }
            set leftLines {}
            set rightLines {}
            set state none

        }


        if {$newName ne ""} {
            # If fname is set, a file that had no contents has passed.
            # It could be a binary file or some other that the diffing source
            # could not handle.
            # Display the name to see that it is involved. 
            if {$fname ne ""} {
                foreach side {1 2} {
                    emptyLine $top $side
                    insertLine $top $side "" $divider patch
                    insertLine $top $side "" $fname   patch
                    insertLine $top $side "" $divider patch
                }
                addChange $top 4 change 0 0 0 0
            }
            set fname $newName
        }
        if {$newFile || $newName ne ""} {
            continue

        }
        # Detect the first line in a -c style diff
        if {[regexp {^\*\*\* } $line]} {
            if {$state eq "right"} {
                displayOnePatch $top $leftLines $rightLines $leftLine $rightLine
                set leftLines {}
                set rightLines {}
................................................................................
            emptyLine $top $side
            insertLine $top $side "" $divider patch
            insertLine $top $side "" $fname   patch
            insertLine $top $side "" $divider patch
        }
        addChange $top 4 change 0 0 0 0
    }




}

#####################################
# Main diff
#####################################

# Prepare for a diff by creating needed temporary files

Changes to src/rev.tcl.

43
44
45
46
47
48
49
50
51
52
53
54
55



56
57
58
59
60
61
62
63
...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423


































424
425
426
427
428
429
430
...
460
461
462
463
464
465
466
467
468
469
470
471
472

473
474
475
476
477














478
479
480
481
482
483
484
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
...
598
599
600
601
602
603
604













605
606
607
608
609
610
611
...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674











675
676
677
678
679
680
681
...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
....
1674
1675
1676
1677
1678
1679
1680

1681


1682
1683
1684
1685
1686
1687
1688
....
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820

# eskil::rev::XXX::get {filename outfile rev}
#
# Get a revision of a file and place it in outfile.
# rev is in any format understood by this system, and
# should be retrieved from ParseRevs

# eskil::rev::XXX::getPatch {revs {files {}}}
#
# Get a patch of the file tree, between the revisions given.
# revs is in any format understood by this system, and
# should be retrieved from ParseRevs
# An optional list of files that should be included can be given.



# Note that current directory must be correct before calling.

# eskil::rev::XXX::getChangedFiles {dir revs}
#
# Get a list of files changed between the revisions given.
# revs is in any format understood by this system, and
# should be retrieved from ParseRevs

................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a CVS patch
proc eskil::rev::CVS::getPatch {revs {files {}}} {
    if {$::Pref(context) > 0} {
        set context $::Pref(context)
    } else {
        set context 5
    }
    # TODO: support files
    set cmd [list exec cvs diff -U $context]
................................................................................
        if {[regexp {^(\S+)\s+(\S+)$} $line -> pre file]} {
            lappend changes [file join $dir $file]
        }
    }
    return $changes
}

# Get a SVN patch
proc eskil::rev::SVN::getPatch {revs {files {}}} {
    set cmd [list exec svn diff]
    foreach rev $revs {
        # TODO: What happens in strange combinations ?
        if {[string match "*://*" $rev]} {
            # Full URL
            lappend cmd $rev
        } else {
            lappend cmd -r $rev
        }
    }
    lappend cmd {*}$files

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "SVN error" -message $res
        return ""
    }
    return $res
}

proc eskil::rev::SVN::getChangedFiles {dir revs} {
    # Must call SVN in top dir to get full changeset
    GetTopDir $dir top tail
    set cmd [list execDir $top svn diff --summarize]
    set revs2 {}
    foreach rev $revs {
        # TODO: What happens in strange combinations ?
        if {[string match "*://*" $rev]} {
            # Full URL
            lappend cmd $rev
        } else {
            lappend revs2 $rev
        }
    }
    if {[llength $revs2] > 0} {
        lappend cmd -r [join $revs2 :]
    }



































    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "SVN error" -message $res
        return ""
    }
    # Result is one file per line, with an info word before
    set files {}
................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a HG patch
proc eskil::rev::HG::getPatch {revs {files {}}} {
    # TODO: support files
    set cmd [list exec hg diff]
    foreach rev $revs {
        lappend cmd -r $rev
    }


    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "HG error" -message $res
        return ""
    }














    return $res
}

proc eskil::rev::HG::getChangedFiles {dir revs} {
    set cmd [list execDir $dir hg diff --stat]
    foreach rev $revs {
        lappend cmd -r $rev
................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a BZR patch
proc eskil::rev::BZR::getPatch {revs {files {}}} {
    # TODO: support files
    set cmd [list exec bzr diff]
    if {[llength $revs] == 2} {
        lappend cmd -r [lindex $revs 0]..[lindex $revs 1]
    } elseif {[llength $revs] == 1} {
        lappend cmd -r [lindex $revs 0]
    }
................................................................................
# Get an RCS revision
proc eskil::rev::RCS::get {filename outfile {rev {}}} {
    catch {exec co -p$rev [file nativename $filename] \
            > $outfile}
}

# Get a RCS patch
proc eskil::rev::RCS::getPatch {revs {files {}}} {
    # Not supported yet.
    return ""
}

proc eskil::rev::RCS::getChangedFiles {dir revs} {
    # Not supported yet.
    return ""
................................................................................
# Add file to GIT index
proc eskil::rev::GIT::add {filename} {
    GetTopDir $filename dir tail
    catch {execDir $dir git add $tail}
}

# Get a GIT patch
proc eskil::rev::GIT::getPatch {revs {files {}}} {
    set cmd [list exec git diff -p]
    if {[llength $revs] == 0} {
        # Always default to HEAD to see changes regardless of index
        lappend cmd HEAD
    } else {
        foreach rev $revs {
            lappend cmd $rev
................................................................................
    }
    lappend cmd "--" {*}$files

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "GIT error" -message $res
        return ""
    }













    return $res
}

# Get a GIT change set
proc eskil::rev::GIT::getChangedFiles {dir revs} {
    set cmd [list execDir $dir git diff --name-only]
    if {[llength $revs] == 0} {
................................................................................
        catch {execDir $dir fossil finfo -p $tail > $outfile}
    } else {
        catch {execDir $dir fossil finfo -p $tail -r $rev > $outfile}
    }
}

# Get a FOSSIL patch
proc eskil::rev::FOSSIL::getPatch {revs {files {}}} {
    set cmd [list exec fossil diff]

    if {[llength $revs] >= 1} {
        lappend cmd --from [lindex $revs 0]
    }
    if {[llength $revs] >= 2} {
        lappend cmd --to [lindex $revs 1]
    }
    if {[llength $files] > 0} {
        # Fossil diff only handles one file at a time.
        set res ""
        foreach file $files {
            set fcmd $cmd
            lappend fcmd $file
            if {[catch {eval $fcmd} fres]} {
                tk_messageBox -icon error -title "FOSSIL error" -message $fres
                return ""
            }
            # Fake the per-file rows
            append res "Index: $file\n==================================\n"
            append res $fres
        }
    } else {
        # Include added files contents
        lappend cmd -N
        if {[catch {eval $cmd} res]} {
            tk_messageBox -icon error -title "FOSSIL error" -message $res
            return ""
        }











    }
    return $res
}

proc eskil::rev::FOSSIL::getChangedFiles {dir revs} {
    set cmd [list execDir $dir fossil diff]

................................................................................
    if {[catch {exec cleartool get -to $outfile $filerev} msg]} {
        tk_messageBox -icon error -title "Cleartool error" -message $msg
        return
    }
}

# Get a CT patch
proc eskil::rev::CT::getPatch {revs {files {}}} {
    # Not supported yet
    return ""
}

proc eskil::rev::CT::getChangedFiles {dir revs} {
    # Not supported yet
    return ""
................................................................................
            $::widgets($top,commit) configure -state normal
        }
        if {[info commands eskil::rev::${type}::revertFile] ne ""} {
            $::widgets($top,revert) configure -state normal
        }
    }


    return [eskil::rev::${type}::getPatch $revs $files]


}

##############################################################################
# Utilities
##############################################################################

# Execute a command within a specific dir as pwd
................................................................................
    }

    set res [string trim $::eskil(logdialog)]
    set ::eskil(logdialog) $res

    set todo $postcmd
    if {[llength $postcmd] > 1} {

        set todo {}
        set t 0
        foreach fileName $postcmd {
            if {$::eskil($top,commit,fileselect$t)} {
                lappend todo $fileName
            }
            incr t
        }
        # None left means skip.
        if {[llength $todo] == 0} {
            return
        }
    }

    # Splash screen for visual feedback
    set now [clock clicks -milliseconds]







|




|
>
>
>
|







 







|







 







|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<




>





>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|








|
<
<
<
<
|
<
<
<
|
<
<
|
|
<
<
<
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>







 







|







 







>
|
>
>







 







>








|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
...
382
383
384
385
386
387
388
389
390
391






















392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
...
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696




697



698


699
700



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
...
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
....
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
....
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865

# eskil::rev::XXX::get {filename outfile rev}
#
# Get a revision of a file and place it in outfile.
# rev is in any format understood by this system, and
# should be retrieved from ParseRevs

# eskil::rev::XXX::getPatch {revs files {fileListName {}}}
#
# Get a patch of the file tree, between the revisions given.
# revs is in any format understood by this system, and
# should be retrieved from ParseRevs
# If files is non-empty it is a list of files that should be included.
# If fileListName is given, it is a variable name where to place the
# list of files affected by the patch. The list should be cleaned
# through lsort -dictionary -unique.
# NOTE that current directory must be correct before calling.

# eskil::rev::XXX::getChangedFiles {dir revs}
#
# Get a list of files changed between the revisions given.
# revs is in any format understood by this system, and
# should be retrieved from ParseRevs

................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a CVS patch
proc eskil::rev::CVS::getPatch {revs files {fileListName {}}} {
    if {$::Pref(context) > 0} {
        set context $::Pref(context)
    } else {
        set context 5
    }
    # TODO: support files
    set cmd [list exec cvs diff -U $context]
................................................................................
        if {[regexp {^(\S+)\s+(\S+)$} $line -> pre file]} {
            lappend changes [file join $dir $file]
        }
    }
    return $changes
}

# Common helper for SVN revisions
proc eskil::rev::SVN::RevsToCmd {revs} {
    set cmd {}






















    set revs2 {}
    foreach rev $revs {
        # TODO: What happens in strange combinations ?
        if {[string match "*://*" $rev]} {
            # Full URL
            lappend cmd $rev
        } else {
            lappend revs2 $rev
        }
    }
    if {[llength $revs2] > 0} {
        lappend cmd -r [join $revs2 :]
    }
    return $cmd
}

# Get a SVN patch
proc eskil::rev::SVN::getPatch {revs files {fileListName {}}} {
    set cmd [list exec svn diff]
    lappend cmd {*}[RevsToCmd $revs]
    lappend cmd {*}$files

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "SVN error" -message $res
        return ""
    }
    if {$fileListName ne ""} {
        upvar 1 $fileListName fileList
        set fileList {}
        # SVN will have lines like this to show files:
        #Index: dir1/f11
        foreach line [lsearch -all -inline -regexp [split $res \n] {^Index: }] {
            if {[regexp {Index: (.*)} $line -> fn]} {
                lappend fileList $fn
            }
        }
        set fileList [lsort -dictionary -unique $fileList]
    }

    return $res
}

proc eskil::rev::SVN::getChangedFiles {dir revs} {
    # Must call SVN in top dir to get full changeset
    GetTopDir $dir top tail
    set cmd [list execDir $top svn diff --summarize]
    lappend cmd {*}[RevsToCmd $revs]

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "SVN error" -message $res
        return ""
    }
    # Result is one file per line, with an info word before
    set files {}
................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a HG patch
proc eskil::rev::HG::getPatch {revs files {fileListName {}}} {

    set cmd [list exec hg diff]
    foreach rev $revs {
        lappend cmd -r $rev
    }
    lappend cmd "--" {*}$files

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "HG error" -message $res
        return ""
    }
    if {$fileListName ne ""} {
        upvar 1 $fileListName fileList
        set fileList {}
        # HG will have lines like this to show files:
        #diff -r 533b1d848a1c dir1/f12
        #diff -r 0dba7b280f8f -r 2e84355cc419 f1
        foreach line [lsearch -all -inline -regexp [split $res \n] {^diff -}] {
            if {[regexp {diff (?:-r \w+\s+)*(.*)$} $line -> fn]} {
                lappend fileList $fn
            }
        }
        set fileList [lsort -dictionary -unique $fileList]
    }

    return $res
}

proc eskil::rev::HG::getChangedFiles {dir revs} {
    set cmd [list execDir $dir hg diff --stat]
    foreach rev $revs {
        lappend cmd -r $rev
................................................................................

    if {$old != ""} {
        cd $old
    }
}

# Get a BZR patch
proc eskil::rev::BZR::getPatch {revs files {fileListName {}}} {
    # TODO: support files
    set cmd [list exec bzr diff]
    if {[llength $revs] == 2} {
        lappend cmd -r [lindex $revs 0]..[lindex $revs 1]
    } elseif {[llength $revs] == 1} {
        lappend cmd -r [lindex $revs 0]
    }
................................................................................
# Get an RCS revision
proc eskil::rev::RCS::get {filename outfile {rev {}}} {
    catch {exec co -p$rev [file nativename $filename] \
            > $outfile}
}

# Get a RCS patch
proc eskil::rev::RCS::getPatch {revs files {fileListName {}}} {
    # Not supported yet.
    return ""
}

proc eskil::rev::RCS::getChangedFiles {dir revs} {
    # Not supported yet.
    return ""
................................................................................
# Add file to GIT index
proc eskil::rev::GIT::add {filename} {
    GetTopDir $filename dir tail
    catch {execDir $dir git add $tail}
}

# Get a GIT patch
proc eskil::rev::GIT::getPatch {revs files {fileListName {}}} {
    set cmd [list exec git diff -p]
    if {[llength $revs] == 0} {
        # Always default to HEAD to see changes regardless of index
        lappend cmd HEAD
    } else {
        foreach rev $revs {
            lappend cmd $rev
................................................................................
    }
    lappend cmd "--" {*}$files

    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "GIT error" -message $res
        return ""
    }
    if {$fileListName ne ""} {
        upvar 1 $fileListName fileList
        set fileList {}
        # GIT will have lines like this to show files:
        #diff --git a/dir1/f12 b/dir1/f12
        foreach line [lsearch -all -inline -regexp [split $res \n] {^diff -}] {
            if {[regexp { a/(.*) b/} $line -> fn]} {
                lappend fileList $fn
            }
        }
        set fileList [lsort -dictionary -unique $fileList]
    }
    
    return $res
}

# Get a GIT change set
proc eskil::rev::GIT::getChangedFiles {dir revs} {
    set cmd [list execDir $dir git diff --name-only]
    if {[llength $revs] == 0} {
................................................................................
        catch {execDir $dir fossil finfo -p $tail > $outfile}
    } else {
        catch {execDir $dir fossil finfo -p $tail -r $rev > $outfile}
    }
}

# Get a FOSSIL patch
proc eskil::rev::FOSSIL::getPatch {revs files {fileListName {}}} {
    set cmd [list exec fossil diff]

    if {[llength $revs] >= 1} {
        lappend cmd --from [lindex $revs 0]
    }
    if {[llength $revs] >= 2} {
        lappend cmd --to [lindex $revs 1]
    }
    # Include added files contents




    lappend cmd -N






    lappend cmd {*}$files




    if {[catch {eval $cmd} res]} {
        tk_messageBox -icon error -title "FOSSIL error" -message $res
        return ""
    }
    if {$fileListName ne ""} {
        upvar 1 $fileListName fileList
        set fileList {}
        # FOSSIL will have lines like this to show files:
        #Index: dir1/f11
        foreach line [lsearch -all -inline -regexp [split $res \n] {^Index: }] {
            if {[regexp {Index: (.*)} $line -> fn]} {
                lappend fileList $fn
            }
        }
        set fileList [lsort -dictionary -unique $fileList]
    }
    return $res
}

proc eskil::rev::FOSSIL::getChangedFiles {dir revs} {
    set cmd [list execDir $dir fossil diff]

................................................................................
    if {[catch {exec cleartool get -to $outfile $filerev} msg]} {
        tk_messageBox -icon error -title "Cleartool error" -message $msg
        return
    }
}

# Get a CT patch
proc eskil::rev::CT::getPatch {revs files {fileListName {}}} {
    # Not supported yet
    return ""
}

proc eskil::rev::CT::getChangedFiles {dir revs} {
    # Not supported yet
    return ""
................................................................................
            $::widgets($top,commit) configure -state normal
        }
        if {[info commands eskil::rev::${type}::revertFile] ne ""} {
            $::widgets($top,revert) configure -state normal
        }
    }

    set fileList {}
    set patch [eskil::rev::${type}::getPatch $revs $files fileList]
    set ::eskil($top,patchFilelist) $fileList
    return $patch
}

##############################################################################
# Utilities
##############################################################################

# Execute a command within a specific dir as pwd
................................................................................
    }

    set res [string trim $::eskil(logdialog)]
    set ::eskil(logdialog) $res

    set todo $postcmd
    if {[llength $postcmd] > 1} {
        # Look through checkbuttons
        set todo {}
        set t 0
        foreach fileName $postcmd {
            if {$::eskil($top,commit,fileselect$t)} {
                lappend todo $fileName
            }
            incr t
        }
        # None left means ignore.
        if {[llength $todo] == 0} {
            return
        }
    }

    # Splash screen for visual feedback
    set now [clock clicks -milliseconds]

Changes to tests/rev.test.

341
342
343
344
345
346
347







348
349
350
351
352
353
354
...
390
391
392
393
394
395
396


397
398
399
400

401
402
403
404
405
406
407
408
409
410


411
412
413
414

415
416
417
418
419
420
421
...
448
449
450
451
452
453
454























































455
456
}
proc Fill3 {} {
    cd $::work
    exec echo Nisse > dir1/f11
    exec echo Hult  > dir2/f21
    exec echo Lingonben >> f1
}








proc CreateRepo {type} {
    set repoDir [tmpFile]
    file mkdir $repoDir
    switch $type {
        FOSSIL {
            set repo $repoDir/apa.fossil
................................................................................
        HG     { exec hg  add {*}[glob *]}
    }
    exec {*}$cmt "First"
    Fill2
    exec {*}$cmt "Second"
    Fill3
    exec {*}$cmt "Third"



    # Any cleanup?
    switch $type {
        SVN { exec svn update }

    }
}

foreach type {FOSSIL GIT SVN HG} {
    test rev-4.$type.1 {
        Setup fake repo
    } -body {
        CreateRepo $type
        # Dump info for debug of setup
        if 0 {


            switch $type {
                FOSSIL { puts [exec fossil timeline -v] }
                GIT    { puts [exec git log --name-only] }
                SVN    { puts [exec svn log --verbose] }

            }
        }
        list
    }

    test rev-4.$type.2 {
        GetTopDir
................................................................................
    } -body {
        cd ~
        set f $::work/f1
        set revs [eskil::rev::${type}::ParseRevs $f "-1 0"]
        lsort -dictionary [eskil::rev::${type}::getChangedFiles $f $revs]
    } -match regexp -result {^/\S+/dir1/f11 /\S+/dir2/f21 /\S+/f1$}
























































    clearTmp
}







>
>
>
>
>
>
>







 







>
>




>










>
>




>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
}
proc Fill3 {} {
    cd $::work
    exec echo Nisse > dir1/f11
    exec echo Hult  > dir2/f21
    exec echo Lingonben >> f1
}
proc Fill4 {} {
    cd $::work
    exec echo Musse > dir1/f11
    exec echo Pigg  > dir1/f12
    exec echo Mimmi >> dir2/f21
    exec echo Pluto >> f2
}

proc CreateRepo {type} {
    set repoDir [tmpFile]
    file mkdir $repoDir
    switch $type {
        FOSSIL {
            set repo $repoDir/apa.fossil
................................................................................
        HG     { exec hg  add {*}[glob *]}
    }
    exec {*}$cmt "First"
    Fill2
    exec {*}$cmt "Second"
    Fill3
    exec {*}$cmt "Third"
    # Local changes
    Fill4

    # Any cleanup?
    switch $type {
        SVN { exec svn update }
        FOSSIL {exec fossil status --sha1sum}
    }
}

foreach type {FOSSIL GIT SVN HG} {
    test rev-4.$type.1 {
        Setup fake repo
    } -body {
        CreateRepo $type
        # Dump info for debug of setup
        if 0 {
            puts "------------------- $type --------------------"
            puts "--- $::work"
            switch $type {
                FOSSIL { puts [exec fossil timeline -v] }
                GIT    { puts [exec git log --name-only] }
                SVN    { puts [exec svn log --verbose] }
                HG     { puts [exec hg log --verbose] }
            }
        }
        list
    }

    test rev-4.$type.2 {
        GetTopDir
................................................................................
    } -body {
        cd ~
        set f $::work/f1
        set revs [eskil::rev::${type}::ParseRevs $f "-1 0"]
        lsort -dictionary [eskil::rev::${type}::getChangedFiles $f $revs]
    } -match regexp -result {^/\S+/dir1/f11 /\S+/dir2/f21 /\S+/f1$}

    test rev-4.$type.16 {
        getPatch, list of files
    } -body {
        # getPatch needs to be in the checkout
        cd $::work
        set files [list $::work/dir1 $::work/f1 $::work/f2]
        if {$type in "SVN"} {
            # SVN gives full paths when given full paths
            set expect [list $::work/dir1/f11 $::work/dir1/f12 $::work/f2]
        } else {
            set expect [list dir1/f11 dir1/f12 f2]
        }
        set expect [lsort -dictionary $expect]
        set patch [eskil::rev::${type}::getPatch {} $files outFileList]
        if {$outFileList ne $expect} {
            return $outFileList ;#$patch
        } else {
            return 1
        }
    } -result 1

    test rev-4.$type.7 {
        getPatch, list of files
    } -body {
        # getPatch needs to be in the checkout
        cd $::work
        set files [list dir1 f1 f2]
        set expect [list dir1/f11 dir1/f12 f2]
        set expect [lsort -dictionary $expect]
        set patch [eskil::rev::${type}::getPatch {} $files outFileList]
        if {$outFileList ne $expect} {
            return $outFileList ;#$patch
        } else {
            return 1
        }
    } -result 1

    test rev-4.$type.8 {
        getPatch, list of files
    } -body {
        # getPatch needs to be in the checkout
        cd $::work
        set f f1
        set revs [eskil::rev::${type}::ParseRevs $f "-1 0"]
        set files [list dir1 f1 f2]
        set expect [list dir1/f11 f1]
        set expect [lsort -dictionary $expect]
        set patch [eskil::rev::${type}::getPatch $revs $files outFileList]
        if {$outFileList ne $expect} {
            return $outFileList ;#$patch
        } else {
            return 1
        }
    } -result 1
    
    clearTmp
}