Repository: go-gitea/gitea
File: services/repository/archiver/archiver.go (Go)

Code before:
func DeleteRepositoryArchives(ctx context.Context) error {
	if err := repo_model.DeleteAllRepoArchives(ctx); err != nil {
		return err
	}
	return storage.Clean(storage.RepoArchives)
}

func ServeRepoArchive(ctx *gitea_context.Base, archiveReq *ArchiveRequest) error {
	// Add nix format link header so tarballs lock correctly:
	// https://github.com/nixos/nix/blob/56763ff918eb308db23080e560ed2ea3e00c80a7/doc/manual/src/protocols/tarball-fetcher.md
	ctx.Resp.Header().Add("Link", fmt.Sprintf(`<%s/archive/%s.%s?rev=%s>; rel="immutable"`,
		archiveReq.Repo.APIURL(),
		archiveReq.CommitID,
		archiveReq.Type.String(),
		archiveReq.CommitID,
	))
	downloadName := archiveReq.Repo.Name + "-" + archiveReq.GetArchiveName()

	if setting.Repository.StreamArchives || len(archiveReq.Paths) > 0 {
		// the header must be set before starting streaming even an error would occur,
		// because errors may happen in git command and such cases aren't in our control.
		httplib.ServeSetHeaders(ctx.Resp, &httplib.ServeHeaderOptions{Filename: downloadName})
		if err := archiveReq.Stream(ctx, ctx.Resp); err != nil && !ctx.Written() {
			// we can't use RunStdError as ConcatenateError doesn't return it.
			// TODO: Investigate removing WithStdError completely and always returning RunStdError from failed git calls.
			if strings.Contains(err.Error(), "fatal: pathspec") {
				return util.NewInvalidArgumentErrorf("path doesn't exist or is invalid")
			}
			return fmt.Errorf("archive repo %s: failed to stream: %w", archiveReq.Repo.FullName(), err)
		}
		return nil
	}

	archiver, err := archiveReq.Await(ctx)
	if err != nil {
		return fmt.Errorf("archive repo %s: failed to await: %w", archiveReq.Repo.FullName(), err)
	}

	rPath := archiver.RelativePath()
	if setting.RepoArchive.Storage.ServeDirect() {
		// If we have a signed url (S3, object storage), redirect to this directly.
		u, err := storage.RepoArchives.URL(rPath, downloadName, ctx.Req.Method, nil)
		if u != nil && err == nil {
			ctx.Redirect(u.String())
			return nil
		}
	}

	fr, err := storage.RepoArchives.Open(rPath)
	if err != nil {
		return fmt.Errorf("archive repo %s: failed to open archive file: %w", archiveReq.Repo.FullName(), err)

Review comment (suggestion):
```
if ok := errors.As(err, &gitErr); ok && strings.HasPrefix(gitErr.Stderr(), "fatal: pathspec") {
```

~~It should be like this.~~

Hmm, indeed, it doesn't return RunStdError, will take a look

Code after:
// DeleteRepositoryArchives deletes all repositories' archives.
func DeleteRepositoryArchives(ctx context.Context) error {
	if err := repo_model.DeleteAllRepoArchives(ctx); err != nil {
		return err
	}
	return storage.Clean(storage.RepoArchives)
}

func ServeRepoArchive(ctx *gitea_context.Base, archiveReq *ArchiveRequest) error {
	// Add nix format link header so tarballs lock correctly:
	// https://github.com/nixos/nix/blob/56763ff918eb308db23080e560ed2ea3e00c80a7/doc/manual/src/protocols/tarball-fetcher.md
	ctx.Resp.Header().Add("Link", fmt.Sprintf(`<%s/archive/%s.%s?rev=%s>; rel="immutable"`,
		archiveReq.Repo.APIURL(),
		archiveReq.CommitID,
		archiveReq.Type.String(),
		archiveReq.CommitID,
	))
	downloadName := archiveReq.Repo.Name + "-" + archiveReq.GetArchiveName()

	if setting.Repository.StreamArchives || len(archiveReq.Paths) > 0 {
		// the header must be set before starting streaming even an error would occur,
		// because errors may happen in git command and such cases aren't in our control.
		httplib.ServeSetHeaders(ctx.Resp, &httplib.ServeHeaderOptions{Filename: downloadName})
		if err := archiveReq.Stream(ctx, ctx.Resp); err != nil && !ctx.Written() {
			if gitcmd.StderrHasPrefix(err, "fatal: pathspec") {
				return util.NewInvalidArgumentErrorf("path doesn't exist or is invalid")
			}
			return fmt.Errorf("archive repo %s: failed to stream: %w", archiveReq.Repo.FullName(), err)
		}
		return nil
	}

	archiver, err := archiveReq.Await(ctx)
	if err != nil {
		return fmt.Errorf("archive repo %s: failed to await: %w", archiveReq.Repo.FullName(), err)
	}

	rPath := archiver.RelativePath()
	if setting.RepoArchive.Storage.ServeDirect() {
		// If we have a signed url (S3, object storage), redirect to this directly.
		u, err := storage.RepoArchives.URL(rPath, downloadName, ctx.Req.Method, nil)
		if u != nil && err == nil {
			ctx.Redirect(u.String())
			return nil
		}
	}

	fr, err := storage.RepoArchives.Open(rPath)
	if err != nil {
		return fmt.Errorf("archive repo %s: failed to open archive file: %w", archiveReq.Repo.FullName(), err)
	}