forked from tangled.org/core
this repo has no description
at master 2.7 kB view raw
1package git 2 3import ( 4 "fmt" 5 "slices" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/go-git/go-git/v5/plumbing" 11 "github.com/go-git/go-git/v5/plumbing/object" 12 "tangled.sh/tangled.sh/core/types" 13) 14 15func (g *GitRepo) Branches() ([]types.Branch, error) { 16 fields := []string{ 17 "refname:short", 18 "objectname", 19 "authorname", 20 "authoremail", 21 "authordate:unix", 22 "committername", 23 "committeremail", 24 "committerdate:unix", 25 "tree", 26 "parent", 27 "contents", 28 } 29 30 var outFormat strings.Builder 31 outFormat.WriteString("--format=") 32 for i, f := range fields { 33 if i != 0 { 34 outFormat.WriteString(fieldSeparator) 35 } 36 outFormat.WriteString(fmt.Sprintf("%%(%s)", f)) 37 } 38 outFormat.WriteString("") 39 outFormat.WriteString(recordSeparator) 40 41 output, err := g.forEachRef(outFormat.String(), "refs/heads") 42 if err != nil { 43 return nil, fmt.Errorf("failed to get branches: %w", err) 44 } 45 46 records := strings.Split(strings.TrimSpace(string(output)), recordSeparator) 47 if len(records) == 1 && records[0] == "" { 48 return nil, nil 49 } 50 51 branches := make([]types.Branch, 0, len(records)) 52 53 // ignore errors here 54 defaultBranch, _ := g.FindMainBranch() 55 56 for _, line := range records { 57 parts := strings.SplitN(strings.TrimSpace(line), fieldSeparator, len(fields)) 58 if len(parts) < 6 { 59 continue 60 } 61 62 branchName := parts[0] 63 commitHash := plumbing.NewHash(parts[1]) 64 authorName := parts[2] 65 authorEmail := strings.TrimSuffix(strings.TrimPrefix(parts[3], "<"), ">") 66 authorDate := parts[4] 67 committerName := parts[5] 68 committerEmail := strings.TrimSuffix(strings.TrimPrefix(parts[6], "<"), ">") 69 committerDate := parts[7] 70 treeHash := plumbing.NewHash(parts[8]) 71 parentHash := plumbing.NewHash(parts[9]) 72 message := parts[10] 73 74 // parse creation time 75 var authoredAt, committedAt time.Time 76 if unix, err := strconv.ParseInt(authorDate, 10, 64); err == nil { 77 authoredAt = time.Unix(unix, 0) 78 } 79 if unix, err := strconv.ParseInt(committerDate, 10, 64); err == nil { 80 committedAt = time.Unix(unix, 0) 81 } 82 83 branch := types.Branch{ 84 IsDefault: branchName == defaultBranch, 85 Reference: types.Reference{ 86 Name: branchName, 87 Hash: commitHash.String(), 88 }, 89 Commit: &object.Commit{ 90 Hash: commitHash, 91 Author: object.Signature{ 92 Name: authorName, 93 Email: authorEmail, 94 When: authoredAt, 95 }, 96 Committer: object.Signature{ 97 Name: committerName, 98 Email: committerEmail, 99 When: committedAt, 100 }, 101 TreeHash: treeHash, 102 ParentHashes: []plumbing.Hash{parentHash}, 103 Message: message, 104 }, 105 } 106 107 branches = append(branches, branch) 108 } 109 110 slices.Reverse(branches) 111 return branches, nil 112}