mirror of
https://github.com/Jguer/yay
synced 2024-09-14 13:51:12 +00:00
80c59a74cc
Use the command `git ls-remote <url> <branch>` to track devel updates rather than relying on the GitHub API. This allows devel update to work for every git based source and elimantes the rate limiting from GitHub. The yay_vcs.json format has changed to better support packages which multiple vcs sources and to track the protocols each source uses. And track the branch that each source tracks in it's fragment.
176 lines
3.4 KiB
Go
176 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Info contains the last commit sha of a repo
|
|
type vcsInfo map[string]shaInfos
|
|
type shaInfos map[string]shaInfo
|
|
type shaInfo struct {
|
|
Protocols []string `json:"protocols"`
|
|
Brach string `json:"branch"`
|
|
SHA string `json:"sha"`
|
|
}
|
|
|
|
// createDevelDB forces yay to create a DB of the existing development packages
|
|
func createDevelDB() error {
|
|
_, _, _, remoteNames, err := filterPackages()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
config.NoConfirm = true
|
|
arguments := makeArguments()
|
|
arguments.addArg("gendb")
|
|
arguments.addTarget(remoteNames...)
|
|
err = install(arguments)
|
|
return err
|
|
}
|
|
|
|
// parseSource returns the git url and efault branch
|
|
func parseSource(source string) (url string, branch string, protocols []string) {
|
|
if !(strings.Contains(source, "git://") ||
|
|
strings.Contains(source, ".git") ||
|
|
strings.Contains(source, "git+https://")) {
|
|
return
|
|
}
|
|
split := strings.Split(source, "::")
|
|
source = split[len(split)-1]
|
|
split = strings.SplitN(source, "://", 2)
|
|
|
|
if len(split) != 2 {
|
|
return
|
|
}
|
|
|
|
protocols = strings.Split(split[0], "+")
|
|
split = strings.SplitN(split[1], "#", 2)
|
|
if len(split) == 2 {
|
|
secondSplit := strings.SplitN(split[1], "=", 2)
|
|
if secondSplit[0] != "branch" {
|
|
//source has #commit= or #tag= which makes them not vcs
|
|
//packages because they reference a specific point
|
|
return
|
|
}
|
|
|
|
if len(secondSplit) == 2 {
|
|
url = split[0]
|
|
branch = secondSplit[1]
|
|
}
|
|
} else {
|
|
url = split[0]
|
|
branch = "HEAD"
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func updateVCSData(pkgName string, sources []string) {
|
|
if savedInfo == nil {
|
|
savedInfo = make(vcsInfo)
|
|
}
|
|
|
|
info := make(shaInfos)
|
|
|
|
for _, source := range sources {
|
|
url, branch, protocols := parseSource(source)
|
|
if url == "" || branch == "" {
|
|
continue
|
|
}
|
|
|
|
commit := getCommit(url, branch, protocols)
|
|
if commit == "" {
|
|
continue
|
|
}
|
|
|
|
info[url] = shaInfo{
|
|
protocols,
|
|
branch,
|
|
commit,
|
|
}
|
|
|
|
savedInfo[pkgName] = info
|
|
saveVCSInfo()
|
|
}
|
|
}
|
|
|
|
func getCommit(url string, branch string, protocols []string) string {
|
|
for _, protocol := range protocols {
|
|
var outbuf bytes.Buffer
|
|
|
|
cmd := exec.Command("git", "ls-remote", protocol+"://"+url, branch)
|
|
cmd.Stdout = &outbuf
|
|
|
|
err := cmd.Start()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
//for some reason
|
|
//git://bitbucket.org/volumesoffun/polyvox.git` hangs on my
|
|
//machine but using http:// instead of git does not hang.
|
|
//Introduce a time out so this can not hang
|
|
timer := time.AfterFunc(5*time.Second, func() {
|
|
cmd.Process.Kill()
|
|
})
|
|
|
|
err = cmd.Wait()
|
|
timer.Stop()
|
|
|
|
if err != nil {
|
|
continue
|
|
}
|
|
err = cmd.Run()
|
|
|
|
stdout := outbuf.String()
|
|
split := strings.Fields(stdout)
|
|
|
|
if len(split) < 2 {
|
|
continue
|
|
}
|
|
|
|
commit := split[0]
|
|
return commit
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (infos shaInfos) needsUpdate() bool {
|
|
for url, info := range infos {
|
|
hash := getCommit(url, info.Brach, info.Protocols)
|
|
if hash != info.SHA {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func inStore(pkgName string) shaInfos {
|
|
return savedInfo[pkgName]
|
|
}
|
|
|
|
func saveVCSInfo() error {
|
|
marshalledinfo, err := json.MarshalIndent(savedInfo, "", "\t")
|
|
if err != nil || string(marshalledinfo) == "null" {
|
|
return err
|
|
}
|
|
in, err := os.OpenFile(vcsFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer in.Close()
|
|
_, err = in.Write(marshalledinfo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = in.Sync()
|
|
return err
|
|
}
|