github.com/git-lfs/git-lfs@v2.5.2+incompatible/commands/command_lock.go (about)

     1  package commands
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/git-lfs/git-lfs/errors"
    11  	"github.com/git-lfs/git-lfs/git"
    12  	"github.com/spf13/cobra"
    13  )
    14  
    15  var (
    16  	lockRemote     string
    17  	lockRemoteHelp = "specify which remote to use when interacting with locks"
    18  )
    19  
    20  func lockCommand(cmd *cobra.Command, args []string) {
    21  	if len(args) == 0 {
    22  		Print("Usage: git lfs lock <path>")
    23  		return
    24  	}
    25  
    26  	path, err := lockPath(args[0])
    27  	if err != nil {
    28  		Exit(err.Error())
    29  	}
    30  
    31  	if len(lockRemote) > 0 {
    32  		cfg.SetRemote(lockRemote)
    33  	}
    34  
    35  	refUpdate := git.NewRefUpdate(cfg.Git, cfg.PushRemote(), cfg.CurrentRef(), nil)
    36  	lockClient := newLockClient()
    37  	lockClient.RemoteRef = refUpdate.Right()
    38  	defer lockClient.Close()
    39  
    40  	lock, err := lockClient.LockFile(path)
    41  	if err != nil {
    42  		Exit("Lock failed: %v", errors.Cause(err))
    43  	}
    44  
    45  	if locksCmdFlags.JSON {
    46  		if err := json.NewEncoder(os.Stdout).Encode(lock); err != nil {
    47  			Error(err.Error())
    48  		}
    49  		return
    50  	}
    51  
    52  	Print("Locked %s", path)
    53  }
    54  
    55  // lockPaths relativizes the given filepath such that it is relative to the root
    56  // path of the repository it is contained within, taking into account the
    57  // working directory of the caller.
    58  //
    59  // lockPaths also respects different filesystem directory separators, so that a
    60  // Windows path of "\foo\bar" will be normalized to "foo/bar".
    61  //
    62  // If the root directory, working directory, or file cannot be
    63  // determined/opened, an error will be returned. If the file in question is
    64  // actually a directory, an error will be returned. Otherwise, the cleaned path
    65  // will be returned.
    66  //
    67  // For example:
    68  //     - Working directory: /code/foo/bar/
    69  //     - Repository root: /code/foo/
    70  //     - File to lock: ./baz
    71  //     - Resolved path bar/baz
    72  func lockPath(file string) (string, error) {
    73  	repo, err := git.RootDir()
    74  	if err != nil {
    75  		return "", err
    76  	}
    77  
    78  	wd, err := os.Getwd()
    79  	if err != nil {
    80  		return "", err
    81  	}
    82  	wd, err = filepath.EvalSymlinks(wd)
    83  	if err != nil {
    84  		return "", errors.Wrapf(err,
    85  			"could not follow symlinks for %s", wd)
    86  	}
    87  
    88  	abs := filepath.Join(wd, file)
    89  	path := strings.TrimPrefix(abs, repo)
    90  	path = strings.TrimPrefix(path, string(os.PathSeparator))
    91  	if stat, err := os.Stat(abs); err != nil {
    92  		return "", err
    93  	} else {
    94  		if stat.IsDir() {
    95  			return path, fmt.Errorf("lfs: cannot lock directory: %s", file)
    96  		}
    97  
    98  		return filepath.ToSlash(path), nil
    99  	}
   100  }
   101  
   102  func init() {
   103  	RegisterCommand("lock", lockCommand, func(cmd *cobra.Command) {
   104  		cmd.Flags().StringVarP(&lockRemote, "remote", "r", "", lockRemoteHelp)
   105  		cmd.Flags().BoolVarP(&locksCmdFlags.JSON, "json", "", false, "print output in json")
   106  	})
   107  }