mirror of https://gitlab.com/gitlab-org/cli.git
137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
package archive
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/dustin/go-humanize"
|
|
"github.com/spf13/cobra"
|
|
"github.com/xanzy/go-gitlab"
|
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
|
)
|
|
|
|
func NewCmdArchive(f *cmdutils.Factory) *cobra.Command {
|
|
var repoArchiveCmd = &cobra.Command{
|
|
Use: "archive <command> [flags]",
|
|
Short: `Get an archive of the repository.`,
|
|
Example: heredoc.Doc(`
|
|
glab repo archive profclems/glab
|
|
glab repo archive # Downloads zip file of current repository
|
|
glab repo archive profclems/glab mydirectory # Downloads repo zip file into mydirectory
|
|
glab repo archive profclems/glab --format=zip # Finds repo for current user and download in zip format
|
|
`),
|
|
Long: heredoc.Doc(`
|
|
Clone supports these shorthands
|
|
|
|
- repo
|
|
- namespace/repo
|
|
- namespace/group/repo
|
|
`),
|
|
Args: cobra.MaximumNArgs(2),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
var name string
|
|
var err error
|
|
|
|
if len(args) != 0 {
|
|
err = f.RepoOverride(args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(args) > 1 {
|
|
name = args[1]
|
|
}
|
|
}
|
|
|
|
apiClient, err := f.HttpClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
repo, err := f.BaseRepo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
format, _ := cmd.Flags().GetString("format")
|
|
|
|
// tar.gz, tar.bz2, tbz, tbz2, tb2, bz2, tar, and zip
|
|
extensions := []string{"tar.gz", "tar.bz2", "tbz", "tbz2", "tb2", "bz2", "tar", "zip"}
|
|
if b := contains(extensions, format); !b {
|
|
return errors.New("format must be one of " + strings.Join(extensions, ","))
|
|
}
|
|
|
|
l := &gitlab.ArchiveOptions{}
|
|
l.Format = gitlab.String(format)
|
|
if sha, _ := cmd.Flags().GetString("sha"); sha != "" {
|
|
l.SHA = gitlab.String(sha)
|
|
}
|
|
ext := *l.Format
|
|
archiveName := strings.ReplaceAll(repo.FullName(), "/", "-") + "." + ext
|
|
if strings.TrimSpace(name) != "" {
|
|
archiveName = name + "." + ext
|
|
}
|
|
|
|
bt, _, err := apiClient.Repositories.Archive(repo.FullName(), l)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r := bytes.NewReader(bt)
|
|
out, err := os.Create(archiveName + ".tmp")
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create repo archive: %v", err)
|
|
}
|
|
|
|
counter := &CloneWriter{}
|
|
if _, err = io.Copy(out, io.TeeReader(r, counter)); err != nil {
|
|
_ = out.Close()
|
|
return fmt.Errorf("failed to write repos: %v", err)
|
|
}
|
|
|
|
fmt.Fprint(f.IO.StdOut, "\n")
|
|
_ = out.Close()
|
|
if err = os.Rename(archiveName+".tmp", archiveName); err != nil {
|
|
return fmt.Errorf("failed to rename tmp repos: %v", err)
|
|
}
|
|
fmt.Fprintln(f.IO.StdOut, "Complete...", archiveName)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
repoArchiveCmd.Flags().StringP("format", "f", "zip", "Optionally Specify format if you want a downloaded archive: {tar.gz|tar.bz2|tbz|tbz2|tb2|bz2|tar|zip} (Default: zip)")
|
|
repoArchiveCmd.Flags().StringP("sha", "s", "", "The commit SHA to download. A tag, branch reference, or SHA can be used. This defaults to the tip of the default branch if not specified")
|
|
|
|
return repoArchiveCmd
|
|
}
|
|
|
|
// CloneWriter w
|
|
type CloneWriter struct {
|
|
Total uint64
|
|
}
|
|
|
|
func (wc *CloneWriter) Write(p []byte) (int, error) {
|
|
n := len(p)
|
|
wc.Total += uint64(n)
|
|
wc.progress()
|
|
return n, nil
|
|
}
|
|
|
|
func (wc CloneWriter) progress() {
|
|
fmt.Printf("\r%s", strings.Repeat(" ", 35))
|
|
fmt.Printf("\rCloning... %s complete", humanize.Bytes(wc.Total))
|
|
}
|
|
|
|
func contains(arr []string, str string) bool {
|
|
for _, a := range arr {
|
|
if a == str {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|