diff options
Diffstat (limited to 'internal/github/github.go')
-rw-r--r-- | internal/github/github.go | 262 |
1 files changed, 0 insertions, 262 deletions
diff --git a/internal/github/github.go b/internal/github/github.go deleted file mode 100644 index bf35a6a..0000000 --- a/internal/github/github.go +++ /dev/null @@ -1,262 +0,0 @@ -package github - -import ( - "fmt" - "io" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "regexp" - "time" -) - -type Client struct { - *jsonClient -} - -func NewClient() *Client { - jsonClient := newJSONClient(http.DefaultClient, "https://api.github.com") - return &Client{ - jsonClient: jsonClient, - } -} - -type Asset struct { - Name string `json:"name"` - BrowserDownloadURL string `json:"browser_download_url"` -} - -type Release struct { - ID int `json:"id"` - TagName string `json:"tag_name"` - PublishedAt time.Time `json:"published_at"` - TarballURL string `json:"tarball_url"` - ZipballURL string `json:"zipball_url"` - Assets []Asset `json:"assets"` -} - -func intRef(v int) *int { - return &v -} - -func (c *Client) ListReleases(owner string, project string) ([]Release, error) { - var resp []Release - - _, err := c.jsonClient.Request(http.MethodGet, intRef(http.StatusOK), path.Join("repos", owner, project, "releases"), nil, &resp) - if err != nil { - return nil, err - } - - return resp, nil -} - -func (c *Client) DownloadAsset(w io.Writer, owner string, project string, asset *Asset) error { - resp, err := http.Get(asset.BrowserDownloadURL) - if err != nil { - return err - } - - _, err = io.Copy(w, resp.Body) - if err != nil { - return err - } - return nil - -} - -func (c *Client) DownloadRelease( - dirPath string, - org string, - project string, - release *Release, -) error { - for _, asset := range release.Assets { - fp := path.Join(dirPath, path.Base(asset.Name)) - f, err := os.Create(fp) - if err != nil { - return err - } - defer f.Close() - - resp, err := http.Get(asset.BrowserDownloadURL) - if err != nil { - return err - } - _, err = io.Copy(f, resp.Body) - if err != nil { - return err - } - } - - fp := path.Join(dirPath, releaseSourceFileName(project, release.TagName, "tar.gz")) - if exist, err := isFileExist(fp); err != nil { - return fmt.Errorf("downloading tarball: %w", err) - } else if !exist { - f, err := os.Create(fp) - if err != nil { - return err - } - defer f.Close() - - resp, err := http.Get(release.TarballURL) - if err != nil { - return err - } - _, err = io.Copy(f, resp.Body) - if err != nil { - return err - } - } - - fp = path.Join(dirPath, releaseSourceFileName(project, release.TagName, "zip")) - if exist, err := isFileExist(fp); err != nil { - return err - } else if !exist { - f, err := os.Create(fp) - if err != nil { - return fmt.Errorf("downloading zipball: %w", err) - } - defer f.Close() - - resp, err := http.Get(release.ZipballURL) - if err != nil { - return err - } - _, err = io.Copy(f, resp.Body) - if err != nil { - return err - } - } - - return nil -} - -func releaseDownloads( - project string, - release *Release, -) map[string]string { - files := make(map[string]string) - - for _, asset := range release.Assets { - files[path.Base(asset.Name)] = asset.BrowserDownloadURL - } - - fileName := releaseSourceFileName(project, release.TagName, "tar.gz") - files[fileName] = release.TarballURL - - fileName = releaseSourceFileName(project, release.TagName, "zip") - files[fileName] = release.ZipballURL - - return files -} - -func (c *Client) download(dst string, src string) error { - resp, err := http.Head(src) - if err != nil { - return err - } - - info, err := os.Stat(dst) - if !os.IsNotExist(err) && err != nil { - return err - } - if info != nil { - if info.Size() == resp.ContentLength { - return nil - } - - err := os.Remove(dst) - if !os.IsNotExist(err) && err != nil { - return fmt.Errorf("could not remove '%s': %w", dst, err) - } - } - - resp, err = http.Get(src) - if err != nil { - return err - } - - f, err := os.Create(dst) - if err != nil { - return fmt.Errorf("creating '%s': %w", dst, err) - } - defer f.Close() - - _, err = io.Copy(f, resp.Body) - if err != nil { - return err - } - - return nil -} - -func (c *Client) MirrorAssets(dst *url.URL, src *url.URL) error { - if src.Hostname() != "github.com" { - return fmt.Errorf("host must be github.com") - } - if dst.Scheme != "file:///" && dst.Scheme != "" { - return fmt.Errorf("unsupported destination scheme '%s'", dst.Scheme) - } - - matches := regexp.MustCompilePOSIX("/(.*?)/(.*?)").FindAllStringSubmatch(src.Path, 1) - if len(matches) != 1 && len(matches[0]) != 2 { - return fmt.Errorf("must be a full path to the project") - } - - owner := matches[0][1] - project := matches[0][2] - - releases, err := c.ListReleases(owner, project) - if err != nil { - return fmt.Errorf("fetching list of releases: %w", err) - } - - existingFiles := make(map[string]bool) - - filepath.WalkDir(dst.Path, func(path string, _ os.DirEntry, err error) error { - if err != nil { - return err - } - - path, err = filepath.Abs(path) - if err != nil { - return err - } - existingFiles[path] = true - - return nil - }) - delete(existingFiles, dst.Path) - - for _, release := range releases { - localDir := localReleaseFilePath(dst, release.TagName) - localDir, err = filepath.Abs(localDir) - if err != nil { - return err - } - - err := os.MkdirAll(localDir, 0777) - if err != nil { - return fmt.Errorf("creating '%s': %w", localDir, err) - } - delete(existingFiles, localDir) - - for fileName, srcURL := range releaseDownloads(project, &release) { - localFile := path.Join(localDir, fileName) - delete(existingFiles, localFile) - - err := c.download(localFile, srcURL) - if err != nil { - return fmt.Errorf("downloading '%s': %w", srcURL, err) - } - } - } - - for fp := range existingFiles { - _ = os.RemoveAll(fp) - } - - return nil -} |