Eskil

Check-in [89f6168b65]
Login

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

Overview
Comment:Extended Mercurial support to commit, revert, log and directory diff.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 89f6168b651af2d50834fda200587ea29e306678
User & Date: peter 2015-03-15 21:16:32.882
Context
2015-03-15
23:56
Started on separator support for tables check-in: 4c8f6d2ad7 user: peter tags: trunk
21:16
Extended Mercurial support to commit, revert, log and directory diff. check-in: 89f6168b65 user: peter tags: trunk
2015-03-13
22:43
Use fossil ls -r if available. check-in: 2fe5c1905a user: peter tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to Changes.



1
2
3
4
5
6
7



2015-03-09
 Released 2.7

2015-03-06
 Generate release files for Mac, now when DiffUtil supports Mac.

2015-03-01
>
>
>







1
2
3
4
5
6
7
8
9
10
2015-03-15
 Extended Mercurial support to commit, revert, log and directory diff.

2015-03-09
 Released 2.7

2015-03-06
 Generate release files for Mac, now when DiffUtil supports Mac.

2015-03-01
Changes to doc/revision.txt.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<pre>git diff -p --diff-filter=M master | eskil -</pre>

<ul>View all changes</ul>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.
E.g. in a Mercurial directory, these show the same thing:
<pre>eskil -preview</pre>
<pre>hg diff | eskil -</pre>

If file names are given after -review, only the listed files are included. If supported,
the Commit button will be enabled allowing the viewed differences to be committed.

<ul>RCS/CVS</ul>








|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<pre>git diff -p --diff-filter=M master | eskil -</pre>

<ul>View all changes</ul>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.
E.g. in a Mercurial directory, these show the same thing:
<pre>eskil -review</pre>
<pre>hg diff | eskil -</pre>

If file names are given after -review, only the listed files are included. If supported,
the Commit button will be enabled allowing the viewed differences to be committed.

<ul>RCS/CVS</ul>

76
77
78
79
80
81
82












83
84
85
86
87
88
89
follows the current branch from the current version.

<pre>fossil settings gmerge-command 'eskil -fine -a "%baseline" "%merge" "%original" -o "%output"' -global</pre>

<ul>Mercurial</ul>

For Mercurial -r works as in "hg cat -r".













<ul>Bazaar</ul>

For Bazaar -r works as in "bzr cat -r".

<ul>ClearCase</ul>








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







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
follows the current branch from the current version.

<pre>fossil settings gmerge-command 'eskil -fine -a "%baseline" "%merge" "%original" -o "%output"' -global</pre>

<ul>Mercurial</ul>

For Mercurial -r works as in "hg cat -r".
However, Eskil interprets zero or negative numbers as going back from the tip, i.e. -1 is one step back, corresponding to -2 in Mercurial.

Mercurial is supported in the Directory Diff, however the displayed file sizes
and dates are faked since the current implementation cannot extract that
information from the repository. The fake numbers are taken from the file's
sha1 and thus is unique per file and gives a correct result in comparison.

To use Eskil for conflict resolution these config settings can be used.

[merge-tools]
eskil.args = -fine -a $base $other $local -o $output
eskil.priority = 1

<ul>Bazaar</ul>

For Bazaar -r works as in "bzr cat -r".

<ul>ClearCase</ul>

Changes to htdocs/fossil.wiki.
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
directly to Fossil.

<h2>View all changes</h2>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.

<verbatim>eskil -preview [files] </verbatim>

If file names are given after -review, only the listed files are included.
The Commit button will be enabled allowing the viewed differences to be
committed directly from Eskil.

<h2>Conflict merging</h2>
Eskil can be used as the conflict resolution tool for Fossil by configuring







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
directly to Fossil.

<h2>View all changes</h2>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.

<verbatim>eskil -review [files] </verbatim>

If file names are given after -review, only the listed files are included.
The Commit button will be enabled allowing the viewed differences to be
committed directly from Eskil.

<h2>Conflict merging</h2>
Eskil can be used as the conflict resolution tool for Fossil by configuring
Changes to htdocs/revision.wiki.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<pre>git diff -p --diff-filter=M master | eskil -</pre>

<h1>View all changes</h1>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.

<verbatim>eskil -preview [files] </verbatim>

E.g. in a Mercurial directory, these show the same thing:

<pre>eskil -preview</pre>
<pre>hg diff | eskil -</pre>

