Eskil

Check-in [9b0b8b820c]
Login

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

Overview
Comment:Include a file selector when committing multiple files.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:9b0b8b820ca6f2768c03b59243ffb336223ed483c48970429f3bc38f2c696259
User & Date: peter 2019-02-04 15:55:53
Context
2019-02-04
15:56
Document default print settings. check-in: c07ac8613c user: peter tags: trunk
15:55
Include a file selector when committing multiple files. check-in: 9b0b8b820c user: peter tags: trunk
15:52
Handle a dir name with -review. check-in: 8ecbca03a0 user: peter tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Changes.





1
2
3
4
5
6
7
8
9




2018-10-03
Handle deleted files in GIT vcsvfs

2018-09-23
 Upgraded tablelist to 6.3

2018-06-20
 Added save-reload option in edit mode.
 Upgraded tablelist to 6.2
>
>
>
>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
2019-02-04
 Include a file selector when committing multiple files.
 Allow directory with -review.

2018-10-03
 Handle deleted files in GIT vcsvfs

2018-09-23
 Upgraded tablelist to 6.3

2018-06-20
 Added save-reload option in edit mode.
 Upgraded tablelist to 6.2

Changes to src/dirdiff.tcl.

45
46
47
48
49
50
51

























52
53
54
55
56
57
58
...
101
102
103
104
105
106
107

108


109

110
111
112
113
114
115
116
...
154
155
156
157
158
159
160

161
162

163
164
165
166
167
168
169
...
170
171
172
173
174
175
176

177
178

179
180
181
182
183
184
185
...
434
435
436
437
438
439
440

441
442
443
444
445
446
447
...
904
905
906
907
908
909
910

911
912
913
914
915
916
917
    return 1
}

# Sort file names
proc Fsort {l} {
    lsort -dictionary $l
}


























# Compare two files or dirs
# Return true if equal
proc CompareFiles {file1 file2} {
    if {[catch {file lstat $file1 stat1}]} {
        return 0
    }
................................................................................
    }

    switch $::Pref(dir,comparelevel) {
        2 -
        1 { # Check contents internally
            set bufsz 65536
            set eq 2 ;# 2 = equal this far, 1 = equal, 0 = not equal

            set ch1 [open $file1 r]


            set ch2 [open $file2 r]

            if {$::Pref(dir,comparelevel) == 2} {
                fconfigure $ch1 -translation binary
                fconfigure $ch2 -translation binary
            }
            # Allow a plugin to do its thing
            if {$anyPlugin} {
                #puts "PLUGIN!"
................................................................................
                } else {
                    if {![string equal $f1 $f2]} {
                        set eq 0
                    }
                }
            }
            while {$eq == 2 && ![eof $ch1] && ![eof $ch2]} {

                set f1 [read $ch1 $bufsz]
                set f2 [read $ch2 $bufsz]

                if {$nocase} {
                    if {![string equal -nocase $f1 $f2]} {
                        set eq 0
                    }
                } else {
                    if {![string equal $f1 $f2]} {
                        set eq 0
................................................................................
                    }
                }
            }
            if {$eq == 2 && (![eof $ch1] || ![eof $ch2])} {
                set eq 0
            }
            # Errors during close are not interesting

            catch {close $ch1}
            catch {close $ch2}

        }
    }
    return [expr {$eq != 0}]
}

# Returns the contents of a directory as a sorted list of full file paths.
proc DirContents {dir} {
................................................................................
            set DebugCh ""
            set DebugTime {}
        }
        # Uncomment to activate debug logging
        #set DebugCh [open ~/dirdiff.log a]
        #$self DlogTablelist
        $self Dlog RESTART

        set AfterId ""
        set IdleQueue {}
        set ScheduledRestart 0
        array unset IdleQueueArr
        set protect {left 0 right 0}

        # Directory Diff only supports one plugin.
................................................................................
            } else {
                set statusvar "$rightfull  ($count)"
            }

            $self Dlog Reschedule
            set AfterId [after $AfterTime [mymethod UpdateIdle]]
        } else {

            $self Dlog DONE
            set statusvar ""
            set AfterId ""
        }
    }

    method SetNodeStatus {node status} {







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







 







>

>
>

>







 







>


>







 







>


>







 







>







 







>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
    return 1
}

# Sort file names
proc Fsort {l} {
    lsort -dictionary $l
}

