Kill git-dolt

This commit is contained in:
Timothy Sehn
2022-08-24 11:09:58 -07:00
parent 8b00bb953d
commit 93c677ea48
26 changed files with 10 additions and 11134 deletions

View File

@@ -78,8 +78,7 @@ jobs:
working-directory: ./go
run: |
go build -mod=readonly -o ../.ci_bin/dolt ./cmd/dolt/.
go build -mod=readonly -o ../.ci_bin/git-dolt ./cmd/git-dolt/.
go build -mod=readonly -o ../.ci_bin/git-dolt-smudge ./cmd/git-dolt-smudge/.
go build -mod=readonly -o ../.ci_bin/remotesrv ./utils/remotesrv/.
go build -mod=readonly -o ../.ci_bin/noms ./store/cmd/noms/.
- name: Setup Dolt Config

View File

@@ -136,8 +136,7 @@ jobs:
working-directory: ./go
run: |
go build -mod=readonly -o ../.ci_bin/dolt ./cmd/dolt/.
go build -mod=readonly -o ../.ci_bin/git-dolt ./cmd/git-dolt/.
go build -mod=readonly -o ../.ci_bin/git-dolt-smudge ./cmd/git-dolt-smudge/.
go build -mod=readonly -o ../.ci_bin/remotesrv ./utils/remotesrv/.
go build -mod=readonly -o ../.ci_bin/noms ./store/cmd/noms/.
- name: Setup Dolt Config

9770
go/Godeps/LICENSES generated

File diff suppressed because it is too large Load Diff

4
go/Godeps/update.sh generated
View File

@@ -5,6 +5,6 @@ set -eo pipefail
script_dir=$(dirname "$0")
cd $script_dir/..
( go list -deps -json ./cmd/dolt/. ./cmd/git-dolt/. ./cmd/git-dolt-smudge/. && \
GOOS=windows go list -deps -json ./cmd/dolt/. ./cmd/git-dolt/. ./cmd/git-dolt-smudge/.) \
( go list -deps -json ./cmd/dolt/. && \
GOOS=windows go list -deps -json ./cmd/dolt/. ) \
| go run ./utils/3pdeps/. > ./Godeps/LICENSES

4
go/Godeps/verify.sh generated
View File

@@ -5,6 +5,6 @@ set -eo pipefail
script_dir=$(dirname "$0")
cd $script_dir/..
( go list -deps -json ./cmd/dolt/. ./cmd/git-dolt/. ./cmd/git-dolt-smudge/. && \
GOOS=windows go list -deps -json ./cmd/dolt/. ./cmd/git-dolt/. ./cmd/git-dolt-smudge/.) \
( go list -deps -json ./cmd/dolt/. && \
GOOS=windows go list -deps -json ./cmd/dolt/. ) \
| go run ./utils/3pdeps/. -verify ./Godeps/LICENSES

View File

@@ -1,59 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"github.com/dolthub/dolt/go/cmd/git-dolt/config"
"github.com/dolthub/dolt/go/cmd/git-dolt/doltops"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
func main() {
// Because this is a git smudge filter, the pointer file contents
// are read through stdin.
r := bufio.NewReader(os.Stdin)
bs, err := io.ReadAll(r)
if err != nil {
log.Fatal(err)
}
// Print the pointer file contents right back to stdout; the smudge filter
// uses this output to replace the contents of the smudged file. In this case,
// no changes to the file are desired (though this may change).
fmt.Printf("%s", bs)
cfg, err := config.Parse(string(bs))
if err != nil {
log.Fatalf("error parsing config: %v", err)
}
dirname := utils.LastSegment(cfg.Remote)
// We send output intended for the console to stderr instead of stdout
// or else it will end up in the pointer file.
fmt.Fprintf(os.Stderr, "Found git-dolt pointer file. Cloning remote %s to revision %s in directory %s...", cfg.Remote, cfg.Revision, dirname)
if err := doltops.CloneToRevisionSilent(cfg.Remote, cfg.Revision); err != nil {
log.Fatalf("error cloning repository: %v", err)
}
fmt.Fprintln(os.Stderr, "done.")
}

View File