If file names are given after -review, only the listed files are included.
If supported, the Commit button will be enabled allowing the viewed differences
to be committed directly from Eskil.

<h1>Conflict merging</h1>







|



|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<pre>git diff -p --diff-filter=M master | eskil -</pre>

<h1>View all changes</h1>

If the command line option -review is used, Eskil will generate a patch
for the current tree and display it as in patch mode.

<verbatim>eskil -review [files] </verbatim>

E.g. in a Mercurial directory, these show the same thing:

<pre>eskil -review</pre>
<pre>hg diff | eskil -</pre>

If file names are given after -review, only the listed files are included.
If supported, the Commit button will be enabled allowing the viewed differences
to be committed directly from Eskil.

<h1>Conflict merging</h1>
112
113
114
115
116
117
118
119












120
121
122
123
124
125
126

To use Eskil for conflict resolution these settings can be used.

<pre>fossil settings gmerge-command 'eskil -fine -a "%baseline" "%merge" "%original" -o "%output"' -global</pre>

<h2>Mercurial</h2>

For Mercurial -r works as in "hg cat -r".













<h2>Bazaar</h2>

For Bazaar -r works as in "bzr cat -r".

<h2>ClearCase</h2>








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







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

To use Eskil for conflict resolution these settings can be used.

<pre>fossil settings gmerge-command 'eskil -fine -a "%baseline" "%merge" "%original" -o "%output"' -global</pre>

<h2>Mercurial</h2>

For Mercurial -r mostly works as in "hg cat -r".
However, Eskil interprets zero or negative numbers as going back from the tip, i.e. -1 is one step back, corresponding to -2 in Mercurial.

Mercurial is supported in the Directory Diff, however the displayed file sizes
and dates are faked since the current implementation cannot extract that
information from the repository. The fake numbers are taken from the file's
sha1 and thus is unique per file and gives a correct result in comparison.

To use Eskil for conflict resolution these config settings can be used.

[merge-tools]
eskil.args = -fine -a $base $other $local -o $output
eskil.priority = 1

<h2>Bazaar</h2>

For Bazaar -r works as in "bzr cat -r".

<h2>ClearCase</h2>

Changes to src/rev.tcl.
718
719
720
721
722
723
724






725
726
727
728
729
730
731
732
    return $result
}

# Figure out HG revision from arguments
proc eskil::rev::HG::ParseRevs {filename revs} {
    set result ""
    foreach rev $revs {






        # No parsing yet...
        lappend result $rev
    }
    return $result
}

# Figure out BZR revision from arguments
proc eskil::rev::BZR::ParseRevs {filename revs} {







>
>
>
>
>
>
|







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
    return $result
}

# Figure out HG revision from arguments
proc eskil::rev::HG::ParseRevs {filename revs} {
    set result ""
    foreach rev $revs {
        # HG internally supports negative numbers for backwards search
        # though -1 means current. Translate to Eskil notation by adding one
        if {[string is integer $rev] && $rev < 0} {
            incr rev -1
        }
        if {$rev eq "_" || $rev eq "0"} {set rev tip}

        lappend result $rev
    }
    return $result
}

# Figure out BZR revision from arguments
proc eskil::rev::BZR::ParseRevs {filename revs} {
975
976
977
978
979
980
981




















982
983
984
985
986
987
988
    set sts [catch {exec svn -q commit -m $logmsg {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "SVN commit error" -message $svnmsg \
                -parent $top
    }
}





















# Check in GIT controlled file
proc eskil::rev::GIT::commitFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]







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







981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
    set sts [catch {exec svn -q commit -m $logmsg {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "SVN commit error" -message $svnmsg \
                -parent $top
    }
}

# Check in HG controlled file
proc eskil::rev::HG::commitFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]
    } else {
        set target "[file tail [lindex $args 0]] ..."
    }        
    set logmsg [LogDialog $top $target]
    if {$logmsg eq ""} return

    set sts [catch {exec hg -q commit -m $logmsg {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "HG commit error" -message $svnmsg \
                -parent $top
    }
}

# Check in GIT controlled file
proc eskil::rev::GIT::commitFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]
1046
1047
1048
1049
1050
1051
1052























