summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--repo.proto11
-rw-r--r--stat.SortCtime.go67
-rw-r--r--stat.makeRemote.go82
-rw-r--r--stat.makeRemoteRefs.go7
-rw-r--r--stat.proto26
-rw-r--r--stat.updateRefs.go13
-rw-r--r--tableStats.go44
-rw-r--r--versions.go182
8 files changed, 358 insertions, 74 deletions
diff --git a/repo.proto b/repo.proto
index dbc0268..91edb4e 100644
--- a/repo.proto
+++ b/repo.proto
@@ -45,8 +45,8 @@ message GoInfo { // `autogenpb
}
message Repo { // `autogenpb:marshal` `autogenpb:nomutex`
- string uuid = 1; // `autogenpb:uuid:8daaeba1-fb1f-4762-ae6e-95a55d352673`
- string namespace = 2; // `autogenpb:unique` `autogenpb:sort` // this repo is 'go.wit.com/lib/protobuf/gitpb'
+ string uuid = 1; // `autogenpb:unique` `autogenpb:sort`
+ string namespace = 2; // `autogenpb:unique` `autogenpb:sort`
string fullPath = 3; // `autogenpb:unique` `autogenpb:sort` // the OS path to the .git directory: '/home/devel/golang.org/x/tools'
string masterBranchName = 4; // git 'main' or 'master' branch name
string develBranchName = 5; // whatever the git 'devel' branch name is
@@ -70,12 +70,15 @@ message Repo { // `autogenpb
GoInfo goInfo = 23; // put all the go specifcs here
GitTag currentTag = 24; // used to examine repo branches
GitTags tags = 25; // known tags
- // GoDeps goDeps = 11; // what is in the go.sum file
+ Stat masterStat = 26; // just store this for now
+ Stat develStat = 27; // just store this for now
+ Stat userStat = 28; // just store this for now
+ Stats refs = 29; // just store this for now
}
message Repos { // `autogenpb:marshal` `autogenpb:sort` `autogenpb:gui` `autogenpb:nomutex` `autogenpb:http`
string uuid = 1; // `autogenpb:uuid:8daaeba1-fb1f-4762-ae6e-95a55d352673`
- string version = 2; // `autogenpb:version:v6`
+ string version = 2; // `autogenpb:version:v0.0.8 go.wit.com/protobuf/gitpb`
repeated Repo repos = 3; // `autogenpb:append` // generate AppendUnique() function for this
bool hasFullScan = 4; // a full repo scan has been saved to disk
google.protobuf.Timestamp fullScan = 5; // mtime of the last full scan saved to disk
diff --git a/stat.SortCtime.go b/stat.SortCtime.go
index b8045d2..7e3b41a 100644
--- a/stat.SortCtime.go
+++ b/stat.SortCtime.go
@@ -10,7 +10,12 @@
package gitpb
import (
+ "fmt"
"sort"
+ "strings"
+
+ "go.wit.com/lib/env"
+ "go.wit.com/log"
)
func (pb *Stats) SortCtime() {
@@ -30,3 +35,65 @@ func (a sortStatCtime) Less(i, j int) bool {
return itime.Before(jtime)
}
func (a sortStatCtime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+// sort tags by Version()
+// returns true if anything changed
+var wasSorted bool
+
+func (pb *Stats) SortVersion() bool {
+ statMu.Lock()
+ defer statMu.Unlock()
+
+ wasSorted = true
+
+ sort.Sort(sortStatVersion(pb.Stats))
+
+ return wasSorted
+}
+
+func tokVersion(r *Stat) (*Vers, error) {
+ var ver string
+ if strings.HasPrefix(r.Name, "refs/tags/") {
+ ver = strings.TrimPrefix(r.Name, "refs/tags/")
+ } else if strings.HasPrefix(r.Name, "refs/heads/") {
+ ver = strings.TrimPrefix(r.Name, "refs/heads/")
+ } else if strings.HasPrefix(r.Name, "refs/remotes/") {
+ ver = strings.TrimPrefix(r.Name, "refs/remotes/")
+ } else if strings.HasPrefix(r.Name, "refs/") {
+ ver = strings.TrimPrefix(r.Name, "refs/")
+ } else {
+ ver = fmt.Sprintf("%s", r.Name)
+ }
+ tok, err := TokenVersions(ver)
+ return tok, err
+}
+
+// sort struct by Version
+type sortStatVersion []*Stat
+
+func (a sortStatVersion) Len() int { return len(a) }
+func (a sortStatVersion) Less(i, j int) bool {
+ atok, err1 := tokVersion(a[i])
+ btok, err2 := tokVersion(a[j])
+ _, _ = err1, err2
+ cint := CompareVers(atok, btok)
+ if cint == 1 {
+ if env.True("stats") {
+ log.Info("false one", atok, "vs", btok, err1, err2, a[i].Name, a[j].Name)
+ }
+ return false
+ }
+ if cint == -1 {
+ if env.True("stats") {
+ log.Info("true less", atok, "vs", btok, err1, err2, err2, a[i].Name, a[j].Name)
+ }
+ wasSorted = false
+ return true
+ }
+ if env.True("stats") {
+ log.Info("false 0 ", atok, "vs", btok, err1, err2, err2, a[i].Name, a[j].Name)
+ }
+ return false
+}
+
+func (a sortStatVersion) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
diff --git a/stat.makeRemote.go b/stat.makeRemote.go
index 685238a..f583d2d 100644
--- a/stat.makeRemote.go
+++ b/stat.makeRemote.go
@@ -22,7 +22,7 @@ func (r *Repo) LoadRemote(remoteName string) (*Stats, error) {
return stats, err
}
-var standardFmts []string = []string{"H", "T", "at", "ct", "f"}
+var standardFmts []string = []string{"H", "T", "at", "ct", "f", "d"}
var standardSeperator string = "___FORGE___"
func makeFmts() string {
@@ -35,6 +35,31 @@ func makeFmts() string {
return "--format=" + strings.Join(all, standardSeperator)
}
+func makeStat(line string) *Stat {
+ line = strings.TrimSpace(line)
+ parts := strings.Split(line, standardSeperator)
+ if len(parts) != 6 {
+ log.Printf("BAD LINE: len(%d) %s\n", len(parts), line)
+ return nil
+ }
+ newstat := new(Stat)
+ newstat.Hash = parts[0]
+ newstat.TreeHash = parts[1]
+ t, err := cobol.GetTime(parts[2])
+ _ = err
+ if t != nil {
+ newstat.AuthorTime = timestamppb.New(*t)
+ }
+ t, err = cobol.GetTime(parts[3])
+ if t != nil {
+ newstat.CommitTime = timestamppb.New(*t)
+ }
+ newstat.SanitizedSubject = parts[4]
+ newstat.Tags = parts[5]
+
+ return newstat
+}
+
// makes a new file. File must be empty at start
func (r *Repo) MakeRemote(remoteName string) (*Stats, error) {
stats, err := r.LoadRemote(remoteName)
@@ -42,9 +67,10 @@ func (r *Repo) MakeRemote(remoteName string) (*Stats, error) {
return stats, err
}
if stats.Len() != 0 {
- return stats, errors.New("refs file was already created")
+ // file was already created and populated with data
+ return stats, nil
}
- cmd := []string{"git", "log", "-n", "100", makeFmts(), "origin/HEAD"} // HEAD is _NOT_ always set
+ cmd := []string{"git", "log", makeFmts(), "origin/HEAD"} // HEAD is _NOT_ always set
if env.True("stats") {
log.Info("STATS VERBOSE Run:", cmd)
}
@@ -54,31 +80,11 @@ func (r *Repo) MakeRemote(remoteName string) (*Stats, error) {
}
var counter int
for _, line := range cmdout.Stdout {
- line = strings.TrimSpace(line)
- parts := strings.Split(line, standardSeperator)
- if len(parts) != 5 {
- log.Printf("Repo: %s len(%d)\n", r.FullPath, len(parts))
- log.Printf("CMD: %v\n", cmd)
- log.Printf("LINE:%s\n", line)
- return stats, errors.New(line)
- }
if env.True("stats") {
- log.Printf("LINE:%v %d %s\n", parts, counter, r.FullPath)
+ log.Printf("LINE:%s %d %s\n", line, counter, r.FullPath)
}
counter += 1
- newstat := new(Stat)
- newstat.Hash = parts[0]
- newstat.TreeHash = parts[1]
- t, err := cobol.GetTime(parts[2])
- _ = err
- if t != nil {
- newstat.AuthorTime = timestamppb.New(*t)
- }
- t, err = cobol.GetTime(parts[3])
- if t != nil {
- newstat.CommitTime = timestamppb.New(*t)
- }
- newstat.SanitizedSubject = parts[4]
+ newstat := makeStat(line)
stats.Append(newstat)
}
if counter > 0 {
@@ -107,20 +113,12 @@ func (r *Repo) UpdateRemote(remoteName string) error {
}
var counter int
for _, line := range cmdout.Stdout {
- line = strings.TrimSpace(line)
- parts := strings.Split(line, standardSeperator)
- if len(parts) != 5 {
- log.Printf("Repo: %s len(%d)\n", r.FullPath, len(parts))
- log.Printf("CMD: %v\n", cmd)
- log.Printf("LINE:%s\n", line)
- return errors.New(line)
- }
if env.True("stats") {
- log.Printf("LINE:%v %d %s\n", parts, counter, r.FullPath)
+ log.Printf("LINE:%s %d %s\n", line, counter, r.FullPath)
}
counter += 1
- newstat := new(Stat)
- newstat.Hash = parts[0]
+ newstat := makeStat(line)
+ // TODO: convert this protobuf to raw binary, then do a raw BinarySearch() on the hash
n, found := slices.BinarySearchFunc(stats.Stats, newstat, func(a, b *Stat) int {
return strings.Compare(a.Hash, b.Hash)
})
@@ -130,18 +128,6 @@ func (r *Repo) UpdateRemote(remoteName string) error {
// log.Info("found", n)
continue
}
-
- newstat.TreeHash = parts[1]
- t, err := cobol.GetTime(parts[2])
- _ = err
- if t != nil {
- newstat.AuthorTime = timestamppb.New(*t)
- }
- t, err = cobol.GetTime(parts[3])
- if t != nil {
- newstat.CommitTime = timestamppb.New(*t)
- }
- newstat.SanitizedSubject = parts[4]
stats.Append(newstat)
}
if counter > 0 {
diff --git a/stat.makeRemoteRefs.go b/stat.makeRemoteRefs.go
index b1a5736..571843f 100644
--- a/stat.makeRemoteRefs.go
+++ b/stat.makeRemoteRefs.go
@@ -28,7 +28,8 @@ func (r *Repo) MakeRemoteRefs(remoteName string) (*Stats, error) {
return stats, err
}
if stats.Len() != 0 {
- return stats, errors.New("refs file was already created")
+ // file was already created and populated with data
+ return stats, nil
}
cmd := []string{"git", "ls-remote", remoteName} // must use 'master' as queried from the git server // GO has 250k remote refs
if env.True("stats") {
@@ -53,7 +54,7 @@ func (r *Repo) MakeRemoteRefs(remoteName string) (*Stats, error) {
}
counter += 1
newstat := new(Stat)
- newstat.Hash = parts[0]
+ newstat.TagHash = parts[0]
stats.Append(newstat)
}
if counter > 0 {
@@ -116,7 +117,7 @@ func (r *Repo) UpdateRemoteRefs(remoteName string) error {
// }
counter += 1
newstat := new(Stat)
- newstat.Hash = parts[0]
+ newstat.TagHash = parts[0]
n, found := slices.BinarySearchFunc(stats.Stats, newstat, func(a, b *Stat) int {
return strings.Compare(a.Hash, b.Hash)
})
diff --git a/stat.proto b/stat.proto
index e98d73e..ad900ea 100644
--- a/stat.proto
+++ b/stat.proto
@@ -23,24 +23,26 @@ message GitRef {
}
// TODO: use patch.proto instead
message Stat {
- string patchId = 1; // `autogenpb:unique` `autogenpb:sort`
- string hash = 2; // `autogenpb:unique` `autogenpb:sort`
- string treeHash = 3; // `autogenpb:unique` `autogenpb:sort`
- google.protobuf.Timestamp authorTime = 4; // `autogenpb:unique` `autogenpb:sort`
- google.protobuf.Timestamp commitTime = 5; // `autogenpb:unique` `autogenpb:sort`
- string sanitizedSubject = 6; //
- string name = 7; //
- string remote = 8; // blank unless REMOTE
- string subject = 9; // git tag subject
- GitRef.RefType type = 10; // is set by git as the master branch
- repeated GitRef refs = 11; // this is dumb, but works for now. duplicate information is stored sometimes
+ string patchId = 1; // `autogenpb:sort`
+ string hash = 2; // `autogenpb:sort`
+ string treeHash = 3; // `autogenpb:sort`
+ string tagHash = 4; // `autogenpb:unique` `autogenpb:sort`
+ google.protobuf.Timestamp authorTime = 5; // `autogenpb:sort`
+ google.protobuf.Timestamp commitTime = 6; // `autogenpb:sort`
+ string sanitizedSubject = 7; // `autogenpb:sort`
+ string name = 8; // `autogenpb:unique` `autogenpb:sort`
+ string remote = 9; // blank unless REMOTE
+ string subject = 10; // git tag subject
+ GitRef.RefType type = 11; // is set by git as the master branch
+ repeated GitRef refs = 12; // this is dumb, but works for now. duplicate information is stored sometimes
+ string tags = 13; // git tag subject
}
// normally stored as .git/*.pb cache files
// TODO: use patch.proto instead
message Stats { // `autogenpb:marshal` `autogenpb:gui` `autogenpb:http`
string uuid = 1; // `autogenpb:uuid:ba236558-f8a1-4c47-a14a-8856a24d3f72`
- string version = 2; // `autogenpb:version:v0.0.3`
+ string version = 2; // `autogenpb:version:v0.0.7 go.wit.com/lib/protobuf/gitpb`
repeated Stat stats = 3;
string filename = 4; // `autogenpb:save` -- this enables autogenerated pb.Load() and pb.Save()
string head = 5; // the current origin hash
diff --git a/stat.updateRefs.go b/stat.updateRefs.go
index 4676fe9..84f95f9 100644
--- a/stat.updateRefs.go
+++ b/stat.updateRefs.go
@@ -46,18 +46,23 @@ func (r *Repo) UpdateRefs(stats *Stats) error {
log.Printf("LINE:%v %d %s\n", parts, counter, r.FullPath)
}
newstat := new(Stat)
- newstat.Hash = parts[0]
- // newstat.Name = parts[1]
+ newstat.TagHash = parts[0]
+ newstat.Name = parts[1]
- teststat := stats.FindByHash(newstat.Hash)
+ teststat := stats.FindByName(newstat.Name)
if teststat == nil {
counter += 1
stats.Append(newstat)
+ } else {
+ if teststat.Name == "" {
+ counter += 1
+ teststat.Name = parts[1]
+ }
}
}
if counter > 0 {
stats.SaveByHash()
- return errors.New(fmt.Sprintf("len(%d) refs changed: (%d)", stats.Len(), counter))
+ return errors.New(fmt.Sprintf("%s: len(%d) saved. changed %d refs.", stats.Filename, stats.Len(), counter))
}
return nil
}
diff --git a/tableStats.go b/tableStats.go
index f229553..06115dd 100644
--- a/tableStats.go
+++ b/tableStats.go
@@ -3,6 +3,9 @@
package gitpb
import (
+ "fmt"
+ "strings"
+
"go.wit.com/lib/cobol"
"go.wit.com/log"
)
@@ -32,17 +35,52 @@ func (pb *Stats) MakeTable(name string) *StatsTable {
col = t.AddPatchId()
col.Width = 10
- col = t.AddHash()
+ col = t.AddStringFunc("Hash", func(r *Stat) string {
+ if r.Hash != "" {
+ return fmt.Sprintf("Hash(%8.8s)", r.Hash)
+ }
+ if r.TreeHash != "" {
+ return fmt.Sprintf("Tree(%8.8s)", r.TreeHash)
+ }
+ if r.TagHash != "" {
+ return fmt.Sprintf("Tag (%8.8s)", r.TagHash)
+ }
+ return fmt.Sprintf(" (%8.8s)", "")
+ })
col.Width = 20
col.Header.Name = "Git Hash"
col = t.AddStringFunc("age", func(r *Stat) string {
return cobol.Time(r.CommitTime)
})
- col.Width = 28
+ col.Width = 27
+
+ col = t.AddTags()
+ col.Width = 20
+
+ // col = t.AddName()
+ // col.Width = 30
col = t.AddStringFunc("Name", func(r *Stat) string {
- return r.SanitizedSubject
+ if strings.HasPrefix(r.Name, "refs/tags/") {
+ return strings.TrimPrefix(r.Name, "refs/tags/")
+ }
+ if strings.HasPrefix(r.Name, "refs/heads/") {
+ return strings.TrimPrefix(r.Name, "refs/heads/")
+ }
+ if strings.HasPrefix(r.Name, "refs/remotes/") {
+ return strings.TrimPrefix(r.Name, "refs/remotes/")
+ }
+ if strings.HasPrefix(r.Name, "refs/") {
+ return strings.TrimPrefix(r.Name, "refs/")
+ }
+ return fmt.Sprintf("%s", r.Name)
+ })
+ col.Width = 16
+
+ col = t.AddStringFunc("Submect", func(r *Stat) string {
+ // return fmt.Sprintf("subject(%s) name(%s)", r.SanitizedSubject, r.Name)
+ return fmt.Sprintf("%s", r.SanitizedSubject)
})
col.Width = -1
diff --git a/versions.go b/versions.go
new file mode 100644
index 0000000..9f860c5
--- /dev/null
+++ b/versions.go
@@ -0,0 +1,182 @@
+package gitpb
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "go.wit.com/log"
+)
+
+// newver(0.25.101-1+b10)
+// a == 0
+// b == 25
+// c == 101
+// pnum == 1
+// bnum == 10
+type Vers struct {
+ a int // major
+ b int
+ c int
+ pnum int
+ bnum int
+}
+
+func TokenVersions(ver string) (*Vers, error) {
+ var err error
+ tok := new(Vers)
+ var golang bool
+ if strings.HasPrefix(ver, "v") {
+ golang = true
+ ver = strings.TrimPrefix(ver, "v")
+ }
+ parts := strings.Split(ver, "-")
+ if len(parts) == 0 {
+ return nil, errors.New("version was empty")
+ }
+ abc := strings.Split(parts[0], ".")
+ if len(abc) != 3 {
+ return nil, errors.New("abc != 3 parts")
+ }
+ tok.a, err = strconv.Atoi(abc[0])
+ if err != nil {
+ return nil, errors.New("tok.a failed")
+ }
+ tok.b, err = strconv.Atoi(abc[1])
+ if err != nil {
+ return nil, errors.New("tok.b failed")
+ }
+ tok.c, err = strconv.Atoi(abc[2])
+ if err != nil {
+ return nil, errors.New("tok.c failed")
+ }
+ if golang {
+ return tok, nil
+ }
+
+ if len(parts) != 2 {
+ return nil, errors.Join(err, errors.New("len != 2 parts"))
+ }
+ bb := strings.Split(parts[1], "+")
+ if len(bb) != 2 {
+ return nil, errors.Join(err, errors.New(fmt.Sprintf("parts(%v) abc(%v)", parts, abc)))
+ }
+ tok.pnum, err = strconv.Atoi(bb[0])
+ if err != nil {
+ return nil, errors.Join(err, errors.New(fmt.Sprintf("parts(%v) abc(%v)", parts, abc)))
+ }
+ tok.bnum, err = strconv.Atoi(strings.TrimPrefix(bb[1], "b"))
+ if err != nil {
+ return nil, errors.Join(err, errors.New(fmt.Sprintf("parts(%v) abc(%v)", parts, abc)))
+ }
+ return tok, nil
+}
+
+func CompareVers(atok *Vers, btok *Vers) int {
+ if (atok == nil) || (btok == nil) {
+ return 0
+ }
+ // CHECK A
+ if atok.a > btok.a {
+ return 1
+ }
+ if btok.a > atok.a {
+ return -1
+ }
+
+ // CHECK B
+ if atok.b > btok.b {
+ return 1
+ }
+ if btok.b > atok.b {
+ return -1
+ }
+
+ // CHECK C
+ if atok.c > btok.c {
+ return 1
+ }
+ if btok.c > atok.c {
+ return -1
+ }
+
+ // CHECK PATCH #
+ if atok.pnum > btok.pnum {
+ return 1
+ }
+ if btok.pnum > atok.pnum {
+ return -1
+ }
+
+ // CHECK BUILD #
+ if atok.bnum > btok.bnum {
+ return 1
+ }
+ if btok.bnum > atok.bnum {
+ return -1
+ }
+
+ // CHECK IS EQUAL
+ if atok.bnum == btok.bnum {
+ return 0
+ }
+ return 0 // compare should not have gotten here (%v) to curver (%v)", newver, curver))
+}
+
+// compares newver(0.25.101-1+b10) curver(0.25.101-5+b1)
+// returns true only if it's newer. returns false if equal
+// used for .deb mirrors
+func NewerVersion(newver string, curver string) (bool, error) {
+ newtok, err1 := TokenVersions(newver)
+ curtok, err2 := TokenVersions(curver)
+ if (newtok == nil) || (curtok == nil) {
+ s := log.Sprintf("token on the railroad failed (%v) to curver (%v) err(%v)(%v)", newtok, curtok, err1, err2)
+ return false, errors.New(s)
+ }
+ // CHECK A
+ if newtok.a > curtok.a {
+ return true, nil
+ }
+ if curtok.a > newtok.a {
+ return false, errors.New(log.Sprintf("A.x.x lower (%v) to curver (%v)", newver, curver))
+ }
+
+ // CHECK B
+ if newtok.b > curtok.b {
+ return true, nil
+ }
+ if curtok.b > newtok.b {
+ return false, errors.New(log.Sprintf("x.B.x lower (%v) to curver (%v)", newver, curver))
+ }
+
+ // CHECK C
+ if newtok.c > curtok.c {
+ return true, nil
+ }
+ if curtok.c > newtok.c {
+ return false, errors.New(log.Sprintf("x.x.C lower (%v) to curver (%v)", newver, curver))
+ }
+
+ // CHECK PATCH #
+ if newtok.pnum > curtok.pnum {
+ return true, nil
+ }
+ if curtok.pnum > newtok.pnum {
+ return false, errors.New(log.Sprintf("patch # lower (%v) to curver (%v)", newver, curver))
+ }
+
+ // CHECK BUILD #
+ if newtok.bnum > curtok.bnum {
+ return true, nil
+ }
+ if curtok.bnum > newtok.bnum {
+ return false, errors.New(log.Sprintf("build # lower (%v) to curver (%v)", newver, curver))
+ }
+
+ // CHECK IS EQUAL
+ if curtok.bnum == newtok.bnum {
+ return false, errors.New(log.Sprintf("new is equal (%v) to curver (%v)", newver, curver))
+ }
+ return false, errors.New(log.Sprintf("compare should not have gotten here (%v) to curver (%v)", newver, curver))
+}