Eskil

Check-in [12cbadae02]
Login

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

Overview
Comment:Postpone fossil whatis call until needed.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 12cbadae0214132e42c202aae3ab12d8b4412021
User & Date: peter 2015-02-25 23:50:49.146
Context
2015-02-26
00:23
Use fossil ls to polish the result from fileage check-in: 8303f3458f user: peter tags: trunk
2015-02-25
23:50
Postpone fossil whatis call until needed. check-in: 12cbadae02 user: peter tags: trunk
23:04
Moved nice setting to Preferences. Save prefs from dirdiff window. check-in: b07b1877ff user: peter tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vcsvfs.tcl.
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
70
71
72
73
74
75
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
102
103
104
105
106
107
108
109
110
111
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

139
140
141




142
143
144
145
146
147
148
    # 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


    set artifact [exec fossil artifact $rev]
    set commitTime 0
    set cTime now

    foreach line [split $artifact \n] {
        # Expected format in a line:
        # F tests/left.txt c1572b3809a1ba6ab2de9307c96b1cfeefdcf0ba
        # D 2015-02-23T23:30:07.509
        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]} {
            # File names can have spaces, coded with \s
            set fName [string map {\\s " "} $fName]
            dict set finfo $fName sha $fSha
            dict set finfo $fName mtimestr $cTime ;# Anything
            dict set finfo $fName type file
            dict set finfo $fName isfile 1
            dict set finfo $fName isdir 0
            # TBD: Delay calling whatis until size is needed
            # Expected format in a line:
            # size:    629 bytes
            set whatis [exec fossil whatis $fSha]
            regexp {size:\s+(\d+)} $whatis -> fSize
            dict set finfo $fName size $fSize

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

    # Getting files via http fileage to aquire file times



    set html [exec fossil http << "GET /fileage?name=$rev"]
    regexp {Files in.*} $html html



    regexp {\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}} $html cTime2





    set commitTime2 [clock scan $cTime2 -gmt 1]
    #puts "CT $commitTime  CT2 $commitTime2"

    foreach row [regexp -all -inline {<tr>.*?</tr>} $html] {

        set cols [regexp -all -inline {<td>(.*?)</td>} $row]
        set col1 [string trim [lindex $cols 1]]
        set col2 [string trim [lindex $cols 3]]
        # First column is age, in readable format
        # e.g. "current" "36.4 minutes" "97.0 days" "1.06 years"
        if {$col1 eq ""} continue
        if {$col1 eq "current"} {
            set fTime $commitTime
        } else {
            set value [lindex $col1 0]
            set unit [lindex $col1 1]
            switch -glob $unit {
                second* {
                    set value [expr {int($value)}]
                    set unit second
                }
                minute* {
                    set value [expr {int($value*60)}]
                    set unit second
                }
                hour* {
                    set value [expr {int($value*60*60)}]
                    set unit second
                }
                day* {
                    set value [expr {int($value*60*60*24)}]
                    set unit second
                }
                year* {
                    set value [expr {int($value*60*60*24*365)}]
                    set unit second
                }
                default {
                    puts "Unhandled unit: $unit in '$col1'"
                    set value [expr {int($value)}]
                }
            }
            set fTime [expr {$commitTime - $value}]
        }
        #puts "AGE $col1 -> $fTime"

        # Second column is file names, separated by <br>
        # Remove links
        regsub -all {<a .*?>} $col2 "" col2
        regsub -all {</a>} $col2 "" col2
        regsub -all {\n} $col2 "" col2
        regsub -all {<br>} $col2 "\n" col2
        set col2 [string trim $col2]
        foreach fName [split $col2 \n] {

            #puts $fName
            dict set finfo $fName mtime $fTime
        }




    }

    cd $oldpwd

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







>
>



>


















|
|
<
<
<
<














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

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







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
70
71
72
73
74
75
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
102
103
104
105
106
107
108
109
110
111
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    # 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
    # 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] {
        # Expected format in a line:
        # F tests/left.txt c1572b3809a1ba6ab2de9307c96b1cfeefdcf0ba
        # D 2015-02-23T23:30:07.509
        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]} {
            # File names can have spaces, coded with \s
            set fName [string map {\\s " "} $fName]
            dict set finfo $fName sha $fSha
            dict set finfo $fName mtimestr $cTime ;# Anything
            dict set finfo $fName type file
            dict set finfo $fName isfile 1
            dict set finfo $fName isdir 0
            # Setting size is delayed until needed since the needed
            # calls are relatively expensive.





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

    # Getting files via http fileage to aquire file times
    # Since dates are parsed from the age string they are rather imprecise
    # Use a while around it to be able to break free easily (faking goto)
    while 1 {
        set html [exec fossil http << "GET /fileage?name=$rev"]
        if {![regexp {Files in.*} $html html]} {
            # Not the expected format of response, skip
            break
        }
        if {![regexp {\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}} $html cTime2]} {
            # Not the expected format of response, skip
            break
        }
        # This is currently unused since we do not trust the formatted time in
        # the web page. The time stamp from the artifact is used later.
        set commitTime2 [clock scan $cTime2 -gmt 1]
        #puts "CT $commitTime  CT2 $commitTime2"
        # Rows in the HTML table
        foreach row [regexp -all -inline {<tr>.*?</tr>} $html] {
            # Columns in the HTML table
            set cols [regexp -all -inline {<td>(.*?)</td>} $row]
            set col1 [string trim [lindex $cols 1]]
            set col2 [string trim [lindex $cols 3]]
            # First column is age, in readable format
            # e.g. "current" "36.4 minutes" "97.0 days" "1.06 years"
            if {$col1 eq ""} continue
            if {$col1 eq "current"} {
                set fTime $commitTime
            } else {
                set value [lindex $col1 0]
                set unit [lindex $col1 1]
                switch -glob $unit {
                    second* {
                        set value [expr {int($value)}]
                        set unit second
                    }
                    minute* {
                        set value [expr {int($value*60)}]
                        set unit second
                    }
                    hour* {
                        set value [expr {int($value*60*60)}]
                        set unit second
                    }
                    day* {
                        set value [expr {int($value*60*60*24)}]
                        set unit second
                    }
                    year* {
                        set value [expr {int($value*60*60*24*365)}]
                        set unit second
                    }
                    default {
                        puts "Unhandled unit: $unit in '$col1'"
                        set value [expr {int($value)}]
                    }
                }
                set fTime [expr {$commitTime - $value}]
            }
            #puts "AGE $col1 -> $fTime"

            # Second column is file names, separated by <br>
            # Remove links
            regsub -all {<a .*?>} $col2 "" col2
            regsub -all {</a>} $col2 "" col2
            regsub -all {\n} $col2 "" col2
            regsub -all {<br>} $col2 "\n" col2
            set col2 [string trim $col2]
            foreach fName [split $col2 \n] {
                # Check that it matches something filled in from the artifact
                if {[dict exists $finfo $fName]} {
                    dict set finfo $fName mtime $fTime
                }
            }
        }
        # Kill surrounding while loop
        break
    }

    cd $oldpwd

    # Generate a mount point.
    set tail [string range $dir [string length $root] end]
    set mountpoint "${root} ($rev)"
