Drop the "not cloned here" line from overview
It answered a question `list` already answers, and it did so on every run: the point of the overview is the state of the projects you have, not a second listing of the server. reportInventory became reportUnpublished and now reports one thing -- the local projects the server has never seen, which are the ones `init` is for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -162,7 +162,6 @@ thing that sees the local base directory *and* the git server at once.
|
||||
scratch (wip) – laptop 1h
|
||||
4 projects · 2 dirty · 2 in sync
|
||||
not on the server (init) experiments, sandbox
|
||||
not cloned here (clone) oldproject
|
||||
```
|
||||
|
||||
Every field sits in its own column, so the eye can go down one instead of
|
||||
@@ -184,10 +183,11 @@ every message, so `overview` can say where a project was last worked on without
|
||||
storing anything. On a setup spanning a laptop and a workstation that is usually
|
||||
the piece of information you actually wanted.
|
||||
|
||||
The two lists at the end are the join no git command can do: local projects the
|
||||
server has never seen (`init` them) and server repositories missing on this
|
||||
machine (`clone` them). If the server cannot be reached, mgsh says so instead of
|
||||
claiming everything is missing.
|
||||
The line at the end is the join no git command can do: the local projects the
|
||||
git server has never seen, which are the ones `init` is for. If the server
|
||||
cannot be reached, mgsh says so instead of claiming everything is missing. The
|
||||
other direction — repositories on the server that are not here — is what `list`
|
||||
shows.
|
||||
|
||||
### Credential check
|
||||
|
||||
|
||||
+14
-31
@@ -5,9 +5,8 @@ package main
|
||||
// mgsh is the only thing that sees all three places a project can live: the
|
||||
// local base directory, the internal ssh server, and the public mirrors. Joining
|
||||
// those answers the questions plain git cannot — which projects were never
|
||||
// pushed to the server, which exist there but not on this machine, and which
|
||||
// machine last touched each one (every `push` stamps "[user@host]" into the
|
||||
// commit message, so that comes for free).
|
||||
// pushed to the server, and which machine last touched each one (every `push`
|
||||
// stamps "[user@host]" into the commit message, so that comes for free).
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -99,7 +98,7 @@ func overviewAll() {
|
||||
len(rows), dirtyN, syncN)))
|
||||
}
|
||||
|
||||
reportInventory(local, srv.names, srv.err)
|
||||
reportUnpublished(local, srv.names, srv.err)
|
||||
}
|
||||
|
||||
// scanProjects collects the state of every project concurrently. Each project
|
||||
@@ -121,47 +120,31 @@ func scanProjects(names []string) []projStatus {
|
||||
return rows
|
||||
}
|
||||
|
||||
// reportInventory names the projects that live on only one side: local ones the
|
||||
// server has never seen (candidates for `init`) and server repositories missing
|
||||
// here (candidates for `clone`).
|
||||
func reportInventory(local, server []string, err error) {
|
||||
// reportUnpublished names the local projects the git server has never seen —
|
||||
// the ones `init` is for. The reverse direction, server repositories missing
|
||||
// here, is what `list` is for and is not repeated.
|
||||
func reportUnpublished(local, server []string, err error) {
|
||||
if err != nil {
|
||||
fmt.Println(col(cGray, " git server not reachable — local view only"))
|
||||
return
|
||||
}
|
||||
have := map[string]bool{}
|
||||
for _, n := range local {
|
||||
have[n] = true
|
||||
}
|
||||
onServer := map[string]bool{}
|
||||
for _, n := range server {
|
||||
onServer[n] = true
|
||||
}
|
||||
|
||||
var missingRemote, missingLocal []string
|
||||
var missing []string
|
||||
for _, n := range local {
|
||||
if !onServer[n] {
|
||||
missingRemote = append(missingRemote, n)
|
||||
missing = append(missing, n)
|
||||
}
|
||||
}
|
||||
for _, n := range server {
|
||||
if !have[n] {
|
||||
missingLocal = append(missingLocal, n)
|
||||
}
|
||||
}
|
||||
sort.Strings(missingRemote)
|
||||
sort.Strings(missingLocal)
|
||||
|
||||
// the two labels share a column so their contents line up as well
|
||||
const labelW = 24
|
||||
if len(missingRemote) > 0 {
|
||||
fmt.Printf(" %s %s\n", col(cYellow, padRight("not on the server (init)", labelW)),
|
||||
col(cGray, strings.Join(missingRemote, ", ")))
|
||||
}
|
||||
if len(missingLocal) > 0 {
|
||||
fmt.Printf(" %s %s\n", col(cCyan, padRight("not cloned here (clone)", labelW)),
|
||||
col(cGray, strings.Join(missingLocal, ", ")))
|
||||
if len(missing) == 0 {
|
||||
return
|
||||
}
|
||||
sort.Strings(missing)
|
||||
fmt.Printf(" %s %s\n", col(cYellow, "not on the server (init)"),
|
||||
col(cGray, strings.Join(missing, ", ")))
|
||||
}
|
||||
|
||||
// projectStatus gathers the git state of a single project directory.
|
||||
|
||||
+17
-8
@@ -82,11 +82,11 @@ func TestCommitHostRe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestReportInventoryUnreachableServer: when the server cannot be listed, the
|
||||
// TestReportUnpublishedUnreachableServer: when the server cannot be listed, the
|
||||
// overview must say so rather than claim every project is missing there.
|
||||
func TestReportInventoryUnreachableServer(t *testing.T) {
|
||||
func TestReportUnpublishedUnreachableServer(t *testing.T) {
|
||||
out := captureStdout(t, func() {
|
||||
reportInventory([]string{"a", "b"}, nil, errors.New("network is unreachable"))
|
||||
reportUnpublished([]string{"a", "b"}, nil, errors.New("network is unreachable"))
|
||||
})
|
||||
if strings.Contains(out, "not on the server") {
|
||||
t.Errorf("an unreachable server was reported as missing repositories: %q", out)
|
||||
@@ -96,20 +96,29 @@ func TestReportInventoryUnreachableServer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestReportInventorySplitsSides is the join that plain git cannot do.
|
||||
func TestReportInventorySplitsSides(t *testing.T) {
|
||||
// TestReportUnpublished names only the local projects the server has never
|
||||
// seen. The other direction — repositories there but not here — is what `list`
|
||||
// is for, and repeating it here only added noise.
|
||||
func TestReportUnpublished(t *testing.T) {
|
||||
out := captureStdout(t, func() {
|
||||
reportInventory([]string{"both", "onlyhere"}, []string{"both", "onlythere"}, nil)
|
||||
reportUnpublished([]string{"both", "onlyhere"}, []string{"both", "onlythere"}, nil)
|
||||
})
|
||||
if !strings.Contains(out, "not on the server (init)") || !strings.Contains(out, "onlyhere") {
|
||||
t.Errorf("local-only project not reported: %q", out)
|
||||
}
|
||||
if !strings.Contains(out, "not cloned here (clone)") || !strings.Contains(out, "onlythere") {
|
||||
t.Errorf("server-only project not reported: %q", out)
|
||||
if strings.Contains(out, "onlythere") {
|
||||
t.Errorf("server-only project should no longer be listed: %q", out)
|
||||
}
|
||||
if strings.Contains(out, "both") {
|
||||
t.Errorf("a project present on both sides should not be listed: %q", out)
|
||||
}
|
||||
|
||||
// nothing unpublished: no line at all, not an empty label
|
||||
if out := captureStdout(t, func() {
|
||||
reportUnpublished([]string{"both"}, []string{"both"}, nil)
|
||||
}); strings.TrimSpace(out) != "" {
|
||||
t.Errorf("nothing to report should print nothing, got %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortAge(t *testing.T) {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
4.0.36
|
||||
4.0.38
|
||||
|
||||
Reference in New Issue
Block a user