Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • bazel/git
1 result
Show changes
Commits on Source (9)
# [1.0.0-alpha.5](https://git.gitlab.arm.com/bazel/git/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2024-04-15)
### Features
- add `bazel-git show` command ([6b8f167](https://git.gitlab.arm.com/bazel/git/commit/6b8f16750751ee09984029842883151c39848f3c))
- add `ls-tree` command ([19227f5](https://git.gitlab.arm.com/bazel/git/commit/19227f555e7c7717f1f07a4dd6368fbe9f7897f3))
- **cat-file:** support existence of files ([1aa84f8](https://git.gitlab.arm.com/bazel/git/commit/1aa84f825e03d1e10d576576a6c3a72ee5566507))
# [1.0.0-alpha.4](https://git.gitlab.arm.com/bazel/git/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2024-04-11)
### Bug Fixes
......
module(
name = "bazel-git",
version = "1.0.0-alpha.4",
version = "1.0.0-alpha.5",
bazel_compatibility = [
">=7.0.0",
],
......@@ -12,7 +12,7 @@ bazel_dep(name = "rules_coreutils", version = "1.0.0-alpha.8")
bazel_dep(name = "rules_go", version = "0.46.0")
bazel_dep(name = "rules_diff", version = "1.0.0-alpha.3")
bazel_dep(name = "hermetic_cc_toolchain", version = "3.0.0")
bazel_dep(name = "gazelle", version = "0.35.0")
bazel_dep(name = "gazelle", version = "0.36.0")
bazel_dep(name = "circl", version = "1.3.3")
# Need https://github.com/bazelbuild/rules_go/pull/3872 to be hermetic
......
This diff is collapsed.
load(":pure.bzl", "COUPLETS")
load("@rules_go//go:def.bzl", "go_binary", "go_library")
load(":pure.bzl", "COUPLETS")
go_library(
name = "bazel-git_lib",
......@@ -11,7 +11,9 @@ go_library(
"fetch.go",
"init.go",
"ls_remote.go",
"ls_tree.go",
"main.go",
"show.go",
],
importpath = "gitlab.arm.com/bazel/git/v1/cmd/bazel-git",
visibility = ["//visibility:private"],
......@@ -22,9 +24,11 @@ go_library(
"@com_github_go_git_go_git_v5//config:go_default_library",
"@com_github_go_git_go_git_v5//plumbing:go_default_library",
"@com_github_go_git_go_git_v5//plumbing/cache:go_default_library",
"@com_github_go_git_go_git_v5//plumbing/object:go_default_library",
"@com_github_go_git_go_git_v5//plumbing/protocol/packp/sideband:go_default_library",
"@com_github_go_git_go_git_v5//storage/filesystem:go_default_library",
"@com_github_go_git_go_git_v5//storage/memory:go_default_library",
"@com_github_go_git_go_git_v5//utils/ioutil:go_default_library",
"@com_github_jessevdk_go_flags//:go_default_library",
"@com_github_kevinburke_ssh_config//:go_default_library",
"@com_github_mattn_go_isatty//:go_default_library",
......
......@@ -3,15 +3,17 @@ package main
import (
"errors"
"log/slog"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/jessevdk/go-flags"
)
type CatFileCommand struct {
ExitCode bool `short:"e" description:"Exit with zero status if <object> exists and is a valid object. If <object> is of an invalid format, exit with non-zero status and emit an error on stderr." required:"yes"`
Args struct {
Exists bool `short:"e" description:"Exit with zero status if <object> exists and is a valid object. If <object> is of an invalid format, exit with non-zero status and emit an error on stderr." required:"yes"`
Args struct {
Revision plumbing.Revision `positional-arg-name:"<object>" description:"The object to check for existence."`
} `positional-args:"yes" required:"yes"`
}
......@@ -34,7 +36,7 @@ func (x *CatFileCommand) Execute(rest []string) error {
log.Debug("resolve")
hash, err := repo.ResolveRevision(x.Args.Revision)
if x.ExitCode && err == plumbing.ErrReferenceNotFound {
if x.Exists && err == plumbing.ErrReferenceNotFound {
// TODO: remove the message
return NewExitCodeError(1, "Not found")
}
......@@ -44,7 +46,38 @@ func (x *CatFileCommand) Execute(rest []string) error {
}
log.Debug("resolved", "hash", hash)
if x.ExitCode {
if x.Exists && strings.Contains(x.Args.Revision.String(), ":") {
log.Debug("commit")
commit, err := repo.CommitObject(*hash)
if err != nil {
log.Error("commit", "err", err)
return err
}
log.Debug("tree")
tree, err := commit.Tree()
if err != nil {
log.Error("tree", "err", err)
return err
}
filepath := strings.SplitN(x.Args.Revision.String(), ":", 2)[1]
log.Debug("file", "filepath", filepath)
_, err = tree.File(filepath)
if err == object.ErrFileNotFound {
// TODO: remove the message
return NewExitCodeError(1, "Not found")
}
if err != nil {
log.Error("tree", "err", err)
return err
}
return nil
}
if x.Exists {
return nil
}
......
package main
import (
"encoding/hex"
"fmt"
"log/slog"
"regexp"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/jessevdk/go-flags"
)
const gitLink = 0160000
type LsTreeCommand struct {
Format string `long:"format" value-name:"<format>" description:"A string that interpolates %(fieldname) from the result being shown." default:"%(objectmode) %(objecttype) %(objectname)%x09%(path)"`
Args struct {
Revision plumbing.Revision `positional-arg-name:"<tree-ish>" description:"Identifier or a tree-ish."`
Paths []string `positional-arg-name:"<path>" description:"The paths to list."`
} `positional-args:"yes" required:"yes"`
}
var lsTreeCommand LsTreeCommand
func (x *LsTreeCommand) Execute(rest []string) error {
if len(rest) != 0 {
return &flags.Error{flags.ErrDuplicatedFlag, "invalid number of positional arguments"}
}
log := slog.With("cmd", "ls-tree", "object", x.Args.Revision, "path", x.Args.Paths)
log.Debug("open", "git-dir", options.GitDir)
repo, err := git.PlainOpen(options.GitDir)
if err != nil {
log.Error("open", "err", err)
return err
}
log.Debug("resolve")
hash, err := repo.ResolveRevision(x.Args.Revision)
if err != nil {
log.Error("resolve", "err", err)
return err
}
log.Debug("resolved", "hash", hash)
log.Debug("commit")
commit, err := repo.CommitObject(*hash)
if err != nil {
log.Error("commit", "err", err)
return err
}
log.Debug("tree")
tree, err := commit.Tree()
if err != nil {
log.Error("tree", "err", err)
return err
}
entries := tree.Entries
if 0 != len(x.Args.Paths) {
entries = nil
for _, path := range x.Args.Paths {
log.Debug("find")
entry, err := tree.FindEntry(path)
if err != nil {
log.Error("find", "err", err)
return err
}
entry.Name = path
entries = append(entries, *entry)
}
}
re := regexp.MustCompile(`%(?:%|x[a-fA-F0-9]{2}|\((?:objectmode|objecttype|objectname|path)\))`)
for _, entry := range entries {
var kind string
if entry.Mode == gitLink {
kind = "commit"
} else {
object, err := repo.Object(plumbing.AnyObject, entry.Hash)
if err != nil {
return err
}
kind = object.Type().String()
}
replace := func(value string) string {
switch value {
case "%(objecttype)":
return kind
case "%(objectmode)":
return fmt.Sprintf("%06o", entry.Mode)
case "%(objectname)":
return entry.Hash.String()
case "%(path)":
return entry.Name
case "%%":
return "%"
}
if strings.HasPrefix(value, "%x") {
if bytes, err := hex.DecodeString(value[2:]); err == nil {
return string(bytes)
}
}
return value
}
line := re.ReplaceAllStringFunc(x.Format, replace)
fmt.Println(line)
}
return err
}
func init() {
parser.AddCommand("ls-tree",
"List the contents of a tree object.",
`Lists the contents of a given tree object, like what "/bin/ls -a" does in the current working directory.`,
&lsTreeCommand)
}
package main
import (
"fmt"
"io"
"log/slog"
"os"
"strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/jessevdk/go-flags"
)
type ShowCommand struct {
Args struct {
Revision plumbing.Revision `positional-arg-name:"<object>" description:"The object to show."`
} `positional-args:"yes" required:"yes"`
}
var showCommand ShowCommand
func (x *ShowCommand) Execute(rest []string) error {
if len(rest) != 0 {
return &flags.Error{flags.ErrDuplicatedFlag, "invalid number of positional arguments"}
}
log := slog.With("cmd", "show", "object", x.Args.Revision)
log.Debug("open", "git-dir", options.GitDir)
repo, err := git.PlainOpen(options.GitDir)
if err != nil {
log.Error("open", "err", err)
return err
}
log.Debug("resolve")
hash, err := repo.ResolveRevision(x.Args.Revision)
if err != nil {
log.Error("resolve", "err", err)
return err
}
log.Debug("resolved", "hash", hash)
if !strings.Contains(x.Args.Revision.String(), ":") {
return fmt.Errorf("Only blobs with filepaths are supported (`<commit>:<filepath>`) : %s", x.Args.Revision.String())
}
log.Debug("commit")
commit, err := repo.CommitObject(*hash)
if err != nil {
log.Error("commit", "err", err)
return err
}
log.Debug("tree")
tree, err := commit.Tree()
if err != nil {
log.Error("tree", "err", err)
return err
}
filepath := strings.SplitN(x.Args.Revision.String(), ":", 2)[1]
log.Debug("file", "filepath", filepath)
file, err := tree.File(filepath)
if err != nil {
log.Error("tree", "err", err)
return err
}
log.Debug("reader")
reader, err := file.Reader()
if err != nil {
log.Error("reader", "err", err)
return err
}
defer ioutil.CheckClose(reader, &err)
log.Debug("copy")
_, err = io.Copy(os.Stdout, reader)
if err != nil {
log.Error("copy", "err", err)
return err
}
return err
}
func init() {
parser.AddCommand("show",
"Show various types of objects.",
`Shows one or more objects (blobs, tree, tags and commits).
For commits it shows the log message and textual diff. It also presents the merge
commit in a special format as produced by 'git diff-tree --cc'.
For tags, it shows the tag message and the referenced objects.
For trees, it shows the names (equivalent to 'git ls-tree' with '--name-only').
For plain blobs, it shows the plain contents.`,
&showCommand)
}