296
297
298
299
300
301
302

303
304
305
306
307
308
309
        } else {
            # This is a file
            dict set finfo $fName isfile 1
            dict set finfo $fName isdir 0
            dict set finfo $fName "type" file
            dict set finfo $fName "sha" $sha
            dict set finfo $fName "size" $size

            set mtime [exec git log --pretty=format:%ct -n 1 $fName]
            dict set finfo $fName "mtime" $mtime
        }
        # 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







>







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
        } else {
            # This is a file
            dict set finfo $fName isfile 1
            dict set finfo $fName isdir 0
            dict set finfo $fName "type" file
            dict set finfo $fName "sha" $sha
            dict set finfo $fName "size" $size
            # TBD: Delay this call until mtime is needed?
            set mtime [exec git log --pretty=format:%ct -n 1 $fName]
            dict set finfo $fName "mtime" $mtime
        }
        # 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
463
464
465
466
467
468
469
470










471
472

473
474
475
476
477
478
479

480
481
482
483
484
485
486
    #set data [read $chId]
    #close $chId
    cd $oldpwd

    #set chId [vcsvfs::CreateDataRefChan $data]
    return [list $chId [list vcsvfs::ReadAllBeforeClose $chId]]
}











# Parse a time string from Fossil
proc vcsvfs::fossil::mTime {mtimestr} {

    # TBD parse to mtime correct?
    set mtime [clock scan $mtimestr -gmt 1]
    return $mtime
}

# Parse a time string from Subversion
proc vcsvfs::svn::mTime {mtimestr} {

    # TBD parse to mtime correct?
    # Remove any decimals from time string
    regsub {\.\d+Z} $mtimestr "" mtimestr
    set mtime [clock scan $mtimestr -gmt 1]
    return $mtime
}









>
>
>
>
>
>
>
>
>
>

|
>






|
>







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
    #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:
    # size:    629 bytes
    set whatis [exec fossil whatis [dict get $finfo sha]]
    regexp {size:\s+(\d+)} $whatis -> fSize
    return $fSize
}

# Parse a time string from Fossil
proc vcsvfs::fossil::mTime {finfo} {
    set mtimestr [dict get $finfo mtimestr]
    # TBD parse to mtime correct?
    set mtime [clock scan $mtimestr -gmt 1]
    return $mtime
}

# Parse a time string from Subversion
proc vcsvfs::svn::mTime {finfo} {
    set mtimestr [dict get $finfo mtimestr]
    # TBD parse to mtime correct?
    # Remove any decimals from time string
    regsub {\.\d+Z} $mtimestr "" mtimestr
    set mtime [clock scan $mtimestr -gmt 1]
    return $mtime
}

538
539
540
541
542
543
544

545
546
547
548
549
550
551






552
553
554
555
556
557
558
            return [vcsvfs::${vcstype}::openFile $rootD $relative]
        }
        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]} {

                if {![dict exists $finfor mtime]} {
                    set mtime [vcsvfs::${vcstype}::mTime \
                                       [dict get $finfor mtimestr]]
                    dict set finfor "mtime" $mtime
                    # Cache in main dictionary too
                    dict set mpoints $root "finfo" $relative "mtime" $mtime
                }






                dict set res "mtime" [dict get $finfor "mtime"]
                dict set res size  [dict get $finfor size]
            }
            return $res
        }
        createdirectory - deletefile - removedirectory - utime {
            # Read-only, always error







>

|
<




>
>
>
>
>
>







568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
            return [vcsvfs::${vcstype}::openFile $rootD $relative]
        }
        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
                if {![dict exists $finfor mtime]} {
                    set mtime [vcsvfs::${vcstype}::mTime $finfor]

                    dict set finfor "mtime" $mtime
                    # Cache in main dictionary too
                    dict set mpoints $root "finfo" $relative "mtime" $mtime
                }
                if {![dict exists $finfor size]} {
                    set size [vcsvfs::${vcstype}::size $finfor]
                    dict set finfor "size" $size
                    # Cache in main dictionary too
                    dict set mpoints $root "finfo" $relative "size" $size
                }
                dict set res "mtime" [dict get $finfor "mtime"]
                dict set res size  [dict get $finfor size]
            }
            return $res
        }
        createdirectory - deletefile - removedirectory - utime {
            # Read-only, always error