Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify #29

Merged
merged 7 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions .github/workflows/golanglint-ci.yml

This file was deleted.

34 changes: 22 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
name: Tests

on:
push:
name: "Tests"
on: ["push"]

jobs:
build:
runs-on: ubuntu-latest
ci:
name: "Run CI"
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "macOS-latest"]
go: ["1.23.x"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
fetch-depth: 1
- uses: WillAbides/[email protected]
with:
fetch-depth: 2
- uses: actions/setup-go@v3
go-version: ${{ matrix.go }}
- run: "go test ./..."
- run: "go vet ./..."
- uses: dominikh/staticcheck-action@v1
with:
go-version: '1.20'
- name: Run tests
run: go test -v ./...
version: "latest"
install-go: false
cache-key: ${{ matrix.go }}
working-directory: ${{ matrix.dir }}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@

Learning Git Internals by writing a Git in Go.

## CLI Usage

See `go run ./cmd/gitg --help`

70 changes: 66 additions & 4 deletions cmd/gitg/add.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,84 @@
package main

import (
"github.com/richardjennings/g/git"
"fmt"
"github.com/richardjennings/g"
"github.com/spf13/cobra"
"log"
"path/filepath"
"strings"
)

var addCmd = &cobra.Command{
Use: "add <path> ...",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if err := configure(); err != nil {
log.Fatalln(err)
return err
}
return git.Add(args...)
return Add(args...)
},
}

// Add adds one or more file paths to the Index.
func Add(paths ...string) error {
idx, err := g.ReadIndex()
if err != nil {
return err
}
// get working directory files with idx status
wdFiles, err := g.FsStatus(g.Path())
if err != nil {
return err
}
var updates []*g.FileStatus
for _, p := range paths {
if p == "." {
// special case meaning add everything
for _, v := range wdFiles.Files() {
switch v.WorkingDirectoryStatus() {
case g.Untracked, g.WorktreeChangedSinceIndex, g.DeletedInWorktree:
updates = append(updates, v)
}
}
} else {
found := false
for _, v := range wdFiles.Files() {
if v.Path() == p {
switch v.WorkingDirectoryStatus() {
case g.Untracked, g.WorktreeChangedSinceIndex, g.DeletedInWorktree:
updates = append(updates, v)
}
found = true
break
}
}
if !found {
// try directory @todo more efficient implementation
for _, v := range wdFiles.Files() {
if strings.HasPrefix(v.Path(), p+string(filepath.Separator)) {
switch v.WorkingDirectoryStatus() {
case g.Untracked, g.WorktreeChangedSinceIndex, g.DeletedInWorktree:
updates = append(updates, v)
}
found = true
}
}
}

if !found {
return fmt.Errorf("fatal: pathspec '%s' did not match any files (directories not implemented yet)", p)
}
}
}
for _, v := range updates {
if err := idx.Add(v); err != nil {
return err
}
}
// once all files are added to idx struct, write it out
return idx.Write()
}

func init() {
rootCmd.AddCommand(addCmd)
}
55 changes: 49 additions & 6 deletions cmd/gitg/branch.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package main

import (
"github.com/richardjennings/g/git"
"fmt"
"github.com/richardjennings/g"
"github.com/spf13/cobra"
"log"
"io"
"os"
)

Expand All @@ -14,24 +15,66 @@ var branchCmd = &cobra.Command{
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if err := configure(); err != nil {
log.Fatalln(err)
return err
}
if len(args) == 0 {
// default to list branches
return git.ListBranches(os.Stdout)
return ListBranches(os.Stdout)
}
if len(args) == 1 {
if branchDelete {
return git.DeleteBranch(args[0])
return DeleteBranch(args[0])
} else {
// create a branch
return git.CreateBranch(args[0])
return CreateBranch(args[0])
}
}
return nil
},
}

const DeleteBranchCheckedOutErrFmt = "error: Cannot delete branch '%s' checked out at '%s'"

