.
This commit is contained in:
@@ -303,7 +303,8 @@ func parseGitMsg(data <-chan byte) (gitMsg, error) {
|
||||
id = id[:pos]
|
||||
|
||||
pos = 0
|
||||
for c := <-data; c != ' '; c = <-data {
|
||||
var c byte
|
||||
for c = <-data; c != ' ' && c != '\x00'; c = <-data {
|
||||
if c >= 'a' && c <= 'z' {
|
||||
msgType[pos] = c
|
||||
pos++
|
||||
@@ -314,13 +315,22 @@ func parseGitMsg(data <-chan byte) (gitMsg, error) {
|
||||
msgType = msgType[:pos]
|
||||
|
||||
switch string(msgType) {
|
||||
case "commit", "tree":
|
||||
case "commit", "tree", "blob":
|
||||
break
|
||||
case "missing":
|
||||
if c != '\x00' {
|
||||
return gitMsg{}, fmt.Errorf("Missing format weird")
|
||||
}
|
||||
return gitMsg{
|
||||
hash: string(id[:]),
|
||||
itemType: "missing",
|
||||
size: 0,
|
||||
}, fmt.Errorf("Object not found: '%s'", string(id))
|
||||
default:
|
||||
return gitMsg{}, fmt.Errorf("Invalid object type: '%s'", string(msgType))
|
||||
}
|
||||
|
||||
for c := <-data; c != '\000'; c = <-data {
|
||||
for c = <-data; c != '\000'; c = <-data {
|
||||
if c >= '0' && c <= '9' {
|
||||
size = size*10 + (int(c) - '0')
|
||||
} else {
|
||||
@@ -357,6 +367,12 @@ func parseGitCommitMsg(data <-chan byte, l int) (string, error) {
|
||||
|
||||
for c := <-data; c != '\x00'; c = <-data {
|
||||
msg = append(msg, c)
|
||||
l--
|
||||
}
|
||||
// l--
|
||||
|
||||
if l != 0 {
|
||||
return "", fmt.Errorf("Unexpected data in the git commit msg: l=%d", l)
|
||||
}
|
||||
|
||||
return string(msg), nil
|
||||
@@ -434,7 +450,8 @@ func parseGitTree(data <-chan byte) (tree, error) {
|
||||
|
||||
// max capacity to length of hash
|
||||
t := tree{items: make([]tree_entry, 0, hdr.size/len(hdr.hash))}
|
||||
for parsedLen := 0; parsedLen+1 < hdr.size; {
|
||||
parsedLen := 0
|
||||
for parsedLen < hdr.size {
|
||||
entry, err := parseTreeEntry(data, len(hdr.hash)/2)
|
||||
if err != nil {
|
||||
return tree{}, nil
|
||||
@@ -443,10 +460,103 @@ func parseGitTree(data <-chan byte) (tree, error) {
|
||||
t.items = append(t.items, entry)
|
||||
parsedLen += entry.size
|
||||
}
|
||||
c := <-data // \0 read
|
||||
|
||||
if c != '\x00' {
|
||||
return t, fmt.Errorf("Unexpected character during git tree data read")
|
||||
}
|
||||
|
||||
if parsedLen != hdr.size {
|
||||
return t, fmt.Errorf("Invalid size of git tree data")
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func parseGitBlob(data <-chan byte) ([]byte, error) {
|
||||
hdr, err := parseGitMsg(data)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
d := make([]byte, hdr.size)
|
||||
for l:=0; l<hdr.size; l++ {
|
||||
d[l] = <-data
|
||||
}
|
||||
eob := <-data
|
||||
if eob != '\x00' {
|
||||
return d, fmt.Errorf("invalid byte read in parseGitBlob")
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// TODO: support sub-trees
|
||||
func (e *RequestHandler) GitCatFile(cwd, commitId, filename string) []byte {
|
||||
var done sync.Mutex
|
||||
var data []byte
|
||||
|
||||
done.Lock()
|
||||
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
|
||||
|
||||
go func() {
|
||||
defer done.Unlock()
|
||||
defer close(data_out.ch)
|
||||
|
||||
data_out.Write([]byte(commitId))
|
||||
data_out.ch <- '\x00'
|
||||
c, err := parseGitCommit(data_in.ch)
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git commit: %v", err)
|
||||
return
|
||||
}
|
||||
data_out.Write([]byte(c.Tree))
|
||||
data_out.ch <- '\x00'
|
||||
tree, err := parseGitTree(data_in.ch)
|
||||
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git tree: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, te := range tree.items {
|
||||
if te.isBlob() && te.name == filename {
|
||||
data_out.Write([]byte(te.hash))
|
||||
data_out.ch <- '\x00'
|
||||
data, err = parseGitBlob(data_in.ch)
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error reading blob data: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.Error = fmt.Errorf("file not found: '%s'", filename)
|
||||
e.LogPlainError(e.Error)
|
||||
}()
|
||||
|
||||
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
|
||||
cmd.Env = []string{
|
||||
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
|
||||
"GIT_CONFIG_GLOBAL=/dev/null",
|
||||
}
|
||||
cmd.Dir = filepath.Join(e.GitPath, cwd)
|
||||
cmd.Stdout = &data_in
|
||||
cmd.Stdin = &data_out
|
||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||
e.Logger.LogError("%s", data)
|
||||
return len(data), nil
|
||||
})
|
||||
e.Log("command run: %v", cmd.Args)
|
||||
e.Error = cmd.Run()
|
||||
|
||||
done.Lock()
|
||||
return data
|
||||
}
|
||||
|
||||
func (e *RequestHandler) GitSubmoduleList(cwd, commitId string) map[string]string {
|
||||
var done sync.Mutex
|
||||
submoduleList := make(map[string]string)
|
||||
|
||||
Reference in New Issue
Block a user