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

     1  package commands
     2  
     3  import (
     4  	"os"
     5  
     6  	"github.com/git-lfs/git-lfs/git"
     7  	"github.com/git-lfs/git-lfs/locking"
     8  	"github.com/rubyist/tracerx"
     9  	"github.com/spf13/cobra"
    10  )
    11  
    12  // postCheckoutCommand is run through Git's post-checkout hook. The hook passes
    13  // up to 3 arguments on the command line:
    14  //
    15  //   1. SHA of previous commit before the checkout
    16  //   2. SHA of commit just checked out
    17  //   3. Flag ("0" or "1") - 1 if a branch/tag/SHA was checked out, 0 if a file was
    18  //      In the case of a file being checked out, the pre/post SHA are the same
    19  //
    20  // This hook checks that files which are lockable and not locked are made read-only,
    21  // optimising that as best it can based on the available information.
    22  func postCheckoutCommand(cmd *cobra.Command, args []string) {
    23  	if len(args) != 3 {
    24  		Print("This should be run through Git's post-checkout hook.  Run `git lfs update` to install it.")
    25  		os.Exit(1)
    26  	}
    27  
    28  	// Skip entire hook if lockable read only feature is disabled
    29  	if !cfg.SetLockableFilesReadOnly() {
    30  		os.Exit(0)
    31  	}
    32  
    33  	requireGitVersion()
    34  
    35  	lockClient := newLockClient()
    36  
    37  	// Skip this hook if no lockable patterns have been configured
    38  	if len(lockClient.GetLockablePatterns()) == 0 {
    39  		os.Exit(0)
    40  	}
    41  
    42  	if args[2] == "1" && args[0] != "0000000000000000000000000000000000000000" {
    43  		postCheckoutRevChange(lockClient, args[0], args[1])
    44  	} else {
    45  		postCheckoutFileChange(lockClient)
    46  	}
    47  
    48  }
    49  
    50  func postCheckoutRevChange(client *locking.Client, pre, post string) {
    51  	tracerx.Printf("post-checkout: changes between %v and %v", pre, post)
    52  	// We can speed things up by looking at the difference between previous HEAD
    53  	// and current HEAD, and only checking lockable files that are different
    54  	files, err := git.GetFilesChanged(pre, post)
    55  
    56  	if err != nil {
    57  		LoggedError(err, "Warning: post-checkout rev diff %v:%v failed: %v\nFalling back on full scan.", pre, post, err)
    58  		postCheckoutFileChange(client)
    59  	}
    60  	tracerx.Printf("post-checkout: checking write flags on %v", files)
    61  	err = client.FixLockableFileWriteFlags(files)
    62  	if err != nil {
    63  		LoggedError(err, "Warning: post-checkout locked file check failed: %v", err)
    64  	}
    65  
    66  }
    67  
    68  func postCheckoutFileChange(client *locking.Client) {
    69  	tracerx.Printf("post-checkout: checking write flags for all lockable files")
    70  	// Sadly we don't get any information about what files were checked out,
    71  	// so we have to check the entire repo
    72  	err := client.FixAllLockableFileWriteFlags()
    73  	if err != nil {
    74  		LoggedError(err, "Warning: post-checkout locked file check failed: %v", err)
    75  	}
    76  }
    77  
    78  func init() {
    79  	RegisterCommand("post-checkout", postCheckoutCommand, nil)
    80  }