-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgogitvers.go
158 lines (138 loc) · 4.04 KB
/
gogitvers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package main
import (
"fmt"
"os"
"os/exec"
"time"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing/object"
)
/* global variable declaration */
var gForce bool
func generateHeader(dir string) {
fmt.Println("/**")
fmt.Println("* gogitvers.h: file containing version identification constants")
fmt.Println("* ")
fmt.Println("* THIS FILE HAS BEEN AUTOMATICALLY GENERATED, PLEASE DO NOT MODIFY")
fmt.Println("* Generated by gogitvers, visit https://github.com/thew44/gogitvers")
fmt.Println("* Mathieu ALLORY (c) 2020, Under MIT license.")
fmt.Println("*/")
fmt.Println()
fmt.Println("// Generated on: " + time.Now().String())
if dir != "" {
fmt.Println("// Source repository path: " + dir)
fmt.Println()
}
}
func generateError(err string) {
if gForce {
fmt.Println("// ERROR: " + err)
fmt.Println()
generateBody("UNKNOWN", 0, false, false)
} else {
fmt.Println("#error gogitvers: " + err)
fmt.Println()
}
}
func generateWarning(err string) {
fmt.Println("// WARNING: " + err)
fmt.Println()
}
func generateBody(hash string, commitID int, statusIsKnown bool, isClean bool) {
// Repo identification
fmt.Printf("#define GGVERS_HASH \"%s\"\n", hash)
fmt.Printf("#define GVGERS_COMMIT_ID %d\n", commitID)
// Repo cleanliness
var cleanliness string
if statusIsKnown == true && isClean == true {
fmt.Printf("#define GVGERS_ISDIRTY 0\n")
cleanliness = "Clean"
} else if statusIsKnown == true && isClean == false {
fmt.Printf("#define GVGERS_ISDIRTY 1\n")
cleanliness = "Dirty"
} else {
fmt.Printf("#define GVGERS_ISDIRTY 2\n")
cleanliness = "Unknown"
}
// Build identification
fmt.Println()
fmt.Printf("#if defined(_DEBUG) || defined (QT_DEBUG)\n")
fmt.Printf("# define GVGERS_DEBUG 1\n")
fmt.Printf("# define GGVERS_FULL_VERSION \"Commit %d, Hash %s, State:%s,DEBUG\"\n", commitID, hash, cleanliness)
fmt.Printf("#else\n")
fmt.Printf("# define GVGERS_DEBUG 0\n")
fmt.Printf("# define GGVERS_FULL_VERSION \"Commit %d, Hash %s, State:%s\"\n", commitID, hash, cleanliness)
fmt.Printf("#endif\n")
}
func checkIfError(err error) {
if err == nil {
return
}
generateError(fmt.Sprintf("%s", err))
os.Exit(1)
}
func main() {
// Check arguments
if len(os.Args) < 2 {
generateHeader("")
generateError(fmt.Sprintf("Usage: %s <directory> [-f]", os.Args[0]))
os.Exit(1)
}
directory := os.Args[1]
gForce = false
if len(os.Args) > 2 {
if os.Args[2] == "-f" {
gForce = true
}
}
// Print header
generateHeader(directory)
// Opens an already existing repository.
repo, err := git.PlainOpen(directory)
checkIfError(err)
ref, err := repo.Head()
checkIfError(err)
// Get hash
commit, err := repo.CommitObject(ref.Hash())
checkIfError(err)
var hashStr string
for i := 0; i <= 3; i++ {
hashStr += fmt.Sprintf("%x", commit.Hash[i])
}
// Calculate commit_id: the number of commits in the tree
cIter, err := repo.Log(&git.LogOptions{
From: ref.Hash(),
})
checkIfError(err)
countCommits := 0
err = cIter.ForEach(func(c *object.Commit) error {
countCommits++
return nil
})
// Check whether there are uncommitted changes (dirty repo)
// I tried repo.Worktree() then wktree.Status() but first
// it is very slow, second it does not work when a file is locked
// (for instance, when a solution is opened with VC++ :-) and third...
// I always get "true" as an answer to the question.
// So in use the external git command which must be in the path.
// Still, this is not blocking if it does not work
var stateRepoKnown bool
var stateRepoClean bool
cmd := exec.Command("git", "status", "--porcelain")
cmd.Dir = directory
out, err := cmd.Output()
if err != nil {
// Unfortunately, we could not execute the command
generateWarning(fmt.Sprintf("Could not check whether repo is clean (git error): %s", err))
stateRepoKnown = false
stateRepoClean = false
} else {
stateRepoKnown = true
if len(out) == 0 {
stateRepoClean = true
} else {
stateRepoClean = false
}
}
generateBody(hashStr, countCommits, stateRepoKnown, stateRepoClean)
}