Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Version
Manage
Activity
Members
Plan
Jira
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Analyze
Contributor analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
OSS
Utilities
Version
Commits
01616479
Verified
Commit
01616479
authored
1 year ago
by
Volker Schukai
Browse files
Options
Downloads
Patches
Plain Diff
feat: use semantic struct
parent
a0608f85
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
commandline.go
+19
-4
19 additions, 4 deletions
commandline.go
git.go
+70
-83
70 additions, 83 deletions
git.go
with
89 additions
and
87 deletions
commandline.go
+
19
−
4
View file @
01616479
...
@@ -6,6 +6,8 @@ import (
...
@@ -6,6 +6,8 @@ import (
"time"
"time"
"github.com/jessevdk/go-flags"
"github.com/jessevdk/go-flags"
"github.com/go-git/go-git/v5"
)
)
var
(
var
(
...
@@ -65,12 +67,16 @@ func increaseMajor() (string, error) {
...
@@ -65,12 +67,16 @@ func increaseMajor() (string, error) {
return
next
.
String
(),
nil
return
next
.
String
(),
nil
}
}
var
gitRepo
*
git
.
Repository
func
executeCommand
()
{
func
executeCommand
()
{
arguments
=
new
(
commandLineOptions
)
arguments
=
new
(
commandLineOptions
)
p
:=
flags
.
NewParser
(
arguments
,
flags
.
Default
)
p
:=
flags
.
NewParser
(
arguments
,
flags
.
Default
)
_
,
err
:=
p
.
Parse
()
var
err
error
_
,
err
=
p
.
Parse
()
if
err
!=
nil
{
if
err
!=
nil
{
os
.
Exit
(
-
1
)
os
.
Exit
(
-
1
)
}
}
...
@@ -83,8 +89,17 @@ func executeCommand() {
...
@@ -83,8 +89,17 @@ func executeCommand() {
var
newVersion
string
var
newVersion
string
command
:=
activeCommand
.
Name
command
:=
activeCommand
.
Name
if
arguments
.
Git
||
command
==
"auto"
{
gitRepo
,
err
=
git
.
PlainOpen
(
"."
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
-
1
)
}
}
if
command
==
"auto"
{
if
command
==
"auto"
{
updateType
,
err
:=
GetCommitType
(
"."
)
updateType
,
err
:=
GetCommitType
(
gitRepo
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
os
.
Exit
(
-
1
)
os
.
Exit
(
-
1
)
...
@@ -108,13 +123,13 @@ func executeCommand() {
...
@@ -108,13 +123,13 @@ func executeCommand() {
switch
command
{
switch
command
{
case
"print"
:
case
"print"
:
if
arguments
.
Git
{
if
arguments
.
Git
{
version
,
err
:=
getLatestSemanticTag
(
"."
)
version
,
err
:=
getLatestSemanticTag
(
gitRepo
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
os
.
Exit
(
-
1
)
os
.
Exit
(
-
1
)
}
}
fmt
.
Printf
(
"%s"
,
version
)
fmt
.
Printf
(
"%s"
,
version
.
String
()
)
os
.
Exit
(
0
)
os
.
Exit
(
0
)
}
}
case
"date"
:
case
"date"
:
...
...
This diff is collapsed.
Click to expand it.
git.go
+
70
−
83
View file @
01616479
...
@@ -2,17 +2,51 @@ package main
...
@@ -2,17 +2,51 @@ package main
import
(
import
(
"fmt"
"fmt"
"strings"
"regexp"
"regexp"
"sort"
"sort"
"strconv"
"strconv"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
)
)
var
versionRegex
=
regexp
.
MustCompile
(
`^v?(\d+)\.(\d+)\.(\d+).*$`
)
type
SemanticVersion
struct
{
Major
int
Minor
int
Patch
int
Tag
string
}
func
(
v
SemanticVersion
)
String
()
string
{
return
fmt
.
Sprintf
(
"%d.%d.%d"
,
v
.
Major
,
v
.
Minor
,
v
.
Patch
)
}
func
ParseSemanticVersion
(
tag
string
)
SemanticVersion
{
matches
:=
versionRegex
.
FindStringSubmatch
(
tag
)
major
,
_
:=
strconv
.
Atoi
(
matches
[
1
])
minor
,
_
:=
strconv
.
Atoi
(
matches
[
2
])
patch
,
_
:=
strconv
.
Atoi
(
matches
[
3
])
return
SemanticVersion
{
major
,
minor
,
patch
,
tag
}
}
func
(
v
SemanticVersion
)
IsLessThan
(
w
SemanticVersion
)
bool
{
if
v
.
Major
!=
w
.
Major
{
return
v
.
Major
<
w
.
Major
}
if
v
.
Minor
!=
w
.
Minor
{
return
v
.
Minor
<
w
.
Minor
}
if
v
.
Patch
!=
w
.
Patch
{
return
v
.
Patch
<
w
.
Patch
}
return
false
}
type
CommitType
int
type
CommitType
int
const
(
const
(
...
@@ -22,13 +56,14 @@ const (
...
@@ -22,13 +56,14 @@ const (
FixCommit
FixCommit
)
)
func
GetCommitType
(
path
string
)
(
CommitType
,
error
)
{
func
GetCommitType
(
r
*
git
.
Repository
)
(
CommitType
,
error
)
{
r
,
err
:=
git
.
PlainOpen
(
path
)
latestTag
,
err
:=
getLatestSemanticTag
(
r
)
if
err
!=
nil
{
if
err
!=
nil
{
return
OtherCommit
,
fmt
.
Errorf
(
"failed to open repository: %v"
,
err
)
return
OtherCommit
,
err
}
}
tagCommit
,
err
:=
get
Latest
TagCommit
(
r
)
tagCommit
,
err
:=
getTagCommit
(
r
,
latestTag
.
Tag
)
if
err
!=
nil
{
if
err
!=
nil
{
return
OtherCommit
,
err
return
OtherCommit
,
err
}
}
...
@@ -41,109 +76,62 @@ func GetCommitType(path string) (CommitType, error) {
...
@@ -41,109 +76,62 @@ func GetCommitType(path string) (CommitType, error) {
return
commitType
,
nil
return
commitType
,
nil
}
}
func
getLatestSemanticTag
(
path
string
)
(
string
,
error
)
{
func
getLatestSemanticTag
(
r
*
git
.
Repository
)
(
SemanticVersion
,
error
)
{
r
,
err
:=
git
.
PlainOpen
(
path
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"failed to open repository: %v"
,
err
)
}
tagList
,
err
:=
getSemanticTags
(
r
)
tagList
,
err
:=
getSemanticTags
(
r
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
SemanticVersion
{}
,
err
}
}
if
len
(
tagList
)
==
0
{
if
len
(
tagList
)
==
0
{
return
""
,
fmt
.
Errorf
(
"no semantic tags found"
)
return
SemanticVersion
{}
,
fmt
.
Errorf
(
"no semantic tags found"
)
}
}
sort
.
Slice
(
tagList
,
func
(
i
,
j
int
)
bool
{
return
compareSemanticVersions
(
tagList
[
i
],
tagList
[
j
])
})
return
tagList
[
len
(
tagList
)
-
1
],
nil
return
tagList
[
len
(
tagList
)
-
1
],
nil
}
}
func
get
SemanticTags
(
r
*
git
.
Repository
)
([]
string
,
error
)
{
func
get
TagCommit
(
r
*
git
.
Repository
,
tag
string
)
(
*
object
.
Commit
,
error
)
{
tags
,
err
:=
r
.
Tags
()
tags
,
err
:=
r
.
Tags
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get tags: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to get tags: %v"
,
err
)
}
}
var
tagList
[]
string
var
tagCommit
*
object
.
Commit
err
=
tags
.
ForEach
(
func
(
tag
*
plumbing
.
Reference
)
error
{
err
=
tags
.
ForEach
(
func
(
t
*
plumbing
.
Reference
)
error
{
tagName
:=
tag
.
Name
()
.
Short
()
if
t
.
Name
()
.
Short
()
==
tag
{
if
isSemanticVersion
(
tagName
)
{
tagObj
,
err
:=
r
.
TagObject
(
t
.
Hash
())
tagList
=
append
(
tagList
,
tagName
)
if
err
!=
nil
{
return
err
}
tagCommit
,
err
=
tagObj
.
Commit
()
if
err
!=
nil
{
return
err
}
return
storer
.
ErrStop
// stop iteration
}
}
return
nil
return
nil
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to iterate over tags: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to iterate over tags: %v"
,
err
)
}
}
if
tagCommit
==
nil
{
return
tagList
,
nil
return
nil
,
fmt
.
Errorf
(
"tag commit not found in commit log"
)
}
func
isSemanticVersion
(
tagName
string
)
bool
{
versionRegex
:=
regexp
.
MustCompile
(
`^v?\d+\.\d+\.\d+.*$`
)
return
versionRegex
.
MatchString
(
tagName
)
}
func
compareSemanticVersions
(
a
,
b
string
)
bool
{
// Remove leading "v" if present
a
=
strings
.
TrimPrefix
(
a
,
"v"
)
b
=
strings
.
TrimPrefix
(
b
,
"v"
)
aParts
:=
strings
.
Split
(
a
,
"."
)
bParts
:=
strings
.
Split
(
b
,
"."
)
for
i
:=
0
;
i
<
len
(
aParts
)
&&
i
<
len
(
bParts
);
i
++
{
aNum
,
_
:=
strconv
.
Atoi
(
aParts
[
i
])
bNum
,
_
:=
strconv
.
Atoi
(
bParts
[
i
])
if
aNum
!=
bNum
{
return
aNum
<
bNum
}
}
}
return
len
(
aParts
)
<
len
(
bParts
)
return
tagCommit
,
nil
}
}
func
get
LatestTagCommit
(
r
*
git
.
Repository
)
(
*
object
.
Commit
,
error
)
{
func
get
SemanticTags
(
r
*
git
.
Repository
)
(
[]
SemanticVersion
,
error
)
{
tags
,
err
:=
r
.
Tags
()
tags
,
err
:=
r
.
Tags
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get tags: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to get tags: %v"
,
err
)
}
}
var
mostRecentTag
*
plumbing
.
Reference
var
tagList
[]
SemanticVersion
var
mostRecentCommit
*
object
.
Commit
err
=
tags
.
ForEach
(
func
(
tag
*
plumbing
.
Reference
)
error
{
err
=
tags
.
ForEach
(
func
(
tag
*
plumbing
.
Reference
)
error
{
obj
,
err
:=
r
.
TagObject
(
tag
.
Hash
())
tagName
:=
tag
.
Name
()
.
Short
()
if
err
!=
nil
{
if
versionRegex
.
MatchString
(
tagName
)
{
if
err
==
plumbing
.
ErrObjectNotFound
{
tagList
=
append
(
tagList
,
ParseSemanticVersion
(
tagName
))
// If the tag object is not found, it's likely a lightweight tag pointing directly to a commit
commit
,
err
:=
r
.
CommitObject
(
tag
.
Hash
())
if
err
!=
nil
{
return
err
}
obj
=
&
object
.
Tag
{
Tagger
:
commit
.
Author
,
Message
:
commit
.
Message
}
}
else
{
return
err
}
}
commit
,
err
:=
obj
.
Commit
()
if
err
!=
nil
{
return
err
}
if
mostRecentTag
==
nil
||
commit
.
Committer
.
When
.
After
(
mostRecentCommit
.
Committer
.
When
)
{
mostRecentTag
=
tag
mostRecentCommit
=
commit
}
}
return
nil
return
nil
})
})
...
@@ -151,7 +139,11 @@ func getLatestTagCommit(r *git.Repository) (*object.Commit, error) {
...
@@ -151,7 +139,11 @@ func getLatestTagCommit(r *git.Repository) (*object.Commit, error) {
return
nil
,
fmt
.
Errorf
(
"failed to iterate over tags: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to iterate over tags: %v"
,
err
)
}
}
return
mostRecentCommit
,
nil
sort
.
Slice
(
tagList
,
func
(
i
,
j
int
)
bool
{
return
tagList
[
i
]
.
IsLessThan
(
tagList
[
j
])
})
return
tagList
,
nil
}
}
func
getCommitTypeSinceTag
(
r
*
git
.
Repository
,
tagCommit
*
object
.
Commit
)
(
CommitType
,
error
)
{
func
getCommitTypeSinceTag
(
r
*
git
.
Repository
,
tagCommit
*
object
.
Commit
)
(
CommitType
,
error
)
{
...
@@ -196,19 +188,14 @@ func getCommitTypeSinceTag(r *git.Repository, tagCommit *object.Commit) (CommitT
...
@@ -196,19 +188,14 @@ func getCommitTypeSinceTag(r *git.Repository, tagCommit *object.Commit) (CommitT
}
}
func
containsBreakingChangeFooter
(
message
string
)
bool
{
func
containsBreakingChangeFooter
(
message
string
)
bool
{
// Split the commit message by newline to get the footer text
lines
:=
strings
.
Split
(
message
,
"
\n
"
)
lines
:=
strings
.
Split
(
message
,
"
\n
"
)
// Check last lines for the "BREAKING CHANGE" footer
for
i
:=
len
(
lines
)
-
1
;
i
>=
0
;
i
--
{
for
i
:=
len
(
lines
)
-
1
;
i
>=
0
;
i
--
{
if
strings
.
TrimSpace
(
lines
[
i
])
==
""
{
if
strings
.
TrimSpace
(
lines
[
i
])
==
""
{
// Stop checking when an empty line (beginning of the commit body) is reached
break
break
}
}
if
strings
.
Contains
(
strings
.
ToLower
(
lines
[
i
]),
"breaking change:"
)
{
if
strings
.
Contains
(
strings
.
ToLower
(
lines
[
i
]),
"breaking change:"
)
{
return
true
return
true
}
}
}
}
return
false
return
false
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment