github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/env/actions/workspace.go (about)

     1  // Copyright 2020 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package actions
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  
    21  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    22  	"github.com/dolthub/dolt/go/libraries/doltcore/env"
    23  	"github.com/dolthub/dolt/go/libraries/doltcore/ref"
    24  )
    25  
    26  var ErrUnmergedWorkspaceDelete = errors.New("attempted to delete a workspace that is not fully merged into its parent; use `-f` to force")
    27  var ErrCOWorkspaceDelete = errors.New("attempted to delete checked out workspace")
    28  var ErrBranchNameExists = errors.New("workspace name must not be existing branch name")
    29  
    30  func CreateWorkspace(ctx context.Context, dEnv *env.DoltEnv, name, startPoint string) error {
    31  	headRef, err := dEnv.RepoStateReader().CWBHeadRef()
    32  	if err != nil {
    33  		return nil
    34  	}
    35  	return CreateWorkspaceOnDB(ctx, dEnv.DoltDB, name, startPoint, headRef)
    36  }
    37  
    38  func CreateWorkspaceOnDB(ctx context.Context, ddb *doltdb.DoltDB, name, startPoint string, headRef ref.DoltRef) error {
    39  	isBranch, err := IsBranchOnDB(ctx, ddb, name)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	if isBranch {
    44  		return ErrBranchNameExists
    45  	}
    46  
    47  	if !doltdb.IsValidUserBranchName(name) {
    48  		return doltdb.ErrInvWorkspaceName
    49  	}
    50  
    51  	workRef := ref.NewWorkspaceRef(name)
    52  
    53  	hasRef, err := ddb.HasRef(ctx, workRef)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	if hasRef {
    58  		return ErrAlreadyExists
    59  	}
    60  
    61  	cs, err := doltdb.NewCommitSpec(startPoint)
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	optCmt, err := ddb.Resolve(ctx, cs, headRef)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	cm, ok := optCmt.ToCommit()
    71  	if !ok {
    72  		return doltdb.ErrGhostCommitEncountered
    73  	}
    74  
    75  	return ddb.NewWorkspaceAtCommit(ctx, workRef, cm)
    76  }
    77  
    78  func IsWorkspaceOnDB(ctx context.Context, ddb *doltdb.DoltDB, str string) (bool, error) {
    79  	dref := ref.NewWorkspaceRef(str)
    80  	return ddb.HasRef(ctx, dref)
    81  }
    82  
    83  func IsWorkspace(ctx context.Context, dEnv *env.DoltEnv, str string) (bool, error) {
    84  	return IsWorkspaceOnDB(ctx, dEnv.DoltDB, str)
    85  }
    86  
    87  func DeleteWorkspace(ctx context.Context, dEnv *env.DoltEnv, workspaceName string, opts DeleteOptions) error {
    88  	var dref ref.DoltRef
    89  	if opts.Remote {
    90  		var err error
    91  		dref, err = ref.NewRemoteRefFromPathStr(workspaceName)
    92  		if err != nil {
    93  			return err
    94  		}
    95  	} else {
    96  		dref = ref.NewWorkspaceRef(workspaceName)
    97  		headRef, err := dEnv.RepoStateReader().CWBHeadRef()
    98  		if err != nil {
    99  			return err
   100  		}
   101  		if ref.Equals(headRef, dref) {
   102  			return ErrCOWorkspaceDelete
   103  		}
   104  	}
   105  
   106  	return DeleteWorkspaceOnDB(ctx, dEnv, dref, opts)
   107  }
   108  
   109  func DeleteWorkspaceOnDB(ctx context.Context, dEnv *env.DoltEnv, dref ref.DoltRef, opts DeleteOptions) error {
   110  	ddb := dEnv.DoltDB
   111  	hasRef, err := ddb.HasRef(ctx, dref)
   112  
   113  	if err != nil {
   114  		return err
   115  	} else if !hasRef {
   116  		return doltdb.ErrWorkspaceNotFound
   117  	}
   118  
   119  	if !opts.Force && !opts.Remote {
   120  		ms, err := doltdb.NewCommitSpec(env.GetDefaultInitBranch(dEnv.Config))
   121  		if err != nil {
   122  			return err
   123  		}
   124  
   125  		optCmt, err := ddb.Resolve(ctx, ms, nil)
   126  		if err != nil {
   127  			return err
   128  		}
   129  		m, ok := optCmt.ToCommit()
   130  		if !ok {
   131  			return doltdb.ErrGhostCommitEncountered
   132  		}
   133  
   134  		cs, err := doltdb.NewCommitSpec(dref.String())
   135  		if err != nil {
   136  			return err
   137  		}
   138  
   139  		optCmt, err = ddb.Resolve(ctx, cs, nil)
   140  		if err != nil {
   141  			return err
   142  		}
   143  		cm, ok := optCmt.ToCommit()
   144  		if !ok {
   145  			return doltdb.ErrGhostCommitEncountered
   146  		}
   147  
   148  		isMerged, _ := m.CanFastReverseTo(ctx, cm)
   149  		if err != nil && err != doltdb.ErrUpToDate {
   150  			return err
   151  		}
   152  		if !isMerged {
   153  			return ErrUnmergedWorkspaceDelete
   154  		}
   155  	}
   156  
   157  	return ddb.DeleteWorkspace(ctx, dref)
   158  }