@@ -1,187 +0,0 @@
# Git-Dolt
Git-Dolt: It's Git for data...in Git!
## Idea
It should be easy to embed a Dolt repository inside a Git repository, and have
changes tracked and synchronized without leaving Git.
To this end, Git-Dolt creates persistent references to Dolt remotes in the form
of pointer files. This approach is very similar to how [git-lfs](https://git-lfs.github.com/) embeds
large binary files inside of Git repositories.
A Git-Dolt pointer file specifies everything necessary to
reconstruct (clone) the Dolt repository at a given revision:
```
version 0
remote http://dolthub.com/some-org/some-repo
revision eidemcn2rsa5r1kpr5ds7mi0g5h8jt37
```
In the future, we imagine `git-dolt` doing things like automatically proposing
modifications to the pointer file when the cloned Dolt repo is modified. For
now, if you want the pointer file to point to a different commit, you must update
it manually; see the [`update`](#update) command below.
## Example
### Setup
Make sure that `git-dolt` and `git-dolt-smudge` are in your PATH. Then do the steps below in a new directory somewhere:
```
$ git init
Initialized empty Git repository in /Users/mjesuele/dolt/git-dolt-smudge-test/.git/
$ git dolt install
Installed git-dolt smudge filter.
When git-dolt pointer files are checked out in this git repository, the corresponding Dolt repositories will be automatically cloned.
$ git dolt link Liquidata/lunch-places
Dolt repository successfully linked!
* Dolt repository cloned to lunch-places at revision qi331vjgoavqpi5am334cji1gmhlkdv5
* Pointer file created at lunch-places.git-dolt
* lunch-places added to .gitignore
You should git commit these results.
$ git add .
$ git commit -m set up git-dolt integration
[master (root-commit) 82c762e] set up git-dolt integration
3 files changed, 5 insertions(+)
create mode 100644 .gitattributes
create mode 100644 .gitignore
create mode 100644 lunch-places.git-dolt
```
### Testing the smudge filter
```
$ rm -rf lunch-places lunch-places.git-dolt
$ git checkout -- lunch-places.git-dolt
Found git-dolt pointer file. Cloning remote Liquidata/lunch-places to revision qi331vjgoavqpi5am334cji1gmhlkdv5 in directory lunch-places...done.
$ cd lunch-places
$ dolt log -n 3
commit qi331vjgoavqpi5am334cji1gmhlkdv5
Author: bheni <brian@liquidata.co>
Date: Thu Jun 06 17:22:24 -0700 2019
update tocaya rating
commit eidemcn2rsa5r1kpr5ds7mi0g5h8jt37
Merge: 137qgvrsve1u458briekqar5f7iiqq2j ngfah8jf5r9apr7bds87nua9uavnlc1d
Author: Aaron Son <aaron@liquidata.co>
Date: Thu Apr 18 13:04:18 -0700 2019
Merge...
commit 137qgvrsve1u458briekqar5f7iiqq2j
Author: bheni <brian@liquidata.co>
Date: Thu Apr 04 15:43:00 -0700 2019
change rating
```
## Commands
### install
```
git dolt install
```
Initializes a git-dolt integration in the current git repository by:
1. Adding a line in `.gitattributes` declaring the git-dolt smudge filter on `.git-dolt` files.
2. Adding a line in `.git/config` telling git which executable(s) to use for the git-dolt filter.
Once this is done, any time a `.git-dolt` file is checked out in the git repository, the Dolt
repository that it points to will automatically be cloned to the specified revision.
Note that this functionality requires that the `git-dolt-smudge` executable be present in your `PATH`.
See [the chapter in Pro Git on Git Attributes](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes)
for more information about filters.
_Example:_
```
$ git dolt install
Installed git-dolt smudge filter. When git-dolt pointer files are checked out in this git repository, the corresponding Dolt repositories will be automatically cloned.
You should git commit the changes to .gitattributes.
```
### link
```
git dolt link <remote-url>
```
Links a dolt remote to the current git repository by:
1. Cloning the dolt repository in the current directory
2. Adding the dolt repository directory to `.gitignore`
3. Outputting a persistent `.git-dolt` pointer file intended to be committed with git
_Example:_
```
$ git dolt link http://localhost:50051/test-org/test-repo eidemcn2rsa5r1kpr5ds7mi0g5h8jt37
Dolt repository successfully linked!
* Dolt repository cloned to test-repo at revision jdnj4siav9lk8obprgfmsvlae4rvc5jc
* Pointer file created at test-repo.git-dolt
* test-repo added to .gitignore
You should git commit these results.
```
### fetch
```
git dolt fetch <pointer-file>
```
Fetches a dolt repository from the remote and at the revision specified by the given git-dolt pointer file (you may omit the `.git-dolt` suffix when specifying this file).
_Example:_
```
$ git dolt fetch test-repo
Dolt repository cloned from remote http://localhost:50051/test-org/test-repo to directory test-repo at revision 2diug5q1okrdi5rq4f8ct3vea00gblbj
```
#### Note
Currently, dolt lacks detached head support, meaning that you can't check out individual commits. It is also currently not possible to fetch only a specific revision from a remote repository.
Accordingly, the current behavior of `git dolt fetch` is to clone the remote repository and create/check out a new branch called `git-dolt-pinned` which points at the specified commit.
### update
```
git dolt update <pointer-file> <revision>
```
Updates the given git-dolt pointer file to point to the specified revision.
_Example:_
```
$ git dolt update im-interested ppbq8n1difju3u02jf8iqmctd1ovbj76
Updated pointer file im-interested.git-dolt to revision ppbq8n1difju3u02jf8iqmctd1ovbj76. You should git commit this change.
```
## Tests
There are unit tests in Go and CLI tests using [BATS](https://github.com/sstephenson/bats).

View File

@@ -1,17 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package commands contains the command functions executed based on the
// git-dolt subcommand specified on the command line.
package commands

View File

@@ -1,39 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"fmt"
"github.com/dolthub/dolt/go/cmd/git-dolt/config"
"github.com/dolthub/dolt/go/cmd/git-dolt/doltops"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// Fetch takes the filename of a git-dolt pointer file and clones
// the specified dolt repository to the specified revision.
func Fetch(ptrFname string) error {
config, err := config.Load(ptrFname)
if err != nil {
return err
}
if err := doltops.CloneToRevision(config.Remote, config.Revision); err != nil {
return err
}
fmt.Printf("Dolt repository cloned from remote %s to directory %s at revision %s\n", config.Remote, utils.LastSegment(config.Remote), config.Revision)
return nil
}

View File

@@ -1,51 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"fmt"
"os/exec"
"path/filepath"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// Install configures this git repository for use with git-dolt; specifically, it sets up the
// smudge filter that automatically clones dolt repos when git-dolt pointer files are checked out.
func Install() error {
if _, err := exec.LookPath("git-dolt-smudge"); err != nil {
return fmt.Errorf("can't find git-dolt-smudge in PATH")
}
gitPath, err := utils.FindGitConfigUnderRoot()
if err != nil {
return err
}
gitParentPath := filepath.Dir(gitPath)
gitAttributesPath := filepath.Join(gitParentPath, ".gitattributes")
if err := utils.AppendToFile(gitAttributesPath, "*.git-dolt filter=git-dolt"); err != nil {
return err
}
gitConfigPath := filepath.Join(gitPath, "config")
if err := utils.AppendToFile(gitConfigPath, "[filter \"git-dolt\"]\n\tsmudge = git-dolt-smudge"); err != nil {
return err
}
fmt.Println("Installed git-dolt smudge filter. When git-dolt pointer files are checked out in this git repository, the corresponding Dolt repositories will be automatically cloned.")
fmt.Println("\nYou should git commit the changes to .gitattributes.")
return nil
}

View File

@@ -1,54 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"fmt"
"github.com/dolthub/dolt/go/cmd/git-dolt/config"
"github.com/dolthub/dolt/go/cmd/git-dolt/doltops"
"github.com/dolthub/dolt/go/cmd/git-dolt/env"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// Link creates a git-dolt pointer file linking the given dolt remote
// to the current git repository.
func Link(remote string) error {
if err := doltops.Clone(remote); err != nil {
return err
}
dirname := utils.LastSegment(remote)
revision, err := utils.CurrentRevision(dirname)
if err != nil {
return err
}
c := config.GitDoltConfig{Version: env.Version, Remote: remote, Revision: revision}
if err := config.Write(dirname, c.String()); err != nil {
return err
}
if err := utils.AppendToFile(".gitignore", dirname); err != nil {
return err
}
fmt.Printf("\nDolt repository linked!\n\n")
fmt.Printf("* Repository cloned to %s at revision %s\n", dirname, revision)
fmt.Printf("* Pointer file created at %s.git-dolt\n", dirname)
fmt.Printf("* %s added to .gitignore\n\n", dirname)
fmt.Println("You should git commit these results.")
return nil
}

View File

@@ -1,40 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"fmt"
"github.com/dolthub/dolt/go/cmd/git-dolt/config"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// Update updates the git-dolt pointer file at the given filename
// to point to the specified revision.
func Update(ptrFname string, revision string) error {
ptrFname = utils.EnsureSuffix(ptrFname, ".git-dolt")
c, err := config.Load(ptrFname)
if err != nil {
return err
}
c.Revision = revision
if err := config.Write(ptrFname, c.String()); err != nil {
return err
}
fmt.Printf("Updated pointer file %s to revision %s. You should git commit this change.\n", ptrFname, revision)
return nil
}

View File

@@ -1,99 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package config contains types and functions for dealing with
// git-dolt configuration, including config file I/O.
package config
import (
"fmt"
"os"
"strings"
"github.com/dolthub/dolt/go/cmd/git-dolt/env"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// GitDoltConfig represents the configuration for a git-dolt integration.
type GitDoltConfig struct {
// Version is the version of the git-dolt protocol being used.
Version string
// Remote is the url of the dolt remote.
Remote string
// Revision is the revision of the remote that this git-dolt pointer links to.
Revision string
}
// Parse parses a git-dolt config string into a struct.
func Parse(c string) (GitDoltConfig, error) {
lines := strings.Split(c, "\n")
config := make(map[string]string)
for _, line := range lines {
setting := strings.Split(line, " ")
if len(setting) == 2 {
config[setting[0]] = setting[1]
}
}
// default to the current version of git-dolt
if config["version"] == "" {
config["version"] = env.Version
}
requiredProps := []string{"remote", "revision"}
for _, prop := range requiredProps {
if _, ok := config[prop]; !ok {
return GitDoltConfig{}, fmt.Errorf("no %s specified", prop)
}
}
return GitDoltConfig{
Version: config["version"],
Remote: config["remote"],
Revision: config["revision"],
}, nil
}
// Load loads a GitDoltConfig from the pointer file with the given filename.
func Load(ptrFname string) (GitDoltConfig, error) {
ptrFname = utils.EnsureSuffix(ptrFname, ".git-dolt")
ptrData, err := os.ReadFile(ptrFname)
if err != nil {
return GitDoltConfig{}, fmt.Errorf("can't find pointer file %s", ptrFname)
}
config, err := Parse(string(ptrData))
if err != nil {
return GitDoltConfig{}, fmt.Errorf("error parsing config file: %v", err)
}
return config, nil
}
// Write writes to the pointer file with the given filename,
// creating or overwriting it with the given contents.
func Write(ptrFname string, ptrContents string) error {
ptrFname = utils.EnsureSuffix(ptrFname, ".git-dolt")
if err := os.WriteFile(ptrFname, []byte(ptrContents), 0644); err != nil {
return fmt.Errorf("error writing git-dolt pointer file at %s: %v", ptrFname, err)
}
return nil
}
func (c GitDoltConfig) String() string {
return fmt.Sprintf("version %s\nremote %s\nrevision %s\n", c.Version, c.Remote, c.Revision)
}

View File

@@ -1,86 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
const version = "0.0.0"
const remoteURL = "http://localhost:50051/test-org/test-repo"
const revision = "nl5v5qu36e2dfmhnjqiu4crefam52iif"
var testConfig = fmt.Sprintf(`version %s
remote %s
revision %s
`, version, remoteURL, revision)
var noVersionConfig = fmt.Sprintf(`remote %s
revision %s
`, remoteURL, revision)
var noRemoteConfig = fmt.Sprintf(`version %s
revision %s
`, version, revision)
var noRevisionConfig = fmt.Sprintf(`version %s
remote %s
`, version, remoteURL)
var wanted = GitDoltConfig{
Version: version,
Remote: remoteURL,
Revision: revision,
}
func TestParse(t *testing.T) {
type args struct {
c string
}
happyTests := []struct {
name string
args args
want GitDoltConfig
}{
{"parses config", args{testConfig}, wanted},
{"defaults version to current git-dolt version if missing", args{noVersionConfig}, wanted},
}
for _, tt := range happyTests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.args.c)
assert.Nil(t, err)
assert.Equal(t, tt.want, got)
})
}
errorTests := []struct {
name string
args args
want error
}{
{"returns an error if missing remote", args{noRemoteConfig}, errors.New("no remote specified")},
{"returns an error if missing revision", args{noRevisionConfig}, errors.New("no revision specified")},
}
for _, tt := range errorTests {
t.Run(tt.name, func(t *testing.T) {
_, err := Parse(tt.args.c)
assert.Equal(t, tt.want, err)
})
}
}

View File

@@ -1,92 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package doltops contains functions for performing dolt operations
// using the CLI.
package doltops
import (
"bufio"
"fmt"
"os/exec"
"github.com/dolthub/dolt/go/cmd/git-dolt/utils"
)
// Clone clones the specified dolt remote, streaming the output from dolt clone to stdout.
func Clone(remote string) error {
cmd := exec.Command("dolt", "clone", remote)
if err := runAndStreamOutput(cmd, "dolt clone"); err != nil {
return err
}
return nil
}
// CloneToRevision clones the specified dolt remote and checks it out to the specified revision.
// It streams the output from dolt clone and dolt checkout to stdout.
func CloneToRevision(remote string, revision string) error {
if err := Clone(remote); err != nil {
return err
}
dirname := utils.LastSegment(remote)
checkoutCmd := exec.Command("dolt", "checkout", "-b", "git-dolt-pinned", revision)
checkoutCmd.Dir = dirname
if err := runAndStreamOutput(checkoutCmd, "dolt checkout"); err != nil {
return err
}
return nil
}
func runAndStreamOutput(cmd *exec.Cmd, name string) error {
cmdReader, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("error creating StdoutPipe for %s: %v", name, err)
}
scanner := bufio.NewScanner(cmdReader)
go func() {
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}()
if err := cmd.Start(); err != nil {
return fmt.Errorf("error starting %s: %v", name, err)
}
if err := cmd.Wait(); err != nil {
return fmt.Errorf("error waiting for %s: %v", name, err)
}
return nil
}
// CloneToRevisionSilent clones the specified dolt remote and checks it out to the specified revision,
// suppressing all output from dolt clone and dolt checkout.
func CloneToRevisionSilent(remote string, revision string) error {
if err := exec.Command("dolt", "clone", remote).Run(); err != nil {
return fmt.Errorf("error cloning remote repository at %s: %v", remote, err)
}
dirname := utils.LastSegment(remote)
checkoutCmd := exec.Command("dolt", "checkout", "-b", "git-dolt-pinned", revision)
checkoutCmd.Dir = dirname
if err := checkoutCmd.Run(); err != nil {
return fmt.Errorf("error checking out revision %s in directory %s: %v", revision, dirname, err)
}
return nil
}