set ::profList [list CompareFiles eskil::rev::SVN::mount]
proc InitProf {} {
    foreach n $::profList {
        trace add execution $n {enter} [list DoProfEnter $n]
        trace add execution $n {leave} [list DoProfLeave $n]
    }
    set ::prof(start) [clock milliseconds]
}
proc DoProfEnter {point args} {
    set ::prof($point,enter) [clock milliseconds]
}
proc DoProfLeave {point args} {
    set dur [expr { [clock milliseconds] - $::prof($point,enter)}]
    incr ::prof($point,dur) $dur
}
proc EndProf {} {
    set ::prof(end) [clock milliseconds]
    set ::prof(dur) [expr {$::prof(end) - $::prof(start)}]
    foreach n $::profList {
        trace remove execution $n {enter} [list DoProfEnter $n]
        trace remove execution $n {leave} [list DoProfLeave $n]
    }
    parray ::prof
}

# Compare two files or dirs
# Return true if equal
proc CompareFiles {file1 file2} {
    if {[catch {file lstat $file1 stat1}]} {
        return 0
    }
................................................................................
    }

    switch $::Pref(dir,comparelevel) {
        2 -
        1 { # Check contents internally
            set bufsz 65536
            set eq 2 ;# 2 = equal this far, 1 = equal, 0 = not equal
            DoProfEnter OpenFile1
            set ch1 [open $file1 r]
            DoProfLeave OpenFile1
            DoProfEnter OpenFile2
            set ch2 [open $file2 r]
            DoProfLeave OpenFile2
            if {$::Pref(dir,comparelevel) == 2} {
                fconfigure $ch1 -translation binary
                fconfigure $ch2 -translation binary
            }
            # Allow a plugin to do its thing
            if {$anyPlugin} {
                #puts "PLUGIN!"
................................................................................
                } else {
                    if {![string equal $f1 $f2]} {
                        set eq 0
                    }
                }
            }
            while {$eq == 2 && ![eof $ch1] && ![eof $ch2]} {
                DoProfEnter ReadIt
                set f1 [read $ch1 $bufsz]
                set f2 [read $ch2 $bufsz]
                DoProfLeave ReadIt
                if {$nocase} {
                    if {![string equal -nocase $f1 $f2]} {
                        set eq 0
                    }
                } else {
                    if {![string equal $f1 $f2]} {
                        set eq 0
................................................................................
                    }
                }
            }
            if {$eq == 2 && (![eof $ch1] || ![eof $ch2])} {
                set eq 0
            }
            # Errors during close are not interesting
            DoProfEnter Close
            catch {close $ch1}
            catch {close $ch2}
            DoProfLeave Close
        }
    }
    return [expr {$eq != 0}]
}

# Returns the contents of a directory as a sorted list of full file paths.
proc DirContents {dir} {
................................................................................
            set DebugCh ""
            set DebugTime {}
        }
        # Uncomment to activate debug logging
        #set DebugCh [open ~/dirdiff.log a]
        #$self DlogTablelist
        $self Dlog RESTART
        InitProf
        set AfterId ""
        set IdleQueue {}
        set ScheduledRestart 0
        array unset IdleQueueArr
        set protect {left 0 right 0}

        # Directory Diff only supports one plugin.
................................................................................
            } else {
                set statusvar "$rightfull  ($count)"
            }

            $self Dlog Reschedule
            set AfterId [after $AfterTime [mymethod UpdateIdle]]
        } else {
            EndProf
            $self Dlog DONE
            set statusvar ""
            set AfterId ""
        }
    }

    method SetNodeStatus {node status} {

Changes to src/eskil.tcl.

1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
....
1118
1119
1120
1121
1122
1123
1124




1125
1126
1127
1128
1129
1130
1131
....
1271
1272
1273
1274
1275
1276
1277




1278
1279
1280
1281
1282
1283
1284
    mapNoChange $top 0
}

# Read a patch file and display it
proc displayPatch {top} {
    set ::eskil($top,leftLabel) "Patch $::eskil($top,patchFile): old"
    set ::eskil($top,rightLabel) "Patch $::eskil($top,patchFile): new"

    update idletasks

    if {$::eskil($top,patchFile) eq ""} {
        if {$::eskil($top,patchData) eq ""} {
            set data [getFullPatch $top]
        } else {
            set data $::eskil($top,patchData)
................................................................................
                    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]




        }
        # 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







>







 







>
>
>
>







 







>
>
>
>







1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
....
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
    mapNoChange $top 0
}