1053
1054
1055
1056
1057
1058
1059
    set sts [catch {exec svn revert -q {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "SVN revert error" -message $svnmsg \
                -parent $top
    }
}
























# Revert Fossil controlled file
proc eskil::rev::FOSSIL::revertFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]







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







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
    set sts [catch {exec svn revert -q {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "SVN revert error" -message $svnmsg \
                -parent $top
    }
}

# Revert HG controlled file
proc eskil::rev::HG::revertFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]
    } else {
        set target "[file tail [lindex $args 0]] ..."
    }        
    set ok [RevertDialog $top $target]
    if {$ok ne "ok"} return

    if {[llength $args] == 0} {
        set args "--all"
    }
    set sts [catch {exec hg revert -q -C {*}$args} svnmsg]
    set svnmsg [string trim $svnmsg]
    if {$svnmsg ne ""} {
        tk_messageBox -icon error -title "HG revert error" -message $svnmsg \
                -parent $top
    }
}

# Revert Fossil controlled file
proc eskil::rev::FOSSIL::revertFile {top args} {
    if {[llength $args] == 0} {
        set target all
    } elseif {[llength $args] == 1} {
        set target [file tail [lindex $args 0]]
1099
1100
1101
1102
1103
1104
1105





1106
1107
1108
1109
1110
1111
1112
    return [vcsvfs::fossil::mount $dir $rev]
}

# Mount a directory revision as a VFS, and return the mount point
proc eskil::rev::SVN::mount {dir rev} {
    return [vcsvfs::svn::mount $dir $rev]
}






# Mount a directory revision as a VFS, and return the mount point
proc eskil::rev::GIT::mount {dir rev} {
    return [vcsvfs::git::mount $dir $rev]
}

# View log between displayed versions







>
>
>
>
>







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
    return [vcsvfs::fossil::mount $dir $rev]
}

# Mount a directory revision as a VFS, and return the mount point
proc eskil::rev::SVN::mount {dir rev} {
    return [vcsvfs::svn::mount $dir $rev]
}

# Mount a directory revision as a VFS, and return the mount point
proc eskil::rev::HG::mount {dir rev} {
    return [vcsvfs::hg::mount $dir $rev]
}

# Mount a directory revision as a VFS, and return the mount point
proc eskil::rev::GIT::mount {dir rev} {
    return [vcsvfs::git::mount $dir $rev]
}

# View log between displayed versions
1128
1129
1130
1131
1132
1133
1134













1135
1136
1137
1138
1139
1140
1141
proc eskil::rev::SVN::viewLog {top filename revs} {
    set cmd [list exec svn log]
    if {[llength $revs] > 1} {
        lappend cmd -r [join $revs ":"]
    } else {
        lappend cmd -r HEAD:[lindex $revs 0]
    }













    lappend cmd $filename
    if {[catch {eval $cmd} result]} {
        #return
    }
    ViewLog $top $filename $result
}








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







1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
proc eskil::rev::SVN::viewLog {top filename revs} {
    set cmd [list exec svn log]
    if {[llength $revs] > 1} {
        lappend cmd -r [join $revs ":"]
    } else {
        lappend cmd -r HEAD:[lindex $revs 0]
    }
    lappend cmd $filename
    if {[catch {eval $cmd} result]} {
        #return
    }
    ViewLog $top $filename $result
}

# View log between displayed versions
proc eskil::rev::HG::viewLog {top filename revs} {
    set cmd [list exec hg log]
    foreach rev $revs {
        lappend cmd -r $rev
    }
    lappend cmd $filename
    if {[catch {eval $cmd} result]} {
        #return
    }
    ViewLog $top $filename $result
}

Changes to src/vcsvfs.tcl.
11
12
13
14
15
16
17

18
19
20
21
22
23
24

namespace eval vcsvfs {
    variable DataRefChan
    variable mpoints {}
    namespace eval fossil {}
    namespace eval svn {}
    namespace eval git {}

}

# Create a Virtual File System showing a revision of a fossil checkout
#
# dir: Directory in a fossil checkout
# rev: Revision to mount
#







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

namespace eval vcsvfs {
    variable DataRefChan
    variable mpoints {}
    namespace eval fossil {}
    namespace eval svn {}
    namespace eval git {}
    namespace eval hg {}
}

# Create a Virtual File System showing a revision of a fossil checkout
#
# dir: Directory in a fossil checkout
# rev: Revision to mount
#
338
339
340
341
342
343
344









































































345
346
347
348
349
350
351

proc vcsvfs::svn::unmount {dir} {
    variable ::vcsvfs::mpoints
    # TBD: Find the mountpoint
    #dict unset mpoints $mountpoint
    #vfs::filesystem unmount $mountpoint
}










































































