github.com/go-crzy/go-git-http-xfer@v1.4.1-0.20210704194527-d62541d1b6b5/addon/handler/archive/archive.go (about)

     1  package archive
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"path"
     7  	"regexp"
     8  	"strings"
     9  
    10  	"net/url"
    11  
    12  	"github.com/go-crzy/go-git-http-xfer/githttpxfer"
    13  )
    14  
    15  var (
    16  	archiveRegexp = regexp.MustCompile(".*?(/archive/.*?\\.(zip|tar))$")
    17  	Pattern       = func(u *url.URL) *githttpxfer.Match {
    18  		m := archiveRegexp.FindStringSubmatch(u.Path)
    19  		if m == nil {
    20  			return nil
    21  		}
    22  		suffix := m[1]
    23  		repoPath := strings.Replace(u.Path, suffix, "", 1)
    24  		filePath := strings.Replace(u.Path, repoPath+"/", "", 1)
    25  		return &githttpxfer.Match{repoPath, filePath}
    26  	}
    27  	Method = http.MethodGet
    28  )
    29  
    30  func New(ghx *githttpxfer.GitHTTPXfer) *gitHTTPXfer {
    31  	return &gitHTTPXfer{ghx}
    32  }
    33  
    34  type gitHTTPXfer struct {
    35  	*githttpxfer.GitHTTPXfer
    36  }
    37  
    38  func (ghx *gitHTTPXfer) Archive(ctx githttpxfer.Context) {
    39  
    40  	res, repoPath, filePath := ctx.Response(), ctx.RepoPath(), ctx.FilePath()
    41  
    42  	repoName := strings.Split(path.Base(repoPath), ".")[0]
    43  	fileName := path.Base(filePath)
    44  	tree := fileName[0:strings.LastIndex(fileName, ".")]
    45  	ext := path.Ext(fileName)
    46  	format := strings.Replace(ext, ".", "", 1)
    47  
    48  	args := []string{"archive", "--format=" + format, "--prefix=" + repoName + "-" + tree + "/", tree}
    49  	cmd := ghx.Git.GitCommand(repoPath, args...)
    50  	cmd.Env = ctx.Env()
    51  
    52  	stdout, err := cmd.StdoutPipe()
    53  	if err != nil {
    54  		githttpxfer.RenderInternalServerError(res.Writer)
    55  		return
    56  	}
    57  	defer stdout.Close()
    58  
    59  	if err := cmd.Start(); err != nil {
    60  		githttpxfer.RenderInternalServerError(res.Writer)
    61  		return
    62  	}
    63  
    64  	res.SetContentType("application/octet-stream")
    65  	res.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
    66  	res.Header().Add("Content-Transfer-Encoding", "binary")
    67  
    68  	if _, err := res.Copy(stdout); err != nil {
    69  		githttpxfer.RenderInternalServerError(res.Writer)
    70  		return
    71  	}
    72  	if err := cmd.Wait(); err != nil {
    73  		githttpxfer.RenderInternalServerError(res.Writer)
    74  	}
    75  }