35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
35
36
37
38
39
40
41
42
43
44
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
|
-
+
-
+
+
+
+
+
+
+
+
+
+
+
|
# a sub directory was given.
# Locate fossil root for the given directory.
set info [exec fossil info]
regexp -line {local-root:\s*(\S.*)} $info -> root
set root [file normalize $root]
cd $root
# Getting files via artifact
# Getting files via manifest artifact
# This is a quick and robust way to get the file tree and each file's sha
# Other info is trickier and is handled below
set artifact [exec fossil artifact $rev]
set commitTime 0
set cTime now
set finfo {}
foreach line [split $artifact \n] {
set todo [split $artifact \n]
while {[llength $todo] > 0} {
set line [lindex $todo 0]
set todo [lrange $todo 1 end]
# Expected format in a line:
# B baseline
# F tests/left.txt c1572b3809a1ba6ab2de9307c96b1cfeefdcf0ba
# D 2015-02-23T23:30:07.509
if {[regexp {B (.*)} $line -> bUuid]} {
# Pick up a baseline manifest and parse it first
set artifact [exec fossil artifact $bUuid]
set todo [concat [split $artifact \n] $todo]
continue
}
if {[regexp {D (.*)} $line -> cTime]} {
# Remove decimals and middle T
regsub {\.\d+} $cTime "" cTime
regsub {T} $cTime " " cTime
set commitTime [clock scan $cTime -gmt 1]
}
if {[regexp {F (\S+) (\S+)} $line -> fName fSha]} {
|
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
525
526
527
|
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
525
526
527
|
-
+
-
-
+
+
-
-
-
-
+
-
-
+
+
-
-
-
-
+
-
-
-
+
+
-
-
-
|
if {[dict get $finfo $local isdir] && !$allowDir} continue
lappend result [file join $actual $child]
}
return $result
}
# Extract file data from Fossil revision
proc vcsvfs::fossil::openFile {rootD relative} {
proc vcsvfs::fossil::openFile {rootD relative mode} {
set oldpwd [pwd]
cd [dict get $rootD "origroot"]
set rev [dict get $rootD rev]
# Which way of extracting file data is best?
# fossil finfo -p -r $rev $relative
# set sha [dict get $finfor sha]
# fossil artifact $sha
# fossil cat $relative -r $rev
# Read through a pipe to get a binary channel
set chId [open [list |fossil cat $relative -r $rev] rb]
# Read through a pipe to get requested mode
set chId [open [list |fossil cat $relative -r $rev] $mode]
#set data [read $chId]
#close $chId
cd $oldpwd
#set chId [vcsvfs::CreateDataRefChan $data]
return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}
# Extract file data from Subversion revision
proc vcsvfs::svn::openFile {rootD relative} {
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 a binary channel
set chId [open [list |svn cat -r $rev $relative] rb]
# Read through a pipe to get requested mode
set chId [open [list |svn cat -r $rev $relative] $mode]
#set data [read $chId]
#close $chId
cd $oldpwd
#set chId [vcsvfs::CreateDataRefChan $data]
return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}
# Some notes about git commands that can be good to have
proc vcsvfs::git::openFile {rootD relative} {
proc vcsvfs::git::openFile {rootD relative mode} {
set oldpwd [pwd]
cd [dict get $rootD "origroot"]
set rev [dict get $rootD rev]
set sha [dict get $rootD finfo $relative sha]
#git cat-file
#git show <rev>^{tree}
# example: git show HEAD^^^:apa
# Read through a pipe to get a binary channel
set chId [open [list |git cat-file blob $sha] rb]
# Read through a pipe to get requested mode
set chId [open [list |git cat-file blob $sha] $mode]
#set data [read $chId]
#close $chId
cd $oldpwd
#set chId [vcsvfs::CreateDataRefChan $data]
return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}
# Fossil may delay filling in size, this takes car of that
proc vcsvfs::fossil::size {finfo} {
# Use "fossil whatis" on its sha
# Expected format in a line:
|
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
|
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
|
-
+
-
+
|
matchindirectory {
return [vcsvfs::MatchInDirectory $finfo $relative $actual {*}$args]
}
open {
set mode [lindex $args 0]
if {$mode == {}} {set mode r}
#set permissions [lindex $args 1]
if {$mode ne "r"} {
if {$mode ne "r" && $mode ne "rb"} {
# Read only
vfs::filesystem posixerror $::vfs::posix(EACCES)
return -code error $::vfs::posix(EACCES)
}
return [vcsvfs::${vcstype}::openFile $rootD $relative]
return [vcsvfs::${vcstype}::openFile $rootD $relative $mode]
}
stat {
set res [dict create dev 0 ino 0 "mode" 0 nlink 0 uid 0 gid 0 \
size 0 atime 0 mtime 0 ctime 0 type file]
dict set res type [dict get $finfor type]
if {[dict get $finfor isfile]} {
# Fill in any postponed info
|