# Read a patch file and display it
proc displayPatch {top} {
    set ::eskil($top,leftLabel) "Patch $::eskil($top,patchFile): old"
    set ::eskil($top,rightLabel) "Patch $::eskil($top,patchFile): new"
    set ::eskil($top,patchFilelist) {}
    update idletasks

    if {$::eskil($top,patchFile) eq ""} {
        if {$::eskil($top,patchData) eq ""} {
            set data [getFullPatch $top]
        } else {
            set data $::eskil($top,patchData)
................................................................................
                    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

Changes to src/rev.tcl.

1608
1609
1610
1611
1612
1613
1614





1615

1616
1617
1618
1619
1620
1621
1622
....
1726
1727
1728
1729
1730
1731
1732





1733
1734
1735
1736
1737
1738
1739
....
1759
1760
1761
1762
1763
1764
1765















1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
















1776
1777
1778
1779
1780
1781
1782
    set ::eskil($top,leftFile) $::eskil($top,RevFile)
}

proc revCommit {top} {
    if {[$::widgets($top,commit) cget -state] eq "disabled"} return
    set type $::eskil($top,modetype)
    if {$::eskil($top,mode) eq "patch"} {





        set files $::eskil($top,reviewFiles)

    } else {
        set files [list $::eskil($top,RevFile)]
    }
    eskil::rev::${type}::commitFile $top {*}$files
}

proc revRevert {top} {
................................................................................
        return $last
    } else {
        return [file join $penultimate $last]
    }
}

# Dialog for commit, getting log message





proc CommitDialog {top target system precmd postcmd {useSts 0}} {
    set w $top.logmsg
    destroy  $w
    toplevel $w -padx 3 -pady 3
    wm title $w "Commit log message for $target"

    set ::eskil($top,logdialogok) 0
................................................................................
    bind $w <Alt-c> [list destroy $w]\;break
    bind $w <Key-Escape> [list destroy $w]\;break

    grid $w.t  - -sticky news -padx 3 -pady 3
    grid $w.ok $w.ca -padx 3 -pady 3
    grid columnconfigure $w $w.t -weight 1 -uniform a
    grid rowconfigure    $w $w.t -weight 1















    tkwait visibility $w
    focus -force $w.t
    tkwait window $w.dummy

    if {!$::eskil($top,logdialogok)} {
        return
    }

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

















    # Splash screen for visual feedback
    set now [clock clicks -milliseconds]
    ttk::label $w.splash -text "Committing" -anchor center -font myfont
    place $w.splash -x 0 -y 0 -relwidth 1.0 -relheight 1.0
    update
    # Commit







>
>
>
>
>
|
>







 







>
>
>
>
>







 







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










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







1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
....
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
....
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
    set ::eskil($top,leftFile) $::eskil($top,RevFile)
}

proc revCommit {top} {
    if {[$::widgets($top,commit) cget -state] eq "disabled"} return
    set type $::eskil($top,modetype)
    if {$::eskil($top,mode) eq "patch"} {
        if {[llength $::eskil($top,patchFilelist)] != 0} {
            # Use the list extracted from patch
            set files $::eskil($top,patchFilelist)
        } else {
            # Use the list given by user
            set files $::eskil($top,reviewFiles)
        }
    } else {
        set files [list $::eskil($top,RevFile)]
    }
    eskil::rev::${type}::commitFile $top {*}$files
}

proc revRevert {top} {
................................................................................
        return $last
    } else {
        return [file join $penultimate $last]
    }
}

# Dialog for commit, getting log message
# target: String shown in dialog
# system: Rev System
# precmd: Command part before message
# postcmd: Command part after message. Assumed to be files.
# useSts: Use status from exec rather than message to recognise error.
proc CommitDialog {top target system precmd postcmd {useSts 0}} {
    set w $top.logmsg
    destroy  $w
    toplevel $w -padx 3 -pady 3
    wm title $w "Commit log message for $target"

    set ::eskil($top,logdialogok) 0
................................................................................
    bind $w <Alt-c> [list destroy $w]\;break
    bind $w <Key-Escape> [list destroy $w]\;break

    grid $w.t  - -sticky news -padx 3 -pady 3
    grid $w.ok $w.ca -padx 3 -pady 3
    grid columnconfigure $w $w.t -weight 1 -uniform a
    grid rowconfigure    $w $w.t -weight 1

    if {[llength $postcmd] > 1} {
        # TODO: Scrolled frame
        ttk::frame $w.f -padding 1
        set t 0
        foreach fileName $postcmd {
            set ::eskil($top,commit,fileselect$t) 1
            ttk::checkbutton $w.f.cb$t -text $fileName \
                    -variable ::eskil($top,commit,fileselect$t)
            grid $w.f.cb$t -sticky "w" -padx 1 -pady 1
            incr t
        }
        grid $w.f -sticky news -padx 3 -pady 3
    }

    tkwait visibility $w
    focus -force $w.t
    tkwait window $w.dummy

    if {!$::eskil($top,logdialogok)} {
        return
    }

    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]
    ttk::label $w.splash -text "Committing" -anchor center -font myfont
    place $w.splash -x 0 -y 0 -relwidth 1.0 -relheight 1.0
    update
    # Commit