func DeleteBranch(name string) error {
// Delete Branch removes any branch that is not checked out
// @todo more correct semantics
currentBranch, err := g.CurrentBranch()
if err != nil {
return err
}
if name == currentBranch {
return fmt.Errorf(DeleteBranchCheckedOutErrFmt, name, g.Path())
}
return g.DeleteBranch(name)
}

func CreateBranch(name string) error {
return g.CreateBranch(name)
}

func ListBranches(o io.Writer) error {
var err error
currentBranch, err := g.CurrentBranch()
if err != nil {
return err
}
branches, err := g.ListBranches()
if err != nil {
return err
}
for _, v := range branches {
if v == currentBranch {
_, err = o.Write([]byte(fmt.Sprintf("* %v\n", v)))
} else {
_, err = o.Write([]byte(fmt.Sprintf(" %v\n", v)))
}
if err != nil {
return err
}
}
return nil
}

func init() {
branchCmd.Flags().BoolVarP(&branchDelete, "delete", "d", false, "--delete <branch>")
rootCmd.AddCommand(branchCmd)
Expand Down
50 changes: 45 additions & 5 deletions cmd/gitg/commit.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,74 @@
package main

import (
"errors"
"fmt"
"github.com/richardjennings/g/git"
"github.com/richardjennings/g"
"github.com/spf13/cobra"
"log"
"os"
"os/exec"
"time"
)

var commitMessage string

var commitCmd = &cobra.Command{
Use: "commit",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if err := configure(); err != nil {
log.Fatalln(err)
}
var msg []byte
if cmd.Flags().Changed("message") {
msg = []byte(commitMessage)
}
sha, err := git.Commit(msg)
sha, err := Commit(msg)
if err != nil {
fmt.Println(err)
os.Exit(1)
return err
}
fmt.Println(sha.AsHexString())
return nil
},
}

// Commit writes a git commit object from the files in the index
func Commit(message []byte) (g.Sha, error) {
commit := &g.Commit{
Author: fmt.Sprintf("%s <%s>", g.AuthorName(), g.AuthorEmail()),
AuthoredTime: time.Now(),
Committer: fmt.Sprintf("%s <%s>", g.CommitterName(), g.CommitterEmail()),
CommittedTime: time.Now(),
}
if message != nil {
commit.Message = message
} else {
// empty commit file
if err := os.WriteFile(g.EditorFile(), []byte{}, 0600); err != nil {
log.Fatalln(err)
}
ed, args := g.Editor()
args = append(args, g.EditorFile())
cmd := exec.Command(ed, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
log.Fatalln(err)
}
msg, err := os.ReadFile(args[0])
if err != nil {
log.Fatalln(msg)
}
commit.Message = msg
}

if len(commit.Message) == 0 {
return g.Sha{}, errors.New("aborting commit due to empty commit message")
}
return g.CreateCommit(commit)
}

func init() {
commitCmd.Flags().StringVarP(&commitMessage, "message", "m", "", "--message")
rootCmd.AddCommand(commitCmd)
Expand Down
11 changes: 7 additions & 4 deletions cmd/gitg/init.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package main

import (
"github.com/richardjennings/g/git"
"github.com/richardjennings/g"
"github.com/spf13/cobra"
"log"
)

var initCmd = &cobra.Command{
Use: "init",
RunE: func(cmd *cobra.Command, args []string) error {
if err := configure(); err != nil {
log.Fatalln(err)
return err
}
return git.Init()
return Init()
},
}

func Init() error {
return g.Init()
}

func init() {
rootCmd.AddCommand(initCmd)
}
4 changes: 2 additions & 2 deletions git/integration_test.go → cmd/gitg/integration_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package git
package main

import (
"bytes"
Expand Down Expand Up @@ -214,7 +214,7 @@ func testStatus(t *testing.T, expected string) {
}

func testRestore(t *testing.T, path string, staged bool) {
if err := Restore(path, staged); err != nil {
if err := g.Restore(path, staged); err != nil {
t.Fatal(err)
}
}
Expand Down
Loading
Loading