git.go 5.25 KB
Newer Older
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
package internal

import (
	"fmt"
	"github.com/go-git/go-billy/v5/memfs"
	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/config"
	"github.com/go-git/go-git/v5/plumbing"
	"github.com/go-git/go-git/v5/storage/memory"
	"io/ioutil"
	"log"
	"net/http"
	"path/filepath"
	"sort"
	"strings"
)

type GitMode struct{}

func (g *GitMode) RetrieveSource(pd *ProcessData) *modeData {
	repo, err := git.Init(memory.NewStorage(), memfs.New())
	if err != nil {
		log.Fatalf("could not init git repo: %v", err)
	}

	w, err := repo.Worktree()
	if err != nil {
		log.Fatalf("could not get worktree: %v", err)
	}

	refspec := config.RefSpec("+refs/heads/*:refs/remotes/*")
	remote, err := repo.CreateRemote(&config.RemoteConfig{
		Name:  "upstream",
		URLs:  []string{pd.RpmLocation},
		Fetch: []config.RefSpec{refspec},
	})
	if err != nil {
		log.Fatalf("could not create remote: %v", err)
	}

	list, err := remote.List(&git.ListOptions{})
	if err != nil {
		log.Fatalf("could not list remote: %v", err)
	}

	var branches []string

	for _, ref := range list {
		log.Println(ref.String())
		name := string(ref.Name())
		if strings.HasPrefix(name, fmt.Sprintf("refs/tags/imports/c%d", pd.Version)) {
			branches = append(branches, name)
		}
	}
Mustafa Gezen's avatar
Mustafa Gezen committed
55
56
57
58
59
60
61
62
63
64
65

	// no tags? fetch branches
	if len(branches) == 0 {
		for _, ref := range list {
			name := string(ref.Name())
			prefix := fmt.Sprintf("refs/heads/c%d", pd.Version)
			if strings.HasPrefix(name, prefix) {
				branches = append(branches, name)
			}
		}
	}
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	sort.Strings(branches)

	return &modeData{
		repo:       repo,
		worktree:   w,
		rpmFile:    createPackageFile(filepath.Base(pd.RpmLocation)),
		fileWrites: nil,
		branches:   branches,
	}
}

func (g *GitMode) WriteSource(md *modeData) {
	remote, err := md.repo.Remote("upstream")
	if err != nil {
		log.Fatalf("could not get upstream remote: %v", err)
	}

Mustafa Gezen's avatar
Mustafa Gezen committed
83
84
85
86
87
88
89
90
91
92
93
	var refspec config.RefSpec
	var branchName string

	if strings.HasPrefix(md.tagBranch, "refs/heads") {
		refspec = config.RefSpec(fmt.Sprintf("+%s:%s", md.tagBranch, md.tagBranch))
		branchName = strings.TrimPrefix(md.tagBranch, "refs/heads/")
	} else {
		match := tagImportRegex.FindStringSubmatch(md.tagBranch)
		branchName = match[2]
		refspec = config.RefSpec(fmt.Sprintf("+refs/heads/%s:%s", branchName, md.tagBranch))
	}
94
	log.Printf("checking out upstream refspec %s", refspec)
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
	err = remote.Fetch(&git.FetchOptions{
		RemoteName: "upstream",
		RefSpecs:   []config.RefSpec{refspec},
		Tags:       git.AllTags,
		Force:      true,
	})
	if err != nil {
		log.Fatalf("could not fetch upstream: %v", err)
	}

	err = md.worktree.Checkout(&git.CheckoutOptions{
		Branch: plumbing.ReferenceName(md.tagBranch),
		Force:  true,
	})
	if err != nil {
		log.Fatalf("could not checkout source from git: %v", err)
	}

	_, err = md.worktree.Add(".")
	if err != nil {
		log.Fatalf("could not add worktree: %v", err)
	}

	metadataFile, err := md.worktree.Filesystem.Open(fmt.Sprintf(".%s.metadata", md.rpmFile.Name()))
	if err != nil {
Mustafa Gezen's avatar
Mustafa Gezen committed
120
121
		log.Printf("warn: could not open metadata file, so skipping: %v", err)
		return
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	}

	fileBytes, err := ioutil.ReadAll(metadataFile)
	if err != nil {
		log.Fatalf("could not read metadata file: %v", err)
	}

	client := &http.Client{
		Transport: &http.Transport{
			DisableCompression: false,
		},
	}
	fileContent := strings.Split(string(fileBytes), "\n")
	for _, line := range fileContent {
		if strings.TrimSpace(line) == "" {
			continue
		}

140
141
142
		lineInfo := strings.SplitN(line, " ", 2)
		hash := strings.TrimSpace(lineInfo[0])
		path := strings.TrimSpace(lineInfo[1])
143

Mustafa Gezen's avatar
Mustafa Gezen committed
144
		url := fmt.Sprintf("https://git.centos.org/sources/%s/%s/%s", md.rpmFile.Name(), branchName, hash)
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
		log.Printf("downloading %s", url)

		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			log.Fatalf("could not create new http request: %v", err)
		}
		req.Header.Set("Accept-Encoding", "*")

		resp, err := client.Do(req)
		if err != nil {
			log.Fatalf("could not download dist-git file: %v", err)
		}

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Fatalf("could not read the whole dist-git file: %v", err)
		}
		err = resp.Body.Close()
		if err != nil {
			log.Fatalf("could not close body handle: %v", err)
		}

		f, err := md.worktree.Filesystem.Create(path)
		if err != nil {
			log.Fatalf("could not open file pointer: %v", err)
		}

Mustafa Gezen's avatar
Mustafa Gezen committed
172
		hasher := CompareHash(body, hash)
173
174
175
176
177
		if hasher == nil {
			log.Fatal("checksum in metadata does not match dist-git file")
		}

		md.sourcesToIgnore = append(md.sourcesToIgnore, &ignoredSource{
178
			name:         path,
179
180
181
182
183
184
185
186
187
188
189
190
191
			hashFunction: hasher,
		})

		_, err = f.Write(body)
		if err != nil {
			log.Fatalf("could not copy dist-git file to in-tree: %v", err)
		}
		_ = f.Close()
	}
}

func (g *GitMode) PostProcess(md *modeData) {
	for _, source := range md.sourcesToIgnore {
192
193
194
195
196
197
		_, err := md.worktree.Filesystem.Stat(source.name)
		if err == nil {
			err := md.worktree.Filesystem.Remove(source.name)
			if err != nil {
				log.Fatalf("could not remove dist-git file: %v", err)
			}
198
199
200
201
202
203
204
205
206
207
		}
	}

	_, err := md.worktree.Add(".")
	if err != nil {
		log.Fatalf("could not add git sources: %v", err)
	}
}

func (g *GitMode) ImportName(_ *ProcessData, md *modeData) string {
Mustafa Gezen's avatar
Mustafa Gezen committed
208
209
210
211
212
213
	if tagImportRegex.MatchString(md.tagBranch) {
		match := tagImportRegex.FindStringSubmatch(md.tagBranch)
		return match[3]
	}

	return strings.TrimPrefix(md.tagBranch, "refs/heads/")
214
}