mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-05 10:31:30 -06:00
Merge pull request #1272 from dolthub/taylor/workspace-refs
Create, list, delete workspace refs [no-release-notes]
This commit is contained in:
@@ -929,6 +929,33 @@ func (ddb *DoltDB) DeleteTag(ctx context.Context, tag ref.DoltRef) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// NewWorkspaceAtCommit create a new workspace at the commit given.
|
||||
func (ddb *DoltDB) NewWorkspaceAtCommit(ctx context.Context, workRef ref.DoltRef, c *Commit) error {
|
||||
ds, err := ddb.db.GetDataset(ctx, workRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := types.NewRef(c.commitSt, ddb.Format())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ds, err = ddb.db.SetHead(ctx, ds, r)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (ddb *DoltDB) DeleteWorkspace(ctx context.Context, workRef ref.DoltRef) error {
|
||||
err := ddb.deleteRef(ctx, workRef)
|
||||
|
||||
if err == ErrBranchNotFound {
|
||||
return ErrWorkspaceNotFound
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GC performs garbage collection on this ddb. Values passed in |uncommitedVals| will be temporarily saved during gc.
|
||||
func (ddb *DoltDB) GC(ctx context.Context, uncommitedVals ...hash.Hash) error {
|
||||
collector, ok := ddb.db.(datas.GarbageCollector)
|
||||
|
||||
@@ -308,12 +308,12 @@ func TestLDNoms(t *testing.T) {
|
||||
ddb, _ := LoadDoltDB(context.Background(), types.Format_7_18, LocalDirDoltDB)
|
||||
meta, err := NewCommitMeta(committerName, committerEmail, "Sample data")
|
||||
if err != nil {
|
||||
t.Error("Failled to commit")
|
||||
t.Error("Failed to commit")
|
||||
}
|
||||
|
||||
commit, err := ddb.Commit(context.Background(), valHash, ref.NewBranchRef("master"), meta)
|
||||
if err != nil {
|
||||
t.Error("Failled to commit")
|
||||
t.Error("Failed to commit")
|
||||
}
|
||||
|
||||
numParents, err := commit.NumParents()
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
)
|
||||
|
||||
var ErrInvBranchName = errors.New("not a valid user branch name")
|
||||
var ErrInvWorkspaceName = errors.New("not a valid user workspace name")
|
||||
var ErrInvTagName = errors.New("not a valid user tag name")
|
||||
var ErrInvTableName = errors.New("not a valid table name")
|
||||
var ErrInvHash = errors.New("not a valid hash")
|
||||
@@ -32,9 +33,11 @@ var ErrFoundHashNotACommit = errors.New("the value retrieved for this hash is no
|
||||
var ErrHashNotFound = errors.New("could not find a value for this hash")
|
||||
var ErrBranchNotFound = errors.New("branch not found")
|
||||
var ErrTagNotFound = errors.New("tag not found")
|
||||
var ErrWorkspaceNotFound = errors.New("workspace not found")
|
||||
var ErrTableNotFound = errors.New("table not found")
|
||||
var ErrTableExists = errors.New("table already exists")
|
||||
var ErrAlreadyOnBranch = errors.New("Already on branch")
|
||||
var ErrAlreadyOnWorkspace = errors.New("Already on workspace")
|
||||
|
||||
var ErrNomsIO = errors.New("error reading from or writing to noms")
|
||||
|
||||
|
||||
18
go/libraries/doltcore/env/actions/branch.go
vendored
18
go/libraries/doltcore/env/actions/branch.go
vendored
@@ -155,10 +155,10 @@ func DeleteBranchOnDB(ctx context.Context, ddb *doltdb.DoltDB, dref ref.DoltRef,
|
||||
return ddb.DeleteBranch(ctx, dref)
|
||||
}
|
||||
|
||||
func CreateBranch(ctx context.Context, dEnv *env.DoltEnv, newBranch, startingPoint string, force bool) error {
|
||||
func CreateBranchOnDB(ctx context.Context, ddb *doltdb.DoltDB, newBranch, startingPoint string, force bool, headRef ref.DoltRef) error {
|
||||
newRef := ref.NewBranchRef(newBranch)
|
||||
|
||||
hasRef, err := dEnv.DoltDB.HasRef(ctx, newRef)
|
||||
hasRef, err := ddb.HasRef(ctx, newRef)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -178,13 +178,17 @@ func CreateBranch(ctx context.Context, dEnv *env.DoltEnv, newBranch, startingPoi
|
||||
return err
|
||||
}
|
||||
|
||||
cm, err := dEnv.DoltDB.Resolve(ctx, cs, dEnv.RepoState.CWBHeadRef())
|
||||
cm, err := ddb.Resolve(ctx, cs, headRef)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dEnv.DoltDB.NewBranchAtCommit(ctx, newRef, cm)
|
||||
return ddb.NewBranchAtCommit(ctx, newRef, cm)
|
||||
}
|
||||
|
||||
func CreateBranch(ctx context.Context, dEnv *env.DoltEnv, newBranch, startingPoint string, force bool) error {
|
||||
return CreateBranchOnDB(ctx, dEnv.DoltDB, newBranch, startingPoint, force, dEnv.RepoState.CWBHeadRef())
|
||||
}
|
||||
|
||||
func CheckoutBranch(ctx context.Context, dEnv *env.DoltEnv, brName string) error {
|
||||
@@ -393,8 +397,12 @@ func RootsWithTable(ctx context.Context, dEnv *env.DoltEnv, table string) (RootT
|
||||
}
|
||||
|
||||
func IsBranch(ctx context.Context, dEnv *env.DoltEnv, str string) (bool, error) {
|
||||
return IsBranchOnDB(ctx, dEnv.DoltDB, str)
|
||||
}
|
||||
|
||||
func IsBranchOnDB(ctx context.Context, ddb *doltdb.DoltDB, str string) (bool, error) {
|
||||
dref := ref.NewBranchRef(str)
|
||||
return dEnv.DoltDB.HasRef(ctx, dref)
|
||||
return ddb.HasRef(ctx, dref)
|
||||
}
|
||||
|
||||
func MaybeGetCommit(ctx context.Context, dEnv *env.DoltEnv, str string) (*doltdb.Commit, error) {
|
||||
|
||||
137
go/libraries/doltcore/env/actions/workspace.go
vendored
Normal file
137
go/libraries/doltcore/env/actions/workspace.go
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2020 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 actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
|
||||
)
|
||||
|
||||
var ErrUnmergedWorkspaceDelete = errors.New("attempted to delete a workspace that is not fully merged into master; use `-f` to force")
|
||||
var ErrCOWorkspaceDelete = errors.New("attempted to delete checked out workspace")
|
||||
var ErrBranchNameExists = errors.New("workspace name must not be existing branch name")
|
||||
|
||||
func CreateWorkspace(ctx context.Context, dEnv *env.DoltEnv, name, startPoint string) error {
|
||||
return CreateWorkspaceOnDB(ctx, dEnv.DoltDB, name, startPoint, dEnv.RepoState.CWBHeadRef())
|
||||
}
|
||||
|
||||
func CreateWorkspaceOnDB(ctx context.Context, ddb *doltdb.DoltDB, name, startPoint string, headRef ref.DoltRef) error {
|
||||
isBranch, err := IsBranchOnDB(ctx, ddb, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isBranch {
|
||||
return ErrBranchNameExists
|
||||
}
|
||||
|
||||
if !doltdb.IsValidUserBranchName(name) {
|
||||
return doltdb.ErrInvWorkspaceName
|
||||
}
|
||||
|
||||
workRef := ref.NewWorkspaceRef(name)
|
||||
|
||||
hasRef, err := ddb.HasRef(ctx, workRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if hasRef {
|
||||
return ErrAlreadyExists
|
||||
}
|
||||
|
||||
cs, err := doltdb.NewCommitSpec(startPoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cm, err := ddb.Resolve(ctx, cs, headRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ddb.NewWorkspaceAtCommit(ctx, workRef, cm)
|
||||
}
|
||||
|
||||
func IsWorkspaceOnDB(ctx context.Context, ddb *doltdb.DoltDB, str string) (bool, error) {
|
||||
dref := ref.NewWorkspaceRef(str)
|
||||
return ddb.HasRef(ctx, dref)
|
||||
}
|
||||
|
||||
func IsWorkspace(ctx context.Context, dEnv *env.DoltEnv, str string) (bool, error) {
|
||||
return IsWorkspaceOnDB(ctx, dEnv.DoltDB, str)
|
||||
}
|
||||
|
||||
func DeleteWorkspace(ctx context.Context, dEnv *env.DoltEnv, workspaceName string, opts DeleteOptions) error {
|
||||
var dref ref.DoltRef
|
||||
if opts.Remote {
|
||||
var err error
|
||||
dref, err = ref.NewRemoteRefFromPathStr(workspaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
dref = ref.NewWorkspaceRef(workspaceName)
|
||||
if ref.Equals(dEnv.RepoState.CWBHeadRef(), dref) {
|
||||
return ErrCOWorkspaceDelete
|
||||
}
|
||||
}
|
||||
|
||||
return DeleteWorkspaceOnDB(ctx, dEnv.DoltDB, dref, opts)
|
||||
}
|
||||
|
||||
func DeleteWorkspaceOnDB(ctx context.Context, ddb *doltdb.DoltDB, dref ref.DoltRef, opts DeleteOptions) error {
|
||||
hasRef, err := ddb.HasRef(ctx, dref)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !hasRef {
|
||||
return doltdb.ErrWorkspaceNotFound
|
||||
}
|
||||
|
||||
if !opts.Force && !opts.Remote {
|
||||
ms, err := doltdb.NewCommitSpec("master")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
master, err := ddb.Resolve(ctx, ms, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs, err := doltdb.NewCommitSpec(dref.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cm, err := ddb.Resolve(ctx, cs, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isMerged, _ := master.CanFastReverseTo(ctx, cm)
|
||||
if err != nil && err != doltdb.ErrUpToDate {
|
||||
return err
|
||||
}
|
||||
if !isMerged {
|
||||
return ErrUnmergedWorkspaceDelete
|
||||
}
|
||||
}
|
||||
|
||||
return ddb.DeleteWorkspace(ctx, dref)
|
||||
}
|
||||
@@ -48,11 +48,14 @@ const (
|
||||
|
||||
// TagRefType is a reference to commit tag
|
||||
TagRefType RefType = "tags"
|
||||
|
||||
// WorkspaceRefType is a reference to a workspace
|
||||
WorkspaceRefType RefType = "workspaces"
|
||||
)
|
||||
|
||||
// RefTypes is the set of all supported reference types. External RefTypes can be added to this map in order to add
|
||||
// RefTypes for external tooling
|
||||
var RefTypes = map[RefType]struct{}{BranchRefType: {}, RemoteRefType: {}, InternalRefType: {}, TagRefType: {}}
|
||||
var RefTypes = map[RefType]struct{}{BranchRefType: {}, RemoteRefType: {}, InternalRefType: {}, TagRefType: {}, WorkspaceRefType: {}}
|
||||
|
||||
// PrefixForType returns what a reference string for a given type should start with
|
||||
func PrefixForType(refType RefType) string {
|
||||
@@ -143,6 +146,8 @@ func Parse(str string) (DoltRef, error) {
|
||||
return NewInternalRef(str), nil
|
||||
case TagRefType:
|
||||
return NewTagRef(str), nil
|
||||
case WorkspaceRefType:
|
||||
return NewWorkspaceRef(str), nil
|
||||
default:
|
||||
panic("unknown type " + rType)
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ func TestJsonMarshalAndUnmarshal(t *testing.T) {
|
||||
NewInternalRef("create"),
|
||||
`{"test":"refs/internal/create"}`,
|
||||
},
|
||||
{
|
||||
NewWorkspaceRef("newworkspace"),
|
||||
`{"test":"refs/workspaces/newworkspace"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -134,6 +138,26 @@ func TestEqualsStr(t *testing.T) {
|
||||
"refs/internal/create",
|
||||
true,
|
||||
},
|
||||
{
|
||||
NewWorkspaceRef("newworkspace"),
|
||||
"refs/workspaces/newworkspace",
|
||||
true,
|
||||
},
|
||||
{
|
||||
NewWorkspaceRef("refs/workspaces/newworkspace"),
|
||||
"refs/workspaces/newworkspace",
|
||||
true,
|
||||
},
|
||||
{
|
||||
NewWorkspaceRef("newworkspace"),
|
||||
"refs/workspaces/notnewworkspace",
|
||||
false,
|
||||
},
|
||||
{
|
||||
NewWorkspaceRef("newworkspace"),
|
||||
"refs/remotes/origin/newworkspace",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
59
go/libraries/doltcore/ref/workspace_ref.go
Normal file
59
go/libraries/doltcore/ref/workspace_ref.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 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 ref
|
||||
|
||||
import "strings"
|
||||
|
||||
type WorkspaceRef struct {
|
||||
workspace string
|
||||
}
|
||||
|
||||
var _ DoltRef = WorkspaceRef{}
|
||||
|
||||
// NewWorkspaceRef creates a reference to a local workspace from a workspace
|
||||
// name or a workspace ref e.g. my-workspace, or refs/workspace/my-workspace
|
||||
func NewWorkspaceRef(workspace string) WorkspaceRef {
|
||||
if IsRef(workspace) {
|
||||
prefix := PrefixForType(WorkspaceRefType)
|
||||
if strings.HasPrefix(workspace, prefix) {
|
||||
workspace = workspace[len(prefix):]
|
||||
} else {
|
||||
panic(workspace + " is a ref that is not of type " + prefix)
|
||||
}
|
||||
}
|
||||
|
||||
return WorkspaceRef{workspace}
|
||||
}
|
||||
|
||||
// GetType will return WorkspaceRefType
|
||||
func (br WorkspaceRef) GetType() RefType {
|
||||
return WorkspaceRefType
|
||||
}
|
||||
|
||||
// GetPath returns the name of the workspace
|
||||
func (br WorkspaceRef) GetPath() string {
|
||||
return br.workspace
|
||||
}
|
||||
|
||||
// String returns the fully qualified reference name e.g.
|
||||
// refs/workspace/my-workspace
|
||||
func (br WorkspaceRef) String() string {
|
||||
return String(br)
|
||||
}
|
||||
|
||||
// MarshalJSON serializes a WorkspaceRef to JSON.
|
||||
func (br WorkspaceRef) MarshalJSON() ([]byte, error) {
|
||||
return MarshalJSON(br)
|
||||
}
|
||||
Reference in New Issue
Block a user