Skip to content

Commit b7ce660

Browse files
authored
allow passing of commit hash on the cli (#278)
Signed-off-by: Benji Visser <benji@093b.org>
1 parent d609554 commit b7ce660

5 files changed

Lines changed: 134 additions & 1 deletion

File tree

cmd/xeol/cli/options/xeol.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
git "github.com/go-git/go-git/v5"
1010
"github.com/karrick/tparse"
1111

12+
"github.com/xeol-io/xeol/cmd/xeol/internal/types"
1213
"github.com/xeol-io/xeol/internal/format"
1314
)
1415

@@ -99,6 +100,11 @@ func (o *Xeol) AddFlags(flags clio.FlagSet) {
99100
"manually set the name of the project being analyzed for xeol.io. If you are running xeol inside a git repository, this will be automatically detected.",
100101
)
101102

103+
flags.StringVarP(&o.CommitHash,
104+
"commit-hash", "",
105+
"manually set the commit hash of the project being analyzed for xeol.io. If you are running xeol inside a git repository, this will be automatically detected.",
106+
)
107+
102108
flags.StringVarP(&o.APIKey,
103109
"api-key", "",
104110
"set the API key for xeol.io. When this is set, scans will be uploaded to xeol.io.",
@@ -149,6 +155,28 @@ func (o *Xeol) parseLookaheadOption() (err error) {
149155
return nil
150156
}
151157

158+
func (o *Xeol) parseProjectAndCommitOption() (err error) {
159+
if o.APIKey != "" {
160+
if o.ProjectName == "" {
161+
return fmt.Errorf("must specify a project name when using --api-key. This is usually inferred automatically when running inside a git repository, but you may also pass it manually with --project-name")
162+
}
163+
if err := types.ProjectName(o.ProjectName).IsValid(); err != nil {
164+
return err
165+
}
166+
167+
if o.CommitHash == "" {
168+
return fmt.Errorf("must specify a commit hash when using --api-key. This is usually inferred automatically when running inside a git repository, but you may also pass it manually with --commit-hash")
169+
}
170+
if err := types.CommitHash(o.CommitHash).IsValid(); err != nil {
171+
return err
172+
}
173+
}
174+
return nil
175+
}
176+
152177
func (o *Xeol) PostLoad() error {
153-
return o.parseLookaheadOption()
178+
if err := o.parseLookaheadOption(); err != nil {
179+
return err
180+
}
181+
return o.parseProjectAndCommitOption()
154182
}

cmd/xeol/internal/types/commit.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package types
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
)
7+
8+
type CommitHash string
9+
10+
func (c CommitHash) IsValid() error {
11+
re := regexp.MustCompile(`^[a-fA-F0-9]{40}$`)
12+
if !re.MatchString(string(c)) {
13+
return fmt.Errorf("invalid SHA1 hash format for commit hash '%s'", string(c))
14+
}
15+
return nil
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package types
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestCommitHash_IsValid(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
hash CommitHash
11+
wantErr bool
12+
}{
13+
{"Valid SHA1", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", false},
14+
{"Invalid SHA1 - Short", "a94a8fe5cc", true},
15+
{"Invalid SHA1 - Long", "a94a8fe5ccb19ba61c4c0873d391e9879", true},
16+
{"Invalid SHA1 - Special Characters", "a94a8fe5cc#19ba61c4c0873d391e9$", true},
17+
{"Invalid SHA1 - Empty", "", true},
18+
}
19+
20+
for _, tt := range tests {
21+
t.Run(tt.name, func(t *testing.T) {
22+
if err := tt.hash.IsValid(); (err != nil) != tt.wantErr {
23+
t.Errorf("CommitHash.IsValid() error = %v, wantErr %v", err, tt.wantErr)
24+
}
25+
})
26+
}
27+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package types
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
)
7+
8+
type ProjectName string
9+
10+
func (p ProjectName) IsValid() error {
11+
re := regexp.MustCompile(`^(gitlab|github|azure)//([a-zA-Z0-9\-_]+/[a-zA-Z0-9\-_]+(/[a-zA-Z0-9\-_]+)?)$`)
12+
if ok := re.MatchString(string(p)); !ok {
13+
return fmt.Errorf("invalid project name. Accepted formats: 'gitlab//<owner>/<repo>', 'github//<owner>/<repo>', 'azure//<owner>/<project>/<repo>'")
14+
}
15+
return nil
16+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package types
2+
3+
import "testing"
4+
5+
func TestIsValidProjectName(t *testing.T) {
6+
tests := []struct {
7+
projectName string
8+
wantErr bool
9+
}{
10+
{
11+
projectName: "gitlab//noqcks/test",
12+
wantErr: false,
13+
},
14+
{
15+
projectName: "github//noqcks/test",
16+
wantErr: false,
17+
},
18+
{
19+
projectName: "azure//noqcks/test",
20+
wantErr: false,
21+
},
22+
{
23+
projectName: "azure//noqcks/test/test",
24+
wantErr: false,
25+
},
26+
{
27+
projectName: "azure//noqcks/test/test/test",
28+
wantErr: true,
29+
},
30+
{
31+
projectName: "azure//noqcks",
32+
wantErr: true,
33+
},
34+
{
35+
projectName: "test//test",
36+
wantErr: true,
37+
},
38+
}
39+
40+
for _, test := range tests {
41+
err := ProjectName(test.projectName).IsValid()
42+
if test.wantErr && err == nil {
43+
t.Errorf("Expected error for '%s', but got nil", test.projectName)
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)