Skip to content

Commit ac8daf0

Browse files
bindreamsavafanasiev
authored andcommitted
🧱 QD-13044 Make diff start and end options more robust (#737)
1 parent 78978aa commit ac8daf0

File tree

6 files changed

+125
-11
lines changed

6 files changed

+125
-11
lines changed

clang/go.work.sum

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXe
6060
github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY=
6161
github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8=
6262
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
63-
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
64-
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
6563
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
6664
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
6765
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
@@ -96,8 +94,6 @@ github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2T
9694
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
9795
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
9896
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
99-
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
100-
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
10197
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
10298
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
10399
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
@@ -264,8 +260,6 @@ go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37Cb
264260
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
265261
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
266262
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
267-
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
268-
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
269263
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
270264
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
271265
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
@@ -280,6 +274,7 @@ golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
280274
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
281275
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
282276
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
277+
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
283278
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
284279
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
285280
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@@ -291,6 +286,7 @@ golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
291286
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
292287
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b h1:DU+gwOBXU+6bO0sEyO7o/NeMlxZxCZEvI7v+J4a1zRQ=
293288
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4=
289+
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
294290
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
295291
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
296292
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=

core/incremental_analysis.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,28 @@ func NewReverseScopedAnalyzer(
120120
}
121121

122122
func (sa *ScopedAnalyzer) RunAnalysis() int {
123-
c, startHash, endHash := sa.sequenceRunner.GetParams()
123+
c, startRef, endRef := sa.sequenceRunner.GetParams()
124124
var err error
125-
if startHash == "" || endHash == "" {
125+
if startRef == "" || endRef == "" {
126126
log.Fatal("No commits given. Consider passing --commit or --diff-start and --diff-end (optional) with the range of commits to analyze.")
127127
}
128128

129-
changedFiles, err := git.ComputeChangedFiles(c.RepositoryRoot(), startHash, endHash, c.LogDir())
129+
startSha, err := git.RevParse(c.RepositoryRoot(), startRef, c.LogDir())
130+
if err != nil {
131+
log.Fatalf("Failed to calculate analysis scope: %q is not a valid commit ref.", startRef)
132+
}
133+
134+
endSha, err := git.RevParse(c.RepositoryRoot(), endRef, c.LogDir())
135+
if err != nil {
136+
log.Fatalf("Failed to calculate analysis scope: %q is not a valid commit ref.", endRef)
137+
}
138+
139+
changedFiles, err := git.ComputeChangedFiles(c.RepositoryRoot(), startSha, endSha, c.LogDir())
130140
if err != nil {
131141
log.Fatal(err)
132142
}
133143
if len(changedFiles.Files) == 0 {
134-
log.Warnf("Nothing to compare between %s and %s", startHash, endHash)
144+
log.Warnf("Nothing to compare between %s and %s", startRef, endRef)
135145
return utils.QodanaEmptyChangesetExitCodePlaceholder
136146
}
137147

go.work.sum

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,20 @@ github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwm
692692
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
693693
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
694694
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
695+
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
696+
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
697+
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
698+
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
699+
github.com/boyter/simplecache v0.0.0-20250113230110-8a4c9201822a/go.mod h1:8yw7v2b4T5LJbZEBhPOqUsqe8h04anlyPhmWnoUtRIs=
700+
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
701+
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
702+
github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
703+
github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
704+
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
705+
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
706+
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
707+
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
708+
github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
695709
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
696710
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
697711
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@@ -1257,3 +1271,12 @@ rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
12571271
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
12581272
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
12591273
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
1274+
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
1275+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
1276+
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
1277+
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
1278+
github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
1279+
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
1280+
go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k=
1281+
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
1282+
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=

platform/git/git.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ func gitRun(cwd string, command []string, logdir string) (string, string, error)
5858
return stdout, stderr, nil
5959
}
6060

61+
// RevParse converts any commit reference (hash, branch name, tag name, etc.) to a full SHA1 commit hash.
62+
func RevParse(cwd string, ref string, logdir string) (string, error) {
63+
stdout, _, err := gitRun(cwd, []string{"rev-parse", "--verify", "--quiet", "--end-of-options", ref}, logdir)
64+
return strings.TrimSpace(stdout), err
65+
}
66+
6167
// Reset resets the git repository to the given commit.
6268
func Reset(cwd string, sha string, logdir string) error {
6369
_, _, err := gitRun(cwd, []string{"reset", "--soft", sha}, logdir)

platform/git/git_changes.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,23 @@ func ComputeChangedFiles(cwd string, diffStart string, diffEnd string, logdir st
8484
return ChangedFiles{}, fmt.Errorf("failed to close file %s: %w", filePath, err)
8585
}
8686

87+
// Rev-parsing references in advance helps with clearer error messages and in case references could be confused
88+
// with `git diff` options.
89+
diffStartSha, err := RevParse(cwd, diffStart, logdir)
90+
if err != nil {
91+
return ChangedFiles{}, err
92+
}
93+
log.Debugf("Resolved git ref %q as %s", diffStart, diffStartSha)
94+
95+
diffEndSha, err := RevParse(cwd, diffEnd, logdir)
96+
if err != nil {
97+
return ChangedFiles{}, err
98+
}
99+
log.Debugf("Resolved git ref %q as %s", diffEnd, diffEndSha)
100+
87101
_, _, err = gitRun(
88102
cwd,
89-
[]string{"diff", diffStart, diffEnd, "--unified=0", "--no-renames", ">", strutil.QuoteIfSpace(filePath)},
103+
[]string{"diff", diffStartSha, diffEndSha, "--unified=0", "--no-renames", ">", strutil.QuoteIfSpace(filePath)},
90104
logdir,
91105
)
92106
if err != nil {

platform/git/git_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package git
1818

1919
import (
20+
"fmt"
2021
"os"
2122
"os/exec"
2223
"path/filepath"
24+
"regexp"
2325
"testing"
2426

2527
log "github.com/sirupsen/logrus"
@@ -82,6 +84,48 @@ func TestGitRunReportsErrors(t *testing.T) {
8284
assert.Error(t, err)
8385
}
8486

87+
func TestRevParse(t *testing.T) {
88+
reSha1 := regexp.MustCompile("^[0-9a-f]{40}$")
89+
logdir := t.TempDir()
90+
91+
dir := gitInit(t)
92+
gitCommitAll(t, dir, "commit")
93+
94+
// Resolving head
95+
headSha, err := RevParse(dir, "HEAD", logdir)
96+
assert.NoError(t, err)
97+
assert.Regexp(t, reSha1, headSha)
98+
99+
// Resolving branch
100+
branchSha1, err := RevParse(dir, "main", logdir)
101+
assert.NoError(t, err)
102+
assert.Equal(t, headSha, branchSha1)
103+
104+
branchSha2, err := RevParse(dir, "refs/heads/main", logdir)
105+
assert.NoError(t, err)
106+
assert.Equal(t, headSha, branchSha2)
107+
108+
// Resolving tag
109+
git(t, dir, []string{"tag", "v1.0.0"})
110+
tagSha1, err := RevParse(dir, "v1.0.0", logdir)
111+
assert.NoError(t, err)
112+
assert.Equal(t, headSha, tagSha1)
113+
114+
tagSha2, err := RevParse(dir, "refs/tags/v1.0.0", logdir)
115+
assert.NoError(t, err)
116+
assert.Equal(t, headSha, tagSha2)
117+
118+
// Resolving short SHA1
119+
shortSha, err := RevParse(dir, headSha[:5], logdir)
120+
assert.NoError(t, err)
121+
assert.Equal(t, headSha, shortSha)
122+
123+
// Resolving full SHA1
124+
headShaSha, err := RevParse(dir, headSha, logdir)
125+
assert.NoError(t, err)
126+
assert.Equal(t, headSha, headShaSha)
127+
}
128+
85129
func deferredCleanup(path string) {
86130
err := os.RemoveAll(path)
87131
if err != nil {
@@ -128,3 +172,24 @@ func gitClone(repoURL, directory string, revision string, branch string) error {
128172
}
129173
return nil
130174
}
175+
176+
func gitInit(t *testing.T) string {
177+
dir := t.TempDir()
178+
git(t, dir, []string{"init", "--initial-branch=main"})
179+
return dir
180+
}
181+
182+
func gitCommitAll(t *testing.T, cwd string, message string) {
183+
git(t, cwd, []string{"commit", "--all", "--allow-empty", "--allow-empty-message", "--message", message})
184+
}
185+
186+
func git(t *testing.T, cwd string, command []string) string {
187+
logdir := t.TempDir()
188+
defer assert.NoError(t, os.RemoveAll(logdir))
189+
190+
command = append([]string{"-c", "user.name=Test", "-c", "user.email="}, command...)
191+
stdout, stderr, err := gitRun(cwd, command, logdir)
192+
assert.NoError(t, err)
193+
fmt.Print(stderr)
194+
return stdout
195+
}

0 commit comments

Comments
 (0)