Skip to content

Commit c6a940f

Browse files
authored
Merge pull request #59 from gitopia/pr-diff
fix pr diff api to return git triple dot diff
2 parents 8b5947b + c6e713a commit c6a940f

8 files changed

Lines changed: 130 additions & 50 deletions

File tree

.vscode/launch.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
"cwd": "${workspaceFolder}",
1414
"program": "${workspaceFolder}",
1515
"env":{
16-
"ENV":"DEVELOPMENT"
16+
"ENV":"",
17+
"PATH":"$PATH:/opt/homebrew/bin:/usr/bin",
18+
"LIBRARY_PATH":"/opt/homebrew/lib/",
19+
"CGO_ENABLED": "1"
1720
}
1821
},
1922
{

changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## [v2.1.0] - 2023-07-27
4+
5+
- fix pr diff api to return git triple dot diff
6+
- add line filter to content API
7+
38
## [v2.0.1] - 2023-05-18
49

510
- fix pre receive hook for empty branch

config_dev.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ TM_ADDR = "https://rpc.devnet.gitopia.com:443"
88
WORKING_DIR = "/home/ubuntu/git-server/"
99
GAS_PRICES = "0.001ulore"
1010
CHAIN_ID = "gitopia-janus-devnet-4"
11+
FEE_GRANTER_ADDR=""

config_local.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ TM_ADDR = "http://localhost:26657"
88
WORKING_DIR = "/tmp/git-server/"
99
GAS_PRICES = ""
1010
CHAIN_ID = "gitopia"
11+
FEE_GRANTER_ADDR=""

route/content.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package route
22

33
import (
4+
"encoding/base64"
45
"encoding/json"
56
"fmt"
67
"log"
@@ -30,6 +31,12 @@ func ContentHandler(w http.ResponseWriter, r *http.Request) {
3031
return
3132
}
3233

34+
if body.From > body.To {
35+
log.Println("from > to")
36+
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
37+
return
38+
}
39+
3340
blocks := strings.Split(r.URL.Path, "/")
3441

3542
if len(blocks) != 2 {
@@ -84,6 +91,23 @@ func ContentHandler(w http.ResponseWriter, r *http.Request) {
8491
http.Error(w, err.Error(), http.StatusNotFound)
8592
return
8693
}
94+
95+
if body.From != 0 && body.To != 0 {
96+
decodedFc, err := base64.StdEncoding.DecodeString(fc.Content)
97+
if err != nil {
98+
http.Error(w, err.Error(), http.StatusInternalServerError)
99+
return
100+
}
101+
102+
splits := strings.Split(string(decodedFc), "\n")
103+
if body.To > uint64(len(splits)) {
104+
body.To = (uint64)(len(splits))
105+
}
106+
rangeFc := strings.Join(splits[body.From-1:body.To-1], "\n")
107+
fc.Content = base64.StdEncoding.EncodeToString([]byte(rangeFc))
108+
fc.Size = (int64)(len(rangeFc))
109+
}
110+
87111
fileContent = append(fileContent, fc)
88112

89113
if body.IncludeLastCommit {

route/pr/diff.go

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@ package pr
22

33
import (
44
"encoding/json"
5-
"fmt"
65
"log"
76
"net/http"
8-
"path"
7+
"os"
8+
"os/exec"
99

1010
"github.com/gitopia/git-server/utils"
1111
git "github.com/gitopia/go-git/v5"
1212
"github.com/gitopia/go-git/v5/plumbing"
1313
"github.com/gitopia/go-git/v5/plumbing/object"
14-
"github.com/spf13/viper"
1514
)
1615

1716
func PullDiffHandler(w http.ResponseWriter, r *http.Request) {
@@ -28,51 +27,64 @@ func PullDiffHandler(w http.ResponseWriter, r *http.Request) {
2827
return
2928
}
3029

31-
headRepositoryPath := path.Join(viper.GetString("GIT_DIR"), fmt.Sprintf("%d.git", body.HeadRepositoryID))
32-
headRepository, err := git.PlainOpen(headRepositoryPath)
30+
if body.HeadCommitSha == "" || body.BaseCommitSha == "" {
31+
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
32+
return
33+
}
34+
35+
qpath, err := utils.CreateReadOnlyQuarantineRepo(body.BaseRepositoryID, body.HeadRepositoryID)
3336
if err != nil {
34-
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
37+
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
3538
return
3639
}
40+
defer os.RemoveAll(qpath)
3741

38-
baseRepositoryPath := path.Join(viper.GetString("GIT_DIR"), fmt.Sprintf("%d.git", body.BaseRepositoryID))
39-
baseRepository, err := git.PlainOpen(baseRepositoryPath)
42+
cmd := exec.Command("git", "-C", qpath, "merge-base", "--", body.HeadCommitSha, body.BaseCommitSha)
43+
out, err := cmd.Output()
4044
if err != nil {
41-
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
45+
log.Print("err finding merge base " + err.Error())
46+
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
47+
return
48+
}
49+
mergeBase := string(out)
50+
if mergeBase == "" {
51+
log.Print("merge base not found")
52+
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
4253
return
4354
}
4455

45-
if body.HeadCommitSha == "" || body.BaseCommitSha == "" {
46-
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
56+
repo, err := git.PlainOpen(qpath)
57+
if err != nil {
58+
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
4759
return
4860
}
4961

5062
headCommitHash := plumbing.NewHash(body.HeadCommitSha)
51-
baseCommitHash := plumbing.NewHash(body.BaseCommitSha)
63+
baseCommitHash := plumbing.NewHash(mergeBase)
5264

5365
var headCommit, baseCommit *object.Commit
5466

55-
headCommit, err = object.GetCommit(headRepository.Storer, headCommitHash)
67+
headCommit, err = object.GetCommit(repo.Storer, headCommitHash)
5668
if err != nil {
5769
http.Error(w, err.Error(), http.StatusNotFound)
5870
return
5971
}
6072

61-
baseCommit, err = object.GetCommit(baseRepository.Storer, baseCommitHash)
73+
baseCommit, err = object.GetCommit(repo.Storer, baseCommitHash)
6274
if err != nil {
6375
http.Error(w, err.Error(), http.StatusNotFound)
6476
return
6577
}
6678

6779
var headTree, baseTree *object.Tree
6880

69-
headTree, err = object.GetTree(headRepository.Storer, headCommit.TreeHash)
81+
headTree, err = object.GetTree(repo.Storer, headCommit.TreeHash)
7082
if err != nil {
7183
http.Error(w, err.Error(), http.StatusNotFound)
7284
return
7385
}
7486

75-
baseTree, err = object.GetTree(baseRepository.Storer, baseCommit.TreeHash)
87+
baseTree, err = object.GetTree(repo.Storer, baseCommit.TreeHash)
7688
if err != nil {
7789
http.Error(w, err.Error(), http.StatusNotFound)
7890
return

utils/content.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ type ContentRequestBody struct {
2424
RefId string `json:"ref_id"`
2525
Path string `json:"path"`
2626
IncludeLastCommit bool `json:"include_last_commit"`
27+
From uint64 `json:"from"`
28+
To uint64 `json:"to"`
2729
Pagination *PageRequest `json:"pagination"`
2830
NoRestriction bool `json:"no_restriction"`
2931
}

utils/pull.go

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,28 @@ const (
6565
MergeStyleRebaseUpdate MergeStyle = "rebase-update-only"
6666
)
6767

68+
// Add head repo remote
69+
func addCacheRepo(staging, cache string) error {
70+
p := filepath.Join(staging, ".git", "objects", "info", "alternates")
71+
f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
72+
if err != nil {
73+
log.Printf("Could not create .git/objects/info/alternates file in %s: %v\n", staging, err)
74+
return err
75+
}
76+
defer f.Close()
77+
data := filepath.Join(cache, "objects")
78+
if _, err := fmt.Fprintln(f, data); err != nil {
79+
log.Printf("Could not write to .git/objects/info/alternates file in %s: %v\n", staging, err)
80+
return err
81+
}
82+
return nil
83+
}
84+
6885
func CreateQuarantineRepo(baseRepositoryID uint64, headRepositoryID uint64, baseBranch string, headBranch string) (string, error) {
6986
// Clone base repo
7087
tmpBasePath, err := ioutil.TempDir(os.TempDir(), "merge-")
7188
if err != nil {
72-
log.Fatal(err)
89+
log.Fatal(err) // TODO: fix crash on request specific failure
7390
}
7491

7592
gitDir := viper.GetString("GIT_DIR")
@@ -87,70 +104,52 @@ func CreateQuarantineRepo(baseRepositoryID uint64, headRepositoryID uint64, base
87104
baseBranchName := "base"
88105

89106
// Add head repo remote.
90-
addCacheRepo := func(staging, cache string) error {
91-
p := filepath.Join(staging, ".git", "objects", "info", "alternates")
92-
f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
93-
if err != nil {
94-
log.Printf("Could not create .git/objects/info/alternates file in %s: %v\n", staging, err)
95-
os.RemoveAll(tmpBasePath)
96-
return err
97-
}
98-
defer f.Close()
99-
data := filepath.Join(cache, "objects")
100-
if _, err := fmt.Fprintln(f, data); err != nil {
101-
log.Printf("Could not write to .git/objects/info/alternates file in %s: %v\n", staging, err)
102-
os.RemoveAll(tmpBasePath)
103-
return err
104-
}
105-
return nil
106-
}
107-
108107
if err := addCacheRepo(tmpBasePath, baseRepoPath); err != nil {
109-
log.Printf("Unable to add base repository to temporary repo [%s -> %s]: %v\n", baseRepoPath, tmpBasePath, err)
108+
log.Printf("unable to add base repository to temporary repo [%s -> %s]: %v\n", baseRepoPath, tmpBasePath, err)
110109
os.RemoveAll(tmpBasePath)
111-
return "", fmt.Errorf("Unable to add base repository to temporary repo [%s -> tmpBasePath]: %v", baseRepoPath, err)
110+
return "", fmt.Errorf("unable to add base repository to temporary repo [%s -> tmpBasePath]: %v", baseRepoPath, err)
112111
}
113112

114113
cmd := exec.Command("git", "remote", "add", "-t", baseBranch, "-m", baseBranch, "origin", baseRepoPath)
115114
cmd.Dir = tmpBasePath
116115
out, err := cmd.Output()
117116
if err != nil {
118-
log.Printf("Unable to add base repository as origin [%s -> %s]: %v\n%s\n", baseRepoPath, tmpBasePath, err, string(out))
117+
log.Printf("unable to add base repository as origin [%s -> %s]: %v\n%s\n", baseRepoPath, tmpBasePath, err, string(out))
119118
os.RemoveAll(tmpBasePath)
120-
return "", fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %v\n%s", baseRepoPath, err, out)
119+
return "", fmt.Errorf("unable to add base repository as origin [%s -> tmpBasePath]: %v\n%s", baseRepoPath, err, out)
121120
}
122121

123122
cmd = exec.Command("git", "fetch", "origin", "--no-tags", "--", baseBranch+":"+baseBranchName, baseBranch+":original_"+baseBranchName)
124123
cmd.Dir = tmpBasePath
125124
out, err = cmd.Output()
126125
if err != nil {
127-
log.Printf("Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n", baseRepoPath, baseBranch, tmpBasePath, err, string(out))
126+
log.Printf("unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n", baseRepoPath, baseBranch, tmpBasePath, err, string(out))
128127
os.RemoveAll(tmpBasePath)
129-
return "", fmt.Errorf("Unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %v\n%s", baseRepoPath, baseBranch, err, string(out))
128+
return "", fmt.Errorf("unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %v\n%s", baseRepoPath, baseBranch, err, string(out))
130129
}
131130

132131
cmd = exec.Command("git", "symbolic-ref", "HEAD", BranchPrefix+baseBranchName)
133132
cmd.Dir = tmpBasePath
134133
out, err = cmd.Output()
135134
if err != nil {
136-
log.Printf("Unable to set HEAD as base branch [%s]: %v\n%s\n", tmpBasePath, err, string(out))
135+
log.Printf("unable to set HEAD as base branch [%s]: %v\n%s\n", tmpBasePath, err, string(out))
137136
os.RemoveAll(tmpBasePath)
138-
return "", fmt.Errorf("Unable to set HEAD as base branch [tmpBasePath]: %v\n%s", err, string(out))
137+
return "", fmt.Errorf("unable to set HEAD as base branch [tmpBasePath]: %v\n%s", err, string(out))
139138
}
140139

141140
if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
142-
log.Printf("Unable to add head repository to temporary repo [%s -> %s]: %v\n", headRepoPath, tmpBasePath, err)
141+
log.Printf("unable to add head repository to temporary repo [%s -> %s]: %v\n", headRepoPath, tmpBasePath, err)
143142
os.RemoveAll(tmpBasePath)
144-
return "", fmt.Errorf("Unable to head base repository to temporary repo [%s -> tmpBasePath]: %v", headRepoPath, err)
143+
return "", fmt.Errorf("unable to head base repository to temporary repo [%s -> tmpBasePath]: %v", headRepoPath, err)
145144
}
146145

147146
cmd = exec.Command("git", "remote", "add", remoteRepoName, headRepoPath)
148147
cmd.Dir = tmpBasePath
149148
out, err = cmd.Output()
150149
if err != nil {
151-
log.Printf("Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n", headRepoPath, tmpBasePath, err, string(out))
150+
log.Printf("unable to add head repository as head_repo [%s -> %s]: %v\n%s\n", headRepoPath, tmpBasePath, err, string(out))
152151
os.RemoveAll(tmpBasePath)
153-
return "", fmt.Errorf("Unable to add head repository as head_repo [%s -> tmpBasePath]: %v\n%s", headRepoPath, err, string(out))
152+
return "", fmt.Errorf("unable to add head repository as head_repo [%s -> tmpBasePath]: %v\n%s", headRepoPath, err, string(out))
154153
}
155154

156155
trackingBranch := "tracking"
@@ -160,9 +159,42 @@ func CreateQuarantineRepo(baseRepositoryID uint64, headRepositoryID uint64, base
160159
cmd.Dir = tmpBasePath
161160
out, err = cmd.Output()
162161
if err != nil {
162+
log.Printf("unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n", headRepoPath, headBranch, tmpBasePath, err, string(out))
163+
os.RemoveAll(tmpBasePath)
164+
return "", fmt.Errorf("unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %v\n%s", headRepoPath, headBranch, err, string(out))
165+
}
166+
167+
return tmpBasePath, nil
168+
}
169+
170+
func CreateReadOnlyQuarantineRepo(baseRepositoryID uint64, headRepositoryID uint64) (string, error) {
171+
// Clone base repo
172+
tmpBasePath, err := ioutil.TempDir(os.TempDir(), "merge-")
173+
if err != nil {
174+
log.Fatal(err)
175+
}
176+
177+
gitDir := viper.GetString("GIT_DIR")
178+
baseRepoPath := path.Join(gitDir, fmt.Sprintf("%v.git", baseRepositoryID))
179+
headRepoPath := path.Join(gitDir, fmt.Sprintf("%v.git", headRepositoryID))
180+
181+
_, err = git.InitRepository(tmpBasePath, false)
182+
if err != nil {
183+
log.Printf("git init tmpBasePath: %v\n", err)
184+
os.RemoveAll(tmpBasePath)
185+
return "", err
186+
}
187+
188+
if err := addCacheRepo(tmpBasePath, baseRepoPath); err != nil {
189+
log.Printf("unable to add base repository to temporary repo [%s -> %s]: %v\n", baseRepoPath, tmpBasePath, err)
190+
os.RemoveAll(tmpBasePath)
191+
return "", fmt.Errorf("unable to add base repository to temporary repo [%s -> tmpBasePath]: %v", baseRepoPath, err)
192+
}
193+
194+
if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
195+
log.Printf("unable to add head repository to temporary repo [%s -> %s]: %v\n", headRepoPath, tmpBasePath, err)
163196
os.RemoveAll(tmpBasePath)
164-
log.Printf("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n", headRepoPath, headBranch, tmpBasePath, err, string(out))
165-
return "", fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %v\n%s", headRepoPath, headBranch, err, string(out))
197+
return "", fmt.Errorf("unable to head base repository to temporary repo [%s -> tmpBasePath]: %v", headRepoPath, err)
166198
}
167199

168200
return tmpBasePath, nil

0 commit comments

Comments
 (0)