View File

@@ -1,20 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package env contains information about the environment of the
// currently-running git-dolt client.
package env
// Version is the version of the currently-running git-dolt client.
const Version = "0.0.0"

View File

@@ -1,95 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"log"
"os"
"os/exec"
"path/filepath"
"github.com/spf13/cobra"
"github.com/dolthub/dolt/go/cmd/git-dolt/commands"
)
func main() {
if _, err := exec.LookPath("dolt"); err != nil {
log.Fatal("It looks like Dolt is not installed on your system. Make sure that the `dolt` binary is in your PATH before attempting to run git-dolt commands.")
}
if filepath.Base(os.Args[0]) == "git-dolt" {
os.Args = append([]string{"git", "dolt"}, os.Args[1:]...)
}
fakeGitCmd := &cobra.Command{
Use: "git",
}
rootCmd := &cobra.Command{
Use: "dolt",
Short: "Run a git-dolt subcommand",
Long: `Run a git-dolt subcommand.
Valid subcommands are: fetch, install, link, update.`,
}
fakeGitCmd.AddCommand(rootCmd)
cmdInstall := &cobra.Command{
Use: "install",
Short: "Installs the git-dolt smudge filter for this Git repository",
Long: `Installs the git-dolt smudge filter for this Git repository.
After this, when git-dolt pointer files are checked out in this repository, the corresponding Dolt repositories will automatically be cloned.`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return commands.Install()
},
}
cmdLink := &cobra.Command{
Use: "link <remote-url>",
Short: "Links the given Dolt repository to the current Git repository",
Long: `Links the given Dolt repository to the current Git repository.
The Dolt repository is cloned in the current directory and added to ./.gitignore, and a git-dolt pointer file is created.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return commands.Link(args[0])
},
}
cmdFetch := &cobra.Command{
Use: "fetch <pointer-file>",
Short: "Fetches the Dolt repository referred to in the given git-dolt pointer file",
Long: `Fetches the Dolt repository referred to in the given git-dolt pointer file.
The Dolt repository is cloned to the current directory and checked out to the revision specified in the git-dolt pointer file.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return commands.Fetch(args[0])
},
}
cmdUpdate := &cobra.Command{
Use: "update <pointer-file> <revision>",
Short: "Updates the reference in the given git-dolt pointer file to the given revision",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return commands.Update(args[0], args[1])
},
}
rootCmd.AddCommand(cmdInstall, cmdLink, cmdFetch, cmdUpdate)
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}

