36b0664fe0
To prepare for the upcoming release of Git LFS v1.3, the `git-lfs lock` and `git-lfs locks` commands are now hidden behind a enviornment variable `GITLFSLOCKSENABLED`. Since most (all?) implementations of LFS do not yet support this new locking API, it makes sense to allow users to experiment with the command while at the same time, not making it a "full" part of the release. If users wish to run any `git-lfs lock{,s}` command, they may do so according to the following: ``` $ GITLFSLOCKSEANBLED=1 git lfs lock <flags> [args] $ GITLFSLOCKSEANBLED=1 git lfs locks <flags> [args] ``` This commit, when applied, adds two new things: 1. The `isCommandEnabled(cmd string) bool` func in the commands package. This new func checks the OS's enviornment variables and determines whether or not a command is "enabled". 2. Updates the `lock` and `locks` tests to use the GITLFSLOCKSENABLED=1 flag such that they are able to run. Since the `isCommandEnabled` func defaults to "false", it should only guard commands which are deemed "experimental", as noted in the godoc.
116 lines
2.5 KiB
Go
116 lines
2.5 KiB
Go
package commands
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/github/git-lfs/api"
|
|
"github.com/github/git-lfs/config"
|
|
"github.com/github/git-lfs/git"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
lockRemote string
|
|
lockRemoteHelp = "specify which remote to use when interacting with locks"
|
|
|
|
// TODO(taylor): consider making this (and the above flag) a property of
|
|
// some parent-command, or another similarly less ugly way of handling
|
|
// this
|
|
setLockRemoteFor = func(c *config.Configuration) {
|
|
c.CurrentRemote = lockRemote
|
|
}
|
|
|
|
lockCmd = &cobra.Command{
|
|
Use: "lock",
|
|
Run: lockCommand,
|
|
}
|
|
)
|
|
|
|
func lockCommand(cmd *cobra.Command, args []string) {
|
|
setLockRemoteFor(config.Config)
|
|
|
|
if len(args) == 0 {
|
|
Print("Usage: git lfs lock <path>")
|
|
return
|
|
}
|
|
|
|
latest, err := git.CurrentRemoteRef()
|
|
if err != nil {
|
|
Error(err.Error())
|
|
Exit("Unable to determine lastest remote ref for branch.")
|
|
}
|
|
|
|
path, err := lockPath(args[0])
|
|
if err != nil {
|
|
Exit(err.Error())
|
|
}
|
|
|
|
s, resp := API.Locks.Lock(&api.LockRequest{
|
|
Path: path,
|
|
Committer: api.CurrentCommitter(),
|
|
LatestRemoteCommit: latest.Sha,
|
|
})
|
|
|
|
if _, err := API.Do(s); err != nil {
|
|
Error(err.Error())
|
|
Exit("Error communicating with LFS API.")
|
|
}
|
|
|
|
if len(resp.Err) > 0 {
|
|
Error(resp.Err)
|
|
Exit("Server unable to create lock.")
|
|
}
|
|
|
|
Print("\n'%s' was locked (%s)", args[0], resp.Lock.Id)
|
|
}
|
|
|
|
// lockPaths relativizes the given filepath such that it is relative to the root
|
|
// path of the repository it is contained within, taking into account the
|
|
// working directory of the caller.
|
|
//
|
|
// If the root directory, working directory, or file cannot be
|
|
// determined/opened, an error will be returned. If the file in question is
|
|
// actually a directory, an error will be returned. Otherwise, the cleaned path
|
|
// will be returned.
|
|
//
|
|
// For example:
|
|
// - Working directory: /code/foo/bar/
|
|
// - Repository root: /code/foo/
|
|
// - File to lock: ./baz
|
|
// - Resolved path bar/baz
|
|
func lockPath(file string) (string, error) {
|
|
repo, err := git.RootDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
abs := filepath.Join(wd, file)
|
|
path := strings.TrimPrefix(abs, repo)
|
|
|
|
if stat, err := os.Stat(abs); err != nil {
|
|
return "", err
|
|
} else {
|
|
if stat.IsDir() {
|
|
return "", fmt.Errorf("lfs: cannot lock directory: %s", file)
|
|
}
|
|
|
|
return path[1:], nil
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
lockCmd.Flags().StringVarP(&lockRemote, "remote", "r", config.Config.CurrentRemote, lockRemoteHelp)
|
|
|
|
if isCommandEnabled("locks") {
|
|
RootCmd.AddCommand(lockCmd)
|
|
}
|
|
}
|