# Create a Virtual File System showing a revision of a GIT checkout
#
# dir: Directory in an GIT checkout
# rev: Revision to mount
#
# Returns: path to the generated VFS







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







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
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

proc vcsvfs::svn::unmount {dir} {
    variable ::vcsvfs::mpoints
    # TBD: Find the mountpoint
    #dict unset mpoints $mountpoint
    #vfs::filesystem unmount $mountpoint
}

# Create a Virtual File System showing a revision of a HG checkout
#
# dir: Directory in an HG checkout
# rev: Revision to mount
#
# Returns: path to the generated VFS
proc vcsvfs::hg::mount {dir rev} {
    variable ::vcsvfs::mpoints
    set dir [file normalize $dir]

    # Command must be run within the dir, so temporarily change pwd
    set oldpwd [pwd]
    cd $dir

    # The mount point will normally be at the wc root, even if
    # a sub directory was given.
    # Locate root for the given directory.
    set root [exec hg root]
    # TBD: Always root at given dir, for speed
    #set root .
    #set root [file normalize $root]
    #cd $root

    # Getting files via manifest
    set allfiles [exec hg manifest --debug -r $rev]
    # Expected line format:
    # sha1sum perms *? name
    foreach line [split $allfiles \n] {
        # Each line is one file name
        regexp {^(\S+)\s+\S+\s+\*?\s*(\S.*)$} $line -> sha fName
        dict set finfo $fName isfile 1
        dict set finfo $fName isdir 0
        dict set finfo $fName "sha" $sha
        dict set finfo $fName type file
        # Fake mtime and size from sha, to make same look same
        dict set finfo $fName mtime [scan [string range $sha 0 6] %x]
        dict set finfo $fName size  [scan [string range $sha 7 9] %x]
        # Mark all known directory paths and build up file tree info
        set parentStr ""
        foreach dirPath [file split $fName] {
            dict set finfo $parentStr child $dirPath 1
            dict set finfo $parentStr isfile 0
            dict set finfo $parentStr isdir 1
            dict set finfo $parentStr type directory
            set parentStr [file join $parentStr $dirPath]
        }
    }

    # TBD: Any way to get file sizes and mtimes from HG?

    cd $oldpwd

    # Generate a mount point.
    set tail [string range $dir [string length $root] end]
    set mountpoint "${root} ($rev)"

    dict set mpoints $mountpoint "finfo" $finfo
    dict set mpoints $mountpoint "origroot" $root
    dict set mpoints $mountpoint "rev" $rev
    dict set mpoints $mountpoint "vcstype" hg
    vfs::filesystem mount $mountpoint [list vcsvfs::Vfs]

    set result $mountpoint$tail
    return $result
}

proc vcsvfs::hg::unmount {dir} {
    variable ::vcsvfs::mpoints
    # TBD: Find the mountpoint
    #dict unset mpoints $mountpoint
    #vfs::filesystem unmount $mountpoint
}

# Create a Virtual File System showing a revision of a GIT checkout
#
# dir: Directory in an GIT checkout
# rev: Revision to mount
#
# Returns: path to the generated VFS
514
515
516
517
518
519
520












521
522
523
524
525
526
527
proc vcsvfs::svn::openFile {rootD relative mode} {
    set oldpwd [pwd]
    cd [dict get $rootD "origroot"]
    set rev [dict get $rootD rev]
    # Read through a pipe to get requested mode
    set chId [open [list |svn cat -r $rev $relative] $mode]
    cd $oldpwd













    return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}

# Some notes about git commands that can be good to have
proc vcsvfs::git::openFile {rootD relative mode} {
    set oldpwd [pwd]







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







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
proc vcsvfs::svn::openFile {rootD relative mode} {
    set oldpwd [pwd]
    cd [dict get $rootD "origroot"]
    set rev [dict get $rootD rev]
    # Read through a pipe to get requested mode
    set chId [open [list |svn cat -r $rev $relative] $mode]
    cd $oldpwd

    return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}

# Extract file data from HG revision
proc vcsvfs::hg::openFile {rootD relative mode} {
    set oldpwd [pwd]
    cd [dict get $rootD "origroot"]
    set rev [dict get $rootD rev]
    # Read through a pipe to get requested mode
    set chId [open [list |hg cat -r $rev $relative] $mode]
    cd $oldpwd

    return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}

# Some notes about git commands that can be good to have
proc vcsvfs::git::openFile {rootD relative mode} {
    set oldpwd [pwd]