Keep an original by its path and its content, so a second original at one path is not discarded (hq ADR 0100)
This commit is contained in:
+11
-5
@@ -22,13 +22,19 @@ import (
|
|||||||
// first copy is the one that was there before the mesh.
|
// first copy is the one that was there before the mesh.
|
||||||
type Keep func(path string, content []byte, mode os.FileMode) (string, error)
|
type Keep func(path string, content []byte, mode os.FileMode) (string, error)
|
||||||
|
|
||||||
// KeepIn keeps originals under dir/kept, each named for the path it came from, readable by root
|
// KeepIn keeps originals under dir/kept, each named for the path it came from AND for what was in
|
||||||
// alone — a predecessor's configuration may carry its credentials.
|
// it, readable by root alone — a predecessor's configuration may carry its credentials.
|
||||||
|
//
|
||||||
|
// **By content as well as path, because a path has more than one original.** A file held, let go
|
||||||
|
// when its module was unassigned, rewritten by the predecessor and found again is a second
|
||||||
|
// original; named by path alone the second copy was silently discarded while the report said it
|
||||||
|
// was kept (novox/hq ADR 0100). The same content at the same path is kept once.
|
||||||
func KeepIn(dir string) Keep {
|
func KeepIn(dir string) Keep {
|
||||||
return func(path string, content []byte, _ os.FileMode) (string, error) {
|
return func(path string, content []byte, _ os.FileMode) (string, error) {
|
||||||
sum := sha256.Sum256([]byte(path))
|
where := sha256.Sum256([]byte(path))
|
||||||
kept := filepath.Join(dir, "kept",
|
what := sha256.Sum256(content)
|
||||||
hex.EncodeToString(sum[:])[:16]+"-"+filepath.Base(path))
|
kept := filepath.Join(dir, "kept", hex.EncodeToString(where[:])[:12]+"-"+
|
||||||
|
hex.EncodeToString(what[:])[:12]+"-"+filepath.Base(path))
|
||||||
if _, err := os.Lstat(kept); err == nil {
|
if _, err := os.Lstat(kept); err == nil {
|
||||||
return kept, nil
|
return kept, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,8 +382,13 @@ func TestAHoldNoLongerDeclaredIsLetGoAndFoundAgainIfItsModuleReturns(t *testing.
|
|||||||
t.Fatalf("a returning module's found file was not held again: %+v", o)
|
t.Fatalf("a returning module's found file was not held again: %+v", o)
|
||||||
}
|
}
|
||||||
again, _ := state.HeldAt("hello-web.page")
|
again, _ := state.HeldAt("hello-web.page")
|
||||||
if kept, _ := os.ReadFile(again.Kept); again.Kept != first.Kept || string(kept) != "the predecessor's page\n" {
|
// The predecessor rewrote it while nothing held it, so that is a second original, kept beside
|
||||||
t.Errorf("the first kept original was lost: %s %q", again.Kept, kept)
|
// the first rather than in place of it (novox/hq ADR 0100).
|
||||||
|
if kept, _ := os.ReadFile(again.Kept); string(kept) != "the predecessor wrote again\n" {
|
||||||
|
t.Errorf("what is named as kept is %q", kept)
|
||||||
|
}
|
||||||
|
if kept, _ := os.ReadFile(first.Kept); string(kept) != "the predecessor's page\n" {
|
||||||
|
t.Errorf("the first kept original was lost: %q", kept)
|
||||||
}
|
}
|
||||||
if got, _ := os.ReadFile(page); string(got) != "the predecessor wrote again\n" {
|
if got, _ := os.ReadFile(page); string(got) != "the predecessor wrote again\n" {
|
||||||
t.Errorf("the found file was touched: %q", got)
|
t.Errorf("the found file was touched: %q", got)
|
||||||
@@ -958,3 +963,60 @@ func TestAPackagedUnitTheMachineUsesIsStillHeld(t *testing.T) {
|
|||||||
t.Errorf("the predecessor's service was restarted: %v", m.asked)
|
t.Errorf("the predecessor's service was restarted: %v", m.asked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestASecondOriginalAtTheSamePathIsKeptToo(t *testing.T) {
|
||||||
|
// Held, let go when the module was unassigned, rewritten by the predecessor, found again:
|
||||||
|
// both originals are kept, and the report names the one it kept (novox/hq ADR 0100).
|
||||||
|
dir := t.TempDir()
|
||||||
|
page := filepath.Join(dir, "index.html")
|
||||||
|
keep := KeepIn(dir)
|
||||||
|
first, err := keep(page, []byte("the predecessor's page\n"), 0o640)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
same, err := keep(page, []byte("the predecessor's page\n"), 0o640)
|
||||||
|
if err != nil || same != first {
|
||||||
|
t.Errorf("the same original was kept twice: %s %s %v", first, same, err)
|
||||||
|
}
|
||||||
|
second, err := keep(page, []byte("the predecessor wrote again\n"), 0o640)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if second == first {
|
||||||
|
t.Fatal("a second original was kept under the first's name")
|
||||||
|
}
|
||||||
|
if got, _ := os.ReadFile(first); string(got) != "the predecessor's page\n" {
|
||||||
|
t.Errorf("the first original is %q", got)
|
||||||
|
}
|
||||||
|
if got, _ := os.ReadFile(second); string(got) != "the predecessor wrote again\n" {
|
||||||
|
t.Errorf("the second original is %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAHoldLetGoAndFoundAgainKeepsBothOriginals(t *testing.T) {
|
||||||
|
dir, page, m := predecessor(t)
|
||||||
|
_, state := applyAdopted(t, adopted(t, untaken("hello-web.page", "hello-web.server"), webResources(page)),
|
||||||
|
store.State{}, m, dir)
|
||||||
|
first, _ := state.HeldAt("hello-web.page")
|
||||||
|
|
||||||
|
// Unassigned, then the predecessor writes again, then assigned once more.
|
||||||
|
_, state = applyAdopted(t, adopted(t, `{"taken":[]}`, withConf(dir)), state, m, dir)
|
||||||
|
if err := os.WriteFile(page, []byte("the predecessor wrote again\n"), 0o640); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
report, state := applyAdopted(t, adopted(t, untaken("hello-web.page", "hello-web.server"), webResources(page)),
|
||||||
|
state, m, dir)
|
||||||
|
again, _ := state.HeldAt("hello-web.page")
|
||||||
|
if again.Kept == first.Kept {
|
||||||
|
t.Fatalf("the second original was kept under the first's name: %s", again.Kept)
|
||||||
|
}
|
||||||
|
if got, _ := os.ReadFile(again.Kept); string(got) != "the predecessor wrote again\n" {
|
||||||
|
t.Errorf("what the report names as kept is %q", got)
|
||||||
|
}
|
||||||
|
if got, _ := os.ReadFile(first.Kept); string(got) != "the predecessor's page\n" {
|
||||||
|
t.Errorf("the first original was lost: %q", got)
|
||||||
|
}
|
||||||
|
if o := outcomeOf(report, "hello-web.page"); o.Action != "held" {
|
||||||
|
t.Errorf("the file found again was not held: %+v", o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user