2014-06-03 15:08:58 +00:00
|
|
|
package commands
|
2013-09-22 23:04:06 +00:00
|
|
|
|
|
|
|
import (
|
2014-06-05 18:19:30 +00:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
2017-09-11 09:42:47 +00:00
|
|
|
"net"
|
2013-09-22 23:04:06 +00:00
|
|
|
"os"
|
2013-10-04 14:42:47 +00:00
|
|
|
"os/exec"
|
2013-09-27 14:39:45 +00:00
|
|
|
"path/filepath"
|
2014-06-05 18:19:30 +00:00
|
|
|
"strings"
|
2017-01-04 23:10:30 +00:00
|
|
|
"sync"
|
2014-06-05 18:19:30 +00:00
|
|
|
"time"
|
2015-05-13 19:43:41 +00:00
|
|
|
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/config"
|
|
|
|
"github.com/git-lfs/git-lfs/errors"
|
2016-11-21 22:14:33 +00:00
|
|
|
"github.com/git-lfs/git-lfs/filepathfilter"
|
2017-10-26 02:23:43 +00:00
|
|
|
"github.com/git-lfs/git-lfs/git"
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfs"
|
2016-12-22 23:59:54 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfsapi"
|
2017-01-03 21:13:59 +00:00
|
|
|
"github.com/git-lfs/git-lfs/locking"
|
2016-12-07 02:50:57 +00:00
|
|
|
"github.com/git-lfs/git-lfs/progress"
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/tools"
|
2016-12-12 00:28:47 +00:00
|
|
|
"github.com/git-lfs/git-lfs/tq"
|
2013-09-22 23:04:06 +00:00
|
|
|
)
|
|
|
|
|
2015-09-14 11:33:59 +00:00
|
|
|
// Populate man pages
|
|
|
|
//go:generate go run ../docs/man/mangen.go
|
|
|
|
|
2014-06-05 18:19:30 +00:00
|
|
|
var (
|
2016-09-01 14:46:26 +00:00
|
|
|
Debugging = false
|
|
|
|
ErrorBuffer = &bytes.Buffer{}
|
|
|
|
ErrorWriter = io.MultiWriter(os.Stderr, ErrorBuffer)
|
|
|
|
OutputWriter = io.MultiWriter(os.Stdout, ErrorBuffer)
|
|
|
|
ManPages = make(map[string]string, 20)
|
2017-10-19 00:09:33 +00:00
|
|
|
tqManifest = make(map[string]*tq.Manifest)
|
2016-09-01 15:21:48 +00:00
|
|
|
|
2017-10-19 00:09:33 +00:00
|
|
|
cfg *config.Configuration
|
|
|
|
apiClient *lfsapi.Client
|
|
|
|
global sync.Mutex
|
2017-01-04 23:10:30 +00:00
|
|
|
|
2016-08-10 15:33:25 +00:00
|
|
|
includeArg string
|
|
|
|
excludeArg string
|
|
|
|
)
|
|
|
|
|
2017-01-04 23:10:30 +00:00
|
|
|
// getTransferManifest builds a tq.Manifest from the global os and git
|
2017-01-03 23:01:45 +00:00
|
|
|
// environments.
|
2017-01-04 23:10:30 +00:00
|
|
|
func getTransferManifest() *tq.Manifest {
|
2017-09-17 10:43:35 +00:00
|
|
|
return getTransferManifestOperationRemote("", "")
|
|
|
|
}
|
|
|
|
|
|
|
|
// getTransferManifestOperationRemote builds a tq.Manifest from the global os
|
|
|
|
// and git environments and operation-specific and remote-specific settings.
|
|
|
|
// Operation must be "download", "upload", or the empty string.
|
|
|
|
func getTransferManifestOperationRemote(operation, remote string) *tq.Manifest {
|
2017-01-04 23:10:30 +00:00
|
|
|
c := getAPIClient()
|
|
|
|
|
|
|
|
global.Lock()
|
|
|
|
defer global.Unlock()
|
|
|
|
|
2017-09-17 10:43:35 +00:00
|
|
|
k := fmt.Sprintf("%s.%s", operation, remote)
|
|
|
|
if tqManifest[k] == nil {
|
2017-10-25 17:46:37 +00:00
|
|
|
tqManifest[k] = tq.NewManifest(cfg.Filesystem(), c, operation, remote)
|
2017-01-04 23:10:30 +00:00
|
|
|
}
|
|
|
|
|
2017-09-17 10:43:35 +00:00
|
|
|
return tqManifest[k]
|
2017-01-03 23:07:57 +00:00
|
|
|
}
|
|
|
|
|
2017-01-04 23:10:30 +00:00
|
|
|
func getAPIClient() *lfsapi.Client {
|
|
|
|
global.Lock()
|
|
|
|
defer global.Unlock()
|
|
|
|
|
|
|
|
if apiClient == nil {
|
2017-10-25 21:33:20 +00:00
|
|
|
c, err := lfsapi.NewClient(cfg)
|
2017-01-04 23:10:30 +00:00
|
|
|
if err != nil {
|
|
|
|
ExitWithError(err)
|
|
|
|
}
|
|
|
|
apiClient = c
|
2016-12-22 23:59:54 +00:00
|
|
|
}
|
2017-01-04 23:10:30 +00:00
|
|
|
return apiClient
|
2016-12-22 23:59:54 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 17:46:13 +00:00
|
|
|
func closeAPIClient() error {
|
|
|
|
global.Lock()
|
|
|
|
defer global.Unlock()
|
|
|
|
if apiClient == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return apiClient.Close()
|
|
|
|
}
|
|
|
|
|
2017-10-27 21:07:32 +00:00
|
|
|
func newLockClient() *locking.Client {
|
|
|
|
lockClient, err := locking.NewClient(cfg.Remote(), getAPIClient())
|
2017-01-03 21:13:59 +00:00
|
|
|
if err == nil {
|
2017-10-25 19:23:12 +00:00
|
|
|
os.MkdirAll(cfg.LFSStorageDir(), 0755)
|
2017-10-24 21:58:42 +00:00
|
|
|
err = lockClient.SetupFileCache(cfg.LFSStorageDir())
|
2017-01-03 21:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
Exit("Unable to create lock system: %v", err.Error())
|
|
|
|
}
|
|
|
|
|
2017-01-16 14:59:55 +00:00
|
|
|
// Configure dirs
|
2017-10-19 00:09:33 +00:00
|
|
|
lockClient.LocalWorkingDir = cfg.LocalWorkingDir()
|
|
|
|
lockClient.LocalGitDir = cfg.LocalGitDir()
|
2017-08-18 00:00:58 +00:00
|
|
|
lockClient.SetLockableFilesReadOnly = cfg.SetLockableFilesReadOnly()
|
2017-01-16 14:59:55 +00:00
|
|
|
|
2017-01-03 21:13:59 +00:00
|
|
|
return lockClient
|
|
|
|
}
|
|
|
|
|
2016-12-13 20:58:09 +00:00
|
|
|
// newDownloadCheckQueue builds a checking queue, checks that objects are there but doesn't download
|
2017-01-04 21:46:30 +00:00
|
|
|
func newDownloadCheckQueue(manifest *tq.Manifest, remote string, options ...tq.Option) *tq.TransferQueue {
|
2017-01-06 18:31:07 +00:00
|
|
|
allOptions := make([]tq.Option, 0, len(options)+1)
|
2017-01-03 22:23:37 +00:00
|
|
|
allOptions = append(allOptions, options...)
|
|
|
|
allOptions = append(allOptions, tq.DryRun(true))
|
2017-01-04 21:46:30 +00:00
|
|
|
return newDownloadQueue(manifest, remote, allOptions...)
|
2016-12-13 20:58:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// newDownloadQueue builds a DownloadQueue, allowing concurrent downloads.
|
2017-01-04 21:46:30 +00:00
|
|
|
func newDownloadQueue(manifest *tq.Manifest, remote string, options ...tq.Option) *tq.TransferQueue {
|
|
|
|
return tq.NewTransferQueue(tq.Download, manifest, remote, options...)
|
2016-12-13 20:58:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// newUploadQueue builds an UploadQueue, allowing `workers` concurrent uploads.
|
2017-01-04 21:46:30 +00:00
|
|
|
func newUploadQueue(manifest *tq.Manifest, remote string, options ...tq.Option) *tq.TransferQueue {
|
|
|
|
return tq.NewTransferQueue(tq.Upload, manifest, remote, options...)
|
2016-12-13 20:58:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func buildFilepathFilter(config *config.Configuration, includeArg, excludeArg *string) *filepathfilter.Filter {
|
|
|
|
inc, exc := determineIncludeExcludePaths(config, includeArg, excludeArg)
|
|
|
|
return filepathfilter.New(inc, exc)
|
2016-08-10 16:08:08 +00:00
|
|
|
}
|
2014-06-05 18:19:30 +00:00
|
|
|
|
2016-12-15 20:20:41 +00:00
|
|
|
func downloadTransfer(p *lfs.WrappedPointer) (name, path, oid string, size int64) {
|
2017-10-25 17:31:15 +00:00
|
|
|
path, _ = cfg.Filesystem().ObjectPath(p.Oid)
|
2016-12-15 20:20:41 +00:00
|
|
|
return p.Name, path, p.Oid, p.Size
|
|
|
|
}
|
|
|
|
|
2017-10-18 21:42:00 +00:00
|
|
|
// Get user-readable manual install steps for hooks
|
|
|
|
func getHookInstallSteps() string {
|
2017-10-18 21:51:48 +00:00
|
|
|
hooks := lfs.LoadHooks(cfg.HookDir())
|
2017-10-18 21:42:00 +00:00
|
|
|
steps := make([]string, 0, len(hooks))
|
|
|
|
for _, h := range hooks {
|
|
|
|
steps = append(steps, fmt.Sprintf(
|
|
|
|
"Add the following to .git/hooks/%s:\n\n%s",
|
|
|
|
h.Type, tools.Indent(h.Contents)))
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(steps, "\n\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func installHooks(force bool) error {
|
2017-10-18 21:51:48 +00:00
|
|
|
hooks := lfs.LoadHooks(cfg.HookDir())
|
2017-10-18 21:42:00 +00:00
|
|
|
for _, h := range hooks {
|
|
|
|
if err := h.Install(force); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// uninstallHooks removes all hooks in range of the `hooks` var.
|
|
|
|
func uninstallHooks() error {
|
2017-10-19 00:25:41 +00:00
|
|
|
if !cfg.InRepo() {
|
|
|
|
return errors.New("Not in a git repository")
|
|
|
|
}
|
|
|
|
|
2017-10-18 21:51:48 +00:00
|
|
|
hooks := lfs.LoadHooks(cfg.HookDir())
|
2017-10-18 21:42:00 +00:00
|
|
|
for _, h := range hooks {
|
|
|
|
if err := h.Uninstall(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-06-05 18:19:30 +00:00
|
|
|
// Error prints a formatted message to Stderr. It also gets printed to the
|
|
|
|
// panic log if one is created for this command.
|
|
|
|
func Error(format string, args ...interface{}) {
|
2016-08-18 21:43:28 +00:00
|
|
|
if len(args) == 0 {
|
|
|
|
fmt.Fprintln(ErrorWriter, format)
|
|
|
|
return
|
2015-06-29 16:27:33 +00:00
|
|
|
}
|
2016-08-18 21:43:28 +00:00
|
|
|
fmt.Fprintf(ErrorWriter, format+"\n", args...)
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Print prints a formatted message to Stdout. It also gets printed to the
|
|
|
|
// panic log if one is created for this command.
|
|
|
|
func Print(format string, args ...interface{}) {
|
2016-08-18 21:43:28 +00:00
|
|
|
if len(args) == 0 {
|
|
|
|
fmt.Fprintln(OutputWriter, format)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
fmt.Fprintf(OutputWriter, format+"\n", args...)
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Exit prints a formatted message and exits.
|
|
|
|
func Exit(format string, args ...interface{}) {
|
|
|
|
Error(format, args...)
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
|
2016-08-16 18:03:37 +00:00
|
|
|
// ExitWithError either panics with a full stack trace for fatal errors, or
|
|
|
|
// simply prints the error message and exits immediately.
|
2016-02-23 16:11:52 +00:00
|
|
|
func ExitWithError(err error) {
|
2016-08-16 18:03:37 +00:00
|
|
|
errorWith(err, Panic, Exit)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FullError prints either a full stack trace for fatal errors, or just the
|
|
|
|
// error message.
|
|
|
|
func FullError(err error) {
|
|
|
|
errorWith(err, LoggedError, Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func errorWith(err error, fatalErrFn func(error, string, ...interface{}), errFn func(string, ...interface{})) {
|
2016-08-18 20:20:33 +00:00
|
|
|
if Debugging || errors.IsFatalError(err) {
|
2016-09-05 22:05:54 +00:00
|
|
|
fatalErrFn(err, "%s", err)
|
2016-08-18 21:43:28 +00:00
|
|
|
return
|
2016-02-23 16:11:52 +00:00
|
|
|
}
|
2016-08-18 21:43:28 +00:00
|
|
|
|
|
|
|
errFn("%s", err)
|
2016-08-17 22:13:36 +00:00
|
|
|
}
|
2016-02-23 16:11:52 +00:00
|
|
|
|
2014-06-05 18:19:30 +00:00
|
|
|
// Debug prints a formatted message if debugging is enabled. The formatted
|
|
|
|
// message also shows up in the panic log, if created.
|
|
|
|
func Debug(format string, args ...interface{}) {
|
|
|
|
if !Debugging {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Printf(format, args...)
|
|
|
|
}
|
|
|
|
|
2016-09-05 22:05:54 +00:00
|
|
|
// LoggedError prints the given message formatted with its arguments (if any) to
|
2017-09-11 09:39:23 +00:00
|
|
|
// Stderr. If an empty string is passed as the "format" argument, only the
|
2016-09-06 16:58:35 +00:00
|
|
|
// standard error logging message will be printed, and the error's body will be
|
|
|
|
// omitted.
|
|
|
|
//
|
|
|
|
// It also writes a stack trace for the error to a log file without exiting.
|
2014-08-07 21:33:29 +00:00
|
|
|
func LoggedError(err error, format string, args ...interface{}) {
|
2016-08-18 21:43:28 +00:00
|
|
|
if len(format) > 0 {
|
|
|
|
Error(format, args...)
|
|
|
|
}
|
2014-06-05 18:19:30 +00:00
|
|
|
file := handlePanic(err)
|
|
|
|
|
|
|
|
if len(file) > 0 {
|
2015-05-05 12:39:05 +00:00
|
|
|
fmt.Fprintf(os.Stderr, "\nErrors logged to %s\nUse `git lfs logs last` to view the log.\n", file)
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
2014-08-07 21:33:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Panic prints a formatted message, and writes a stack trace for the error to
|
|
|
|
// a log file before exiting.
|
|
|
|
func Panic(err error, format string, args ...interface{}) {
|
|
|
|
LoggedError(err, format, args...)
|
2014-06-05 18:19:30 +00:00
|
|
|
os.Exit(2)
|
|
|
|
}
|
2013-09-23 00:39:26 +00:00
|
|
|
|
2016-07-22 00:07:23 +00:00
|
|
|
func Cleanup() {
|
2017-10-25 01:16:14 +00:00
|
|
|
if err := cfg.Cleanup(); err != nil {
|
2016-07-22 00:07:23 +00:00
|
|
|
fmt.Fprintf(os.Stderr, "Error clearing old temp files: %s\n", err)
|
|
|
|
}
|
2013-09-22 23:04:06 +00:00
|
|
|
}
|
|
|
|
|
2013-10-04 14:44:23 +00:00
|
|
|
func PipeMediaCommand(name string, args ...string) error {
|
|
|
|
return PipeCommand("bin/"+name, args...)
|
|
|
|
}
|
|
|
|
|
2013-10-04 14:42:47 +00:00
|
|
|
func PipeCommand(name string, args ...string) error {
|
|
|
|
cmd := exec.Command(name, args...)
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
return cmd.Run()
|
|
|
|
}
|
|
|
|
|
2015-04-24 20:24:32 +00:00
|
|
|
func requireStdin(msg string) {
|
2016-07-04 23:46:35 +00:00
|
|
|
var out string
|
|
|
|
|
|
|
|
stat, err := os.Stdin.Stat()
|
|
|
|
if err != nil {
|
|
|
|
out = fmt.Sprintf("Cannot read from STDIN. %s (%s)", msg, err)
|
|
|
|
} else if (stat.Mode() & os.ModeCharDevice) != 0 {
|
|
|
|
out = fmt.Sprintf("Cannot read from STDIN. %s", msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out) > 0 {
|
|
|
|
Error(out)
|
2015-04-24 20:24:32 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-08 16:23:27 +00:00
|
|
|
func requireInRepo() {
|
2017-10-19 00:25:41 +00:00
|
|
|
if !cfg.InRepo() {
|
2015-09-08 16:23:27 +00:00
|
|
|
Print("Not in a git repository.")
|
|
|
|
os.Exit(128)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-05 18:19:30 +00:00
|
|
|
func handlePanic(err error) string {
|
|
|
|
if err == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:36:02 +00:00
|
|
|
return logPanic(err)
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
|
|
|
|
2015-05-14 17:36:02 +00:00
|
|
|
func logPanic(loggedError error) string {
|
2017-04-25 19:00:55 +00:00
|
|
|
var (
|
|
|
|
fmtWriter io.Writer = os.Stderr
|
|
|
|
lineEnding string = "\n"
|
|
|
|
)
|
2014-08-07 21:00:54 +00:00
|
|
|
|
2015-05-14 17:36:02 +00:00
|
|
|
now := time.Now()
|
|
|
|
name := now.Format("20060102T150405.999999999")
|
2017-10-19 00:09:33 +00:00
|
|
|
full := filepath.Join(cfg.LocalLogDir(), name+".log")
|
2015-05-14 17:36:02 +00:00
|
|
|
|
2017-10-19 00:09:33 +00:00
|
|
|
if err := os.MkdirAll(cfg.LocalLogDir(), 0755); err != nil {
|
2015-05-14 17:39:03 +00:00
|
|
|
full = ""
|
2017-10-19 00:09:33 +00:00
|
|
|
fmt.Fprintf(fmtWriter, "Unable to log panic to %s: %s\n\n", cfg.LocalLogDir(), err.Error())
|
2015-05-14 17:39:03 +00:00
|
|
|
} else if file, err := os.Create(full); err != nil {
|
2015-05-14 17:36:02 +00:00
|
|
|
filename := full
|
|
|
|
full = ""
|
|
|
|
defer func() {
|
|
|
|
fmt.Fprintf(fmtWriter, "Unable to log panic to %s\n\n", filename)
|
2017-04-25 19:00:55 +00:00
|
|
|
logPanicToWriter(fmtWriter, err, lineEnding)
|
2015-05-14 17:36:02 +00:00
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
fmtWriter = file
|
2017-04-25 19:00:55 +00:00
|
|
|
lineEnding = gitLineEnding(cfg.Git)
|
2015-05-14 17:36:02 +00:00
|
|
|
defer file.Close()
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
|
|
|
|
2017-04-25 19:00:55 +00:00
|
|
|
logPanicToWriter(fmtWriter, loggedError, lineEnding)
|
2015-05-14 17:34:58 +00:00
|
|
|
|
|
|
|
return full
|
|
|
|
}
|
|
|
|
|
2017-09-11 09:42:47 +00:00
|
|
|
func ipAddresses() []string {
|
|
|
|
ips := make([]string, 0, 1)
|
|
|
|
ifaces, err := net.Interfaces()
|
|
|
|
if err != nil {
|
|
|
|
ips = append(ips, "Error getting network interface: "+err.Error())
|
|
|
|
return ips
|
|
|
|
}
|
|
|
|
for _, i := range ifaces {
|
|
|
|
if i.Flags&net.FlagUp == 0 {
|
|
|
|
continue // interface down
|
|
|
|
}
|
|
|
|
if i.Flags&net.FlagLoopback != 0 {
|
|
|
|
continue // loopback interface
|
|
|
|
}
|
|
|
|
addrs, _ := i.Addrs()
|
|
|
|
l := make([]string, 0, 1)
|
|
|
|
if err != nil {
|
|
|
|
ips = append(ips, "Error getting IP address: "+err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
|
|
var ip net.IP
|
|
|
|
switch v := addr.(type) {
|
|
|
|
case *net.IPNet:
|
|
|
|
ip = v.IP
|
|
|
|
case *net.IPAddr:
|
|
|
|
ip = v.IP
|
|
|
|
}
|
|
|
|
if ip == nil || ip.IsLoopback() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
l = append(l, ip.String())
|
|
|
|
}
|
|
|
|
if len(l) > 0 {
|
|
|
|
ips = append(ips, strings.Join(l, " "))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ips
|
|
|
|
}
|
|
|
|
|
2017-04-25 19:00:55 +00:00
|
|
|
func logPanicToWriter(w io.Writer, loggedError error, le string) {
|
2015-07-28 22:43:22 +00:00
|
|
|
// log the version
|
2017-10-26 02:23:43 +00:00
|
|
|
gitV, err := git.Version()
|
2015-07-28 22:43:22 +00:00
|
|
|
if err != nil {
|
|
|
|
gitV = "Error getting git version: " + err.Error()
|
|
|
|
}
|
|
|
|
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, config.VersionDesc+le)
|
|
|
|
fmt.Fprint(w, gitV+le)
|
2015-07-28 22:43:22 +00:00
|
|
|
|
|
|
|
// log the command that was run
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, le)
|
2015-07-28 22:43:22 +00:00
|
|
|
fmt.Fprintf(w, "$ %s", filepath.Base(os.Args[0]))
|
2014-06-05 18:19:30 +00:00
|
|
|
if len(os.Args) > 0 {
|
2015-05-14 17:34:58 +00:00
|
|
|
fmt.Fprintf(w, " %s", strings.Join(os.Args[1:], " "))
|
2014-06-05 18:19:30 +00:00
|
|
|
}
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, le)
|
2014-06-05 18:19:30 +00:00
|
|
|
|
2015-07-28 22:43:22 +00:00
|
|
|
// log the error message and stack trace
|
2015-05-14 17:34:58 +00:00
|
|
|
w.Write(ErrorBuffer.Bytes())
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, le)
|
2014-06-05 18:19:30 +00:00
|
|
|
|
2017-05-17 21:13:21 +00:00
|
|
|
fmt.Fprintf(w, "%+v"+le, loggedError)
|
2016-08-19 18:30:53 +00:00
|
|
|
|
2016-08-19 20:03:39 +00:00
|
|
|
for key, val := range errors.Context(err) {
|
2017-05-17 21:13:21 +00:00
|
|
|
fmt.Fprintf(w, "%s=%v"+le, key, val)
|
2014-08-07 22:08:47 +00:00
|
|
|
}
|
2016-08-18 21:43:28 +00:00
|
|
|
|
2017-09-11 10:21:39 +00:00
|
|
|
fmt.Fprint(w, le+"Current time in UTC: "+le)
|
|
|
|
fmt.Fprint(w, time.Now().UTC().Format("2006-01-02 15:04:05")+le)
|
|
|
|
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, le+"ENV:"+le)
|
2014-06-05 18:19:30 +00:00
|
|
|
|
2015-07-28 22:43:22 +00:00
|
|
|
// log the environment
|
2017-01-04 23:10:30 +00:00
|
|
|
for _, env := range lfs.Environ(cfg, getTransferManifest()) {
|
2017-04-25 19:00:55 +00:00
|
|
|
fmt.Fprint(w, env+le)
|
2015-05-14 17:20:23 +00:00
|
|
|
}
|
2017-09-11 09:42:47 +00:00
|
|
|
|
|
|
|
fmt.Fprint(w, le+"Client IP addresses:"+le)
|
|
|
|
|
|
|
|
for _, ip := range ipAddresses() {
|
|
|
|
fmt.Fprint(w, ip+le)
|
|
|
|
}
|
2015-05-14 17:20:23 +00:00
|
|
|
}
|
|
|
|
|
2016-08-01 22:47:41 +00:00
|
|
|
func determineIncludeExcludePaths(config *config.Configuration, includeArg, excludeArg *string) (include, exclude []string) {
|
|
|
|
if includeArg == nil {
|
|
|
|
include = config.FetchIncludePaths()
|
|
|
|
} else {
|
|
|
|
include = tools.CleanPaths(*includeArg, ",")
|
|
|
|
}
|
|
|
|
if excludeArg == nil {
|
|
|
|
exclude = config.FetchExcludePaths()
|
|
|
|
} else {
|
|
|
|
exclude = tools.CleanPaths(*excludeArg, ",")
|
|
|
|
}
|
|
|
|
return
|
2016-05-31 15:48:09 +00:00
|
|
|
}
|
|
|
|
|
2016-12-07 20:27:42 +00:00
|
|
|
func buildProgressMeter(dryRun bool) *progress.ProgressMeter {
|
|
|
|
return progress.NewMeter(
|
|
|
|
progress.WithOSEnv(cfg.Os),
|
|
|
|
progress.DryRun(dryRun),
|
|
|
|
)
|
2016-12-07 02:50:57 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 22:13:36 +00:00
|
|
|
func requireGitVersion() {
|
|
|
|
minimumGit := "1.8.2"
|
2016-08-17 22:17:35 +00:00
|
|
|
|
2017-10-26 02:23:43 +00:00
|
|
|
if !git.IsGitVersionAtLeast(minimumGit) {
|
|
|
|
gitver, err := git.Version()
|
2016-08-17 22:21:00 +00:00
|
|
|
if err != nil {
|
|
|
|
Exit("Error getting git version: %s", err)
|
|
|
|
}
|
2016-08-17 22:17:35 +00:00
|
|
|
Exit("git version >= %s is required for Git LFS, your version: %s", minimumGit, gitver)
|
2016-08-17 22:13:36 +00:00
|
|
|
}
|
|
|
|
}
|