-
-
Notifications
You must be signed in to change notification settings - Fork 139
/
git.go
123 lines (113 loc) · 2.27 KB
/
git.go
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
120
121
122
123
package server
import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"path"
"strings"
"time"
"github.com/esm-dev/esm.sh/server/storage"
"github.com/ije/gox/utils"
)
type GitRef struct {
Ref string
Sha string
}
// list repo refs using `git ls-remote repo`
func listRepoRefs(repo string) (refs []GitRef, err error) {
cacheKey := fmt.Sprintf("gh:%s", repo)
lock := getFetchLock(cacheKey)
lock.Lock()
defer lock.Unlock()
// check cache firstly
if cache != nil {
var data []byte
data, err = cache.Get(cacheKey)
if err == nil && json.Unmarshal(data, &refs) == nil {
return
}
if err != nil && err != storage.ErrNotFound && err != storage.ErrExpired {
log.Error("cache:", err)
}
}
cmd := exec.Command("git", "ls-remote", repo)
out := bytes.NewBuffer(nil)
errOut := bytes.NewBuffer(nil)
cmd.Stdout = out
cmd.Stderr = errOut
err = cmd.Run()
if err != nil {
if errOut.Len() > 0 {
return nil, fmt.Errorf(errOut.String())
}
return nil, err
}
refs = []GitRef{}
for _, line := range strings.Split(out.String(), "\n") {
if line == "" {
continue
}
sha, ref := utils.SplitByLastByte(line, '\t')
refs = append(refs, GitRef{
Ref: ref,
Sha: sha,
})
}
if cache != nil {
cache.Set(cacheKey, utils.MustEncodeJSON(refs), 10*time.Minute)
}
return
}
func ghInstall(wd, name, hash string) (err error) {
url := fmt.Sprintf(`https://codeload.github.com/%s/tar.gz/%s`, name, hash)
res, err := fetch(url)
if err != nil {
return
}
defer res.Body.Close()
// unzip tarball
unziped, err := gzip.NewReader(res.Body)
if err != nil {
return
}
// extract tarball
tr := tar.NewReader(unziped)
rootDir := path.Join(wd, "node_modules", name)
for {
h, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
// strip tarball root dir
hname := strings.Join(strings.Split(h.Name, "/")[1:], "/")
if strings.HasPrefix(hname, ".") {
continue
}
fp := path.Join(rootDir, hname)
if h.Typeflag == tar.TypeDir {
ensureDir(fp)
continue
}
if h.Typeflag != tar.TypeReg {
continue
}
f, err := os.OpenFile(fp, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return err
}
_, err = io.Copy(f, tr)
f.Close()
if err != nil {
return err
}
}
return
}