View File

@@ -1,36 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"fmt"
"os"
)
// AppendToFile appends the given string to the given file in the current
// directory, creating it if it does not exist.
func AppendToFile(f string, s string) error {
giFile, err := os.OpenFile(f, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("error opening %s: %v", f, err)
}
defer giFile.Close()
if _, err = giFile.WriteString(fmt.Sprintf("%s\n", s)); err != nil {
return fmt.Errorf("error writing to %s at %v", f, err)
}
return nil
}

View File

@@ -1,76 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"fmt"
"os"
"path/filepath"
"strings"
)
// FindGitConfigUnderRoot will recurse upwards from the current working directory
// to the system root looking for a directory named .git, returning its path if found,
// and an error if not.
func FindGitConfigUnderRoot() (string, error) {
currentPath, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("error getting current directory: %v", err)
}
rootPath, err := filepath.Abs("/")
if err != nil {
return "", fmt.Errorf("error getting root directory: %v", err)
}
return FindGitConfigDir(currentPath, rootPath)
}
// FindGitConfigDir will recurse upwards from currentPath to terminalPath looking for
// a directory named .git, returning its path if found, and an error if not.
//
// Both currentPath and terminalPath are assumed to be absolute paths. An error is returned
// if currentPath is not a descendant of terminalPath.
func FindGitConfigDir(currentPath, terminalPath string) (string, error) {
if !strings.HasPrefix(currentPath, terminalPath) {
return "", fmt.Errorf("current path %s is not a descendent of terminal path %s", currentPath, terminalPath)
}
// recursive base case -- currentPath and terminalPath are the same
if currentPath == terminalPath {
return "", fmt.Errorf("recursed upwards to %s but couldn't find a .git directory", currentPath)
}
// check to see if .git exists in currentPath
fileInfo, fileErr := os.Stat(filepath.Join(currentPath, ".git"))
// .git exists and is a directory -- success!
if fileErr == nil && fileInfo.IsDir() {
return filepath.Join(currentPath, ".git"), nil
}
// something went wrong looking for .git other than it not existing -- return an error
if fileErr != nil && !os.IsNotExist(fileErr) {
return "", fmt.Errorf("error looking for the .git directory in %s: %v", currentPath, fileErr)
}
// either .git exists and is not a directory, or .git does not exist:
// go up one directory level and make the recursive call
parentPath := filepath.Dir(currentPath)
if parentPath == "." {
return "", fmt.Errorf("ran out of ancestors at %s but couldn't find a .git directory", currentPath)
}
return FindGitConfigDir(parentPath, terminalPath)
}

