Index: lib/fx.tcl ================================================================== --- lib/fx.tcl +++ lib/fx.tcl @@ -1392,10 +1392,29 @@ default {} validate rwdirectory } } [fx::call peer state-dir] + private state-reset { + section Advanced {Armed & Dangerous} Peering + description { + Resets the uuid information used to track new commits. + This forces a re-import of the repository into the local + git state, and further forces a push to the git peers on the + next invokation of "peer exchange". + } + } [fx::call peer state-reset] + + private state-clear { + section Advanced {Armed & Dangerous} Peering + description { + Like "state-reset" but additionally discards the entire + local git state, forcing a complete rebuild on the next + invokation of "peer exchange". + } + } [fx::call peer state-clear] + private list { section Peering section Introspection description { List all peers stored in the repository, and associated Index: lib/peer.tcl ================================================================== --- lib/peer.tcl +++ lib/peer.tcl @@ -38,12 +38,13 @@ namespace export peer namespace ensemble create } namespace eval ::fx::peer { namespace export \ - list add remove add-git remove-git \ - exchange state-dir export import init + list add remove add-git remove-git exchange \ + state-dir state-reset state-clear \ + export import init namespace ensemble create namespace import ::cmdr::color namespace import ::fx::fossil namespace import ::fx::mailer @@ -251,10 +252,70 @@ # Show current value, possibly set above. puts [Statedir] return } + +proc ::fx::peer::state-reset {config} { + debug.fx/peer {} + fossil show-repository-location + init + + set state [Statedir] + if {[IsState $state]} { + if {[MyState $state _ _]} { + puts " Drop tracked uuid from state [color note $state]" + GitDropLast $state + } else { + puts " [color error {Not touching}] non-owned state [color note $state]" + } + } else { + puts " Ignoring non-state [color note $state]" + } + + fossil repository transaction { + set peers [map get fx@peer@git] + dict for {url last} $peers { + puts " Cleared tracked uuid for git peer [color note $url]" + map remove1 fx@peer@git $url + map add1 fx@peer@git $url {} + } + } + + puts [color good OK] + return +} + +proc ::fx::peer::state-clear {config} { + debug.fx/peer {} + fossil show-repository-location + init + + set state [Statedir] + if {[IsState $state]} { + if {[MyState $state _ _]} { + puts " Discard state [color note $state]" + file delete -force $state + } else { + puts " [color error {Not touching}] non-owned state [color note $state]" + } + } else { + puts " Ignoring non-state [color note $state]" + } + + fossil repository transaction { + set peers [map get fx@peer@git] + dict for {url last} $peers { + puts " Cleared tracked uuid for git peer [color note $url]" + map remove1 fx@peer@git $url + map add1 fx@peer@git $url {} + } + } + + puts [color good OK] + return +} # # ## ### ##### ######## ############# ###################### proc ::fx::peer::exchange {config} { debug.fx/peer {} @@ -366,10 +427,17 @@ set i [interp::createEmpty] $i alias fossil ::fx::peer::IFossil $i alias git ::fx::peer::IGit $i eval $data interp delete $i + + variable imported + + if {![llength $imported]} { + puts [color note {No peers}] + return + } if {!$extend} { puts [color warning "Import replaces all existing peers ..."] # Inlined delete of all peers map delete fx@peer@fossil @@ -376,16 +444,10 @@ map delete fx@peer@git } else { puts [color note "Import keeps the existing peers ..."] } - variable imported - if {![llength $imported]} { - puts [color note {No peers}] - return - } - puts "New peers ..." init foreach {type url details} $imported { puts -nonewline " Importing $type $url ($details) ... " flush stdout @@ -488,41 +550,54 @@ debug.fx/peer {} return [config get-with-default \ fx-aku-peer-git-state \ [fossil repository-location].peer-state] } + +proc ::fx::peer::IsState {statedir} { + debug.fx/peer {} + return [expr {[file exists $statedir] && + [file isdirectory $statedir] && + [file exists $statedir/git/git-daemon-export-ok] && + [file isfile $statedir/git/git-daemon-export-ok] + }] +} + +proc ::fx::peer::MyState {statedir pv ov} { + upvar 1 $pv pcode $ov owner + debug.fx/peer {} + set pcode [config get-local project-code] + set owner [string trim [fileutil::cat $statedir/owner]] + return [expr {$pcode eq $owner}] +} + # taken from old setup-import script. proc ::fx::peer::GitSetup {statedir project location} { debug.fx/peer {} - set pcode [config get-local project-code] - puts "Exchange [string repeat _ 40]" puts "Git State Directory" - if {[file exists $statedir] && - [file isdirectory $statedir] && - [file exists $statedir/git/git-daemon-export-ok] && - [file isfile $statedir/git/git-daemon-export-ok] - } { + if {[IsState $statedir]} { debug.fx/peer {/initialized} puts " Ready at [color note $statedir]." # A ready directory may still belong to a different # project. Check this. - set owner [string trim [fileutil::cat $statedir/owner]] - if {$pcode ne $owner} { + if {![MyState $statedir pcode owner]} { puts [color error " Error: Claimed by project \"$owner\""] puts [color error " Error: Which is not us \"$pcode\""] # Abort self, and caller (exchange). return -code return } puts [color good OK] return + } else { + set pcode [config get-local project-code] } puts " Initialize at [color note $statedir]." # State directory is not initialized. Do it now. @@ -629,10 +704,16 @@ proc ::fx::peer::GitUpdateImported {git current} { set idfile $git/fossil-import-id fileutil::writeFile $idfile $current return } + +proc ::fx::peer::GitDropLast {statedir} { + set idfile $statedir/git/fossil-import-id + file delete -force $idfile + return +} proc ::fx::peer::GitPull {tmp git first} { puts " Pull" set begin [clock seconds]