View File

@@ -1,90 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"os"
"path/filepath"
"testing"
"github.com/dolthub/dolt/go/libraries/utils/file"
"github.com/stretchr/testify/assert"
)
func TestFindGitConfigDir(t *testing.T) {
// Setup
tmpDir, err := os.MkdirTemp("", "git-dolt-test")
if err != nil {
t.Errorf("Error creating temp directory: %v", err)
}
defer func() {
if err := file.RemoveAll(tmpDir); err != nil {
t.Errorf("Error removing test directories: %v", err)
}
}()
nestedExamplePath := filepath.Join(tmpDir, "deeply", "nested", "example")
topLevelExamplePath := filepath.Join(tmpDir, "top", "level", "example")
noGitExamplePath := filepath.Join(tmpDir, "no", "git", "example")
nestedGitPath := filepath.Join(nestedExamplePath, ".git")
topLevelGitPath := filepath.Join(tmpDir, "top", ".git")
if err := os.MkdirAll(nestedGitPath, os.ModePerm); err != nil {
t.Errorf("Error creating test directories: %v", err)
}
if err := os.MkdirAll(topLevelExamplePath, os.ModePerm); err != nil {
t.Errorf("Error creating test directories: %v", err)
}
if err := os.MkdirAll(topLevelGitPath, os.ModePerm); err != nil {
t.Errorf("Error creating test directories: %v", err)
}
if err := os.MkdirAll(noGitExamplePath, os.ModePerm); err != nil {
t.Errorf("Error creating test directories: %v", err)
}
// Tests
type args struct {
startingPath string
terminalPath string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{"finds a deeply-nested git directory", args{nestedExamplePath, tmpDir}, nestedGitPath, false},
{"finds a top-level git directory", args{topLevelExamplePath, tmpDir}, topLevelGitPath, false},
{"returns an error when there is no git directory", args{noGitExamplePath, tmpDir}, "", true},
{"returns an error (and does not hang) when startingPath is not a descendent of terminalPath", args{noGitExamplePath, nestedExamplePath}, "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FindGitConfigDir(tt.args.startingPath, tt.args.terminalPath)
if tt.wantErr {
assert.Error(t, err)
} else if err != nil {
t.Errorf("wanted %v, got error %v", tt.want, err)
}
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -1,51 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package utils contains utility functions for use throughout git-dolt.
package utils
import (
"fmt"
"os/exec"
"regexp"
"strings"
)
// EnsureSuffix adds a suffix to a string if not already present.
func EnsureSuffix(s string, suffix string) string {
if !strings.HasSuffix(s, suffix) {
return s + suffix
}
return s
}
// LastSegment gets the last segment of a slash-separated string.
func LastSegment(s string) string {
tokens := strings.Split(s, "/")
return tokens[len(tokens)-1]
}
var hashRegex = regexp.MustCompile(`[0-9a-v]{32}`)
// CurrentRevision gets the commit hash of the currently checked-out revision of
// the dolt repo at the given dirname.
func CurrentRevision(dirname string) (string, error) {
cmd := exec.Command("dolt", "log", "-n", "1")
cmd.Dir = dirname
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("error running dolt log to find current revision: %v", err)
}
return hashRegex.FindString(string(out)), nil
}

View File

@@ -1,62 +0,0 @@
// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEnsureSuffix(t *testing.T) {
type args struct {
s string
suffix string
}
tests := []struct {
name string
args args
want string
}{
{"adds a suffix when not present", args{"foo", ".bar"}, "foo.bar"},
{"doesn't add a suffix when already present", args{"foo.bar", ".bar"}, "foo.bar"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := EnsureSuffix(tt.args.s, tt.args.suffix)
assert.Equal(t, tt.want, got)
})
}
}
func TestLastSegment(t *testing.T) {
type args struct {
s string
}
tests := []struct {
name string
args args
want string
}{
{"gets the last segment of a slash-separated string", args{"foo/bar/baz"}, "baz"},
{"gets the name at the end of a path", args{"/Users/foouser/some/path/somewhere"}, "somewhere"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := LastSegment(tt.args.s)
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -14,7 +14,7 @@ set -o pipefail
apt-get update && apt-get install -y zip
cd /src
BINS="dolt git-dolt git-dolt-smudge"
BINS="dolt"
OS_ARCH_TUPLES="windows-amd64 linux-amd64 linux-arm64 darwin-amd64 darwin-arm64"
for tuple in $OS_ARCH_TUPLES; do

View File

@@ -103,9 +103,9 @@ install_binary_release() {
echo "Downloading:" $URL
curl -A "$CURL_USER_AGENT" -fsL "$URL" > "$FILE"
tar zxf "$FILE"
echo "Installing dolt, git-dolt and git-dolt-smudge to /usr/local/bin."
echo "Installing dolt /usr/local/bin."
[ -d /usr/local/bin ] || install -o 0 -g 0 -d /usr/local/bin
install -o 0 -g 0 dolt-$PLATFORM_TUPLE/bin/{dolt,git-dolt,git-dolt-smudge} /usr/local/bin
install -o 0 -g 0 dolt-$PLATFORM_TUPLE/bin/dolt /usr/local/bin
install -o 0 -g 0 -d /usr/local/share/doc/dolt/
install -o 0 -g 0 -m 644 dolt-$PLATFORM_TUPLE/LICENSES /usr/local/share/doc/dolt/
}

View File

@@ -21,11 +21,9 @@ If you find a bug in `dolt`, we would love a skipped bats test PR in addition to
```
npm install -g bats
```
2. Install `dolt`, `git-dolt`, `git-dolt-smudge`, and `noms`
2. Install `dolt` and `noms`
```
cd go/cmd/dolt && go install . && cd -
cd go/cmd/git-dolt && go install . && cd -
cd go/cmd/git-dolt-smudge && go install . && cd -
cd go/store/cmd/noms && go install . && cd -
````
3. Go to the directory with the bats tests and run:

View File

@@ -1,196 +0,0 @@
#!/usr/bin/env bats
load $BATS_TEST_DIRNAME/helper/common.bash
REMOTE=http://localhost:50051/test-org/test-repo
remotesrv_pid=
setup() {
skiponwindows "tests are flaky on Windows"
setup_common
cd $BATS_TMPDIR
mkdir remotes-$$
echo remotesrv log available here $BATS_TMPDIR/remotes-$$/remotesrv.log
remotesrv --http-port 1234 --dir ./remotes-$$ &> ./remotes-$$/remotesrv.log 3>&- &
remotesrv_pid=$!
cd dolt-repo-$$
dolt remote add test-remote $REMOTE
dolt push test-remote main
export DOLT_HEAD_COMMIT=`get_head_commit`
}
teardown() {
teardown_common
rm -rf $BATS_TMPDIR/git-repo-$$
kill $remotesrv_pid
rm -rf $BATS_TMPDIR/remotes-$$
}
@test "git-dolt: install sets up a smudge filter in the current git repository" {
init_git_repo
run git dolt install
[ "$status" -eq 0 ]
[[ "${lines[0]}" =~ "Installed git-dolt smudge filter" ]] || false
[[ "${lines[1]}" =~ "commit the changes to .gitattributes" ]] || false
run cat .gitattributes
[ "${lines[0]}" = "*.git-dolt filter=git-dolt" ]
run cat .git/config
len=${#lines[@]}
[ "${lines[len-2]}" = "[filter \"git-dolt\"]" ]
[[ "${lines[len-1]}" =~ "smudge = git-dolt-smudge" ]] || false
}
@test "git-dolt: install works in subdirectories of the git repository" {
init_git_repo
mkdir -p deeply/nested/directory
pushd deeply/nested/directory
run git dolt install
[ "$status" -eq 0 ]
popd
run cat .gitattributes
[ "${lines[0]}" = "*.git-dolt filter=git-dolt" ]
run cat .git/config
len=${#lines[@]}
[ "${lines[len-2]}" = "[filter \"git-dolt\"]" ]
[[ "${lines[len-1]}" =~ "smudge = git-dolt-smudge" ]] || false
}
@test "git-dolt: install fails with a helpful error when executed outside of a git repo" {
run git dolt install
[ "$status" -eq 1 ]
[[ "$output" =~ "couldn't find a .git directory" ]] || false
}
@test "git-dolt: link takes a remote url (and an optional revspec and destination directory), clones the repo, and outputs a pointer file" {
init_git_repo
run git dolt link $REMOTE
[ "$status" -eq 0 ]
# Ensure it reports the resolved revision
[[ "$output" =~ "revision $DOLT_HEAD_COMMIT" ]] || false
# Ensure it reports the pointer filename
[[ "$output" =~ "test-repo.git-dolt" ]] || false
# Ensure it reports the addition to .gitignore
[[ "$output" =~ "test-repo added to .gitignore" ]] || false
[ -d test-repo ]
run cat test-repo.git-dolt
[[ "${lines[0]}" =~ ^version\ [0-9]+\.[0-9]+\.[0-9]+$ ]] || false
[ "${lines[1]}" = "remote $REMOTE" ]
[ "${lines[2]}" = "revision $DOLT_HEAD_COMMIT" ]
run cat .gitignore
[[ "${lines[0]}" =~ "test-repo" ]] || false
}
@test "git-dolt: smudge filter automatically clones dolt repositories referenced in checked out git-dolt pointer files" {
init_git_repo
git dolt install
git dolt link $REMOTE
git add .
git commit -m "set up git-dolt integration"
rm -rf test-repo test-repo.git-dolt
run git checkout -- test-repo.git-dolt
[[ "$output" =~ "Found git-dolt pointer file" ]] || false
[[ "$output" =~ "Cloning remote $REMOTE" ]] || false
[ -d test-repo ]
cd test-repo
[ `get_head_commit` = "$DOLT_HEAD_COMMIT" ]
}
@test "git-dolt: fetch takes the name of a git-dolt pointer file and clones the repo to the specified revision if it doesn't exist" {
init_git_repo
create_test_pointer
run git dolt fetch test-repo
[ "$status" -eq 0 ]
[[ "$output" =~ "Dolt repository cloned from remote $REMOTE to directory test-repo at revision $DOLT_HEAD_COMMIT" ]] || false
[ -d test-repo ]
cd test-repo
[ `get_head_commit` = "$DOLT_HEAD_COMMIT" ]
}
@test "git-dolt: update updates the specified pointer file to the specified revision" {
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL COMMENT 'tag:0',
c1 BIGINT COMMENT 'tag:1',
c2 BIGINT COMMENT 'tag:2',
c3 BIGINT COMMENT 'tag:3',
c4 BIGINT COMMENT 'tag:4',
c5 BIGINT COMMENT 'tag:5',
PRIMARY KEY (pk)
);
SQL
dolt add test
dolt commit -m "test commit"
export NEW_DOLT_HEAD_COMMIT=`get_head_commit`
init_git_repo
create_test_pointer
run git dolt update test-repo $NEW_DOLT_HEAD_COMMIT
[ "$status" -eq 0 ]
[ "${lines[0]}" = "Updated pointer file test-repo.git-dolt to revision $NEW_DOLT_HEAD_COMMIT. You should git commit this change." ]
run cat test-repo.git-dolt
[[ "${lines[0]}" =~ ^version\ [0-9]+\.[0-9]+\.[0-9]+$ ]] || false
[ "${lines[1]}" = "remote $REMOTE" ]
[ "${lines[2]}" = "revision $NEW_DOLT_HEAD_COMMIT" ]
}
@test "git-dolt: fails helpfully when dolt is not installed" {
mkdir TMP_PATH
pushd TMP_PATH
cp `which git` ./git
cp `which git-dolt` ./git-dolt
if [ $IS_WINDOWS = true ]; then
ORIGINAL_PATH=$PATH
export PATH=""
export WSLENV=PATH
run git dolt
export PATH=$ORIGINAL_PATH
else
PATH=`pwd` run git dolt
fi
popd
rm -rf TMP_PATH
[ "$status" -eq 1 ]
[[ "$output" =~ "It looks like Dolt is not installed on your system" ]] || false
}
@test "git-dolt: shows usage on unknown commands" {
run git dolt nonsense
[[ "$output" =~ Usage ]] || false
}
@test "git-dolt: prints usage information with no arguments" {
run git dolt
[[ "$output" =~ Usage ]] || false
}
init_git_repo() {
mkdir ../git-repo-$$
cd ../git-repo-$$
git init
git config user.email "foo@bar.com"
git config user.name "Foo User"
}
create_test_pointer() {
cat <<EOF > test-repo.git-dolt
version 0.0.0
remote $REMOTE
revision $DOLT_HEAD_COMMIT
EOF
}
get_head_commit() {
dolt log -n 1 | grep -m 1 commit | cut -c 13-44
}