From 3adf5368dd2204b055eb533fef735113b6124df0 Mon Sep 17 00:00:00 2001 From: frealgagu Date: Thu, 9 Aug 2018 09:13:24 -0500 Subject: [PATCH 01/36] Adding arch linux packages to README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 0bd9b310f..daf8f633c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,20 @@ sudo apt-get update sudo apt-get install lazygit ``` +### Arch Linux +Packages for Arch Linux are available via AUR (Arch User Repository). + +There are two packages. The stable which is built with the last releases and the git version which takes the last commit and build based on. + +Stable: +https://aur.archlinux.org/packages/lazygit/ + +Development: +https://aur.archlinux.org/packages/lazygit-git/ + +Instruction of how to install AUR content can be found here: +https://wiki.archlinux.org/index.php/Arch_User_Repository + ### Binary Release (Windows/Linux/OSX) You can download a binary release [here](https://github.com/jesseduffield/lazygit/releases) From 87872f5514b645f90135b3e91128b3777a853343 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 11:33:49 +1000 Subject: [PATCH 02/36] explicitly add go-git dependency --- Gopkg.lock | 9 +- Gopkg.toml | 4 + .../golang.org/x/sys/unix/syscall_darwin.go | 32 +++++-- .../golang.org/x/sys/unix/syscall_freebsd.go | 8 -- vendor/golang.org/x/sys/unix/syscall_linux.go | 9 +- vendor/golang.org/x/sys/unix/types_freebsd.go | 2 + .../x/sys/unix/zerrors_linux_386.go | 3 + .../x/sys/unix/zerrors_linux_amd64.go | 3 + .../x/sys/unix/zerrors_linux_arm.go | 3 + .../x/sys/unix/zerrors_linux_arm64.go | 3 + .../x/sys/unix/zerrors_linux_mips.go | 3 + .../x/sys/unix/zerrors_linux_mips64.go | 3 + .../x/sys/unix/zerrors_linux_mips64le.go | 3 + .../x/sys/unix/zerrors_linux_mipsle.go | 3 + .../x/sys/unix/zerrors_linux_ppc64.go | 3 + .../x/sys/unix/zerrors_linux_ppc64le.go | 3 + .../x/sys/unix/zerrors_linux_s390x.go | 3 + .../x/sys/unix/zerrors_openbsd_amd64.go | 1 + .../x/sys/unix/zsyscall_darwin_386.go | 57 +++++++++++ .../x/sys/unix/zsyscall_darwin_amd64.go | 57 +++++++++++ .../x/sys/unix/zsyscall_darwin_arm.go | 57 +++++++++++ .../x/sys/unix/zsyscall_darwin_arm64.go | 57 +++++++++++ .../x/sys/unix/zsyscall_linux_386.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_amd64.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_arm.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_arm64.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_mips.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_mips64.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_mips64le.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_mipsle.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_ppc64.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_ppc64le.go | 95 +++++++++++++++++++ .../x/sys/unix/zsyscall_linux_s390x.go | 95 +++++++++++++++++++ .../x/sys/unix/zsysnum_openbsd_amd64.go | 1 + .../x/sys/unix/ztypes_freebsd_386.go | 2 + .../x/sys/unix/ztypes_freebsd_amd64.go | 2 + .../x/sys/unix/ztypes_freebsd_arm.go | 2 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 1 + .../x/sys/unix/ztypes_linux_amd64.go | 1 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 1 + .../x/sys/unix/ztypes_linux_arm64.go | 1 + .../x/sys/unix/ztypes_linux_mips.go | 1 + .../x/sys/unix/ztypes_linux_mips64.go | 1 + .../x/sys/unix/ztypes_linux_mips64le.go | 1 + .../x/sys/unix/ztypes_linux_mipsle.go | 1 + .../x/sys/unix/ztypes_linux_ppc64.go | 1 + .../x/sys/unix/ztypes_linux_ppc64le.go | 1 + .../x/sys/unix/ztypes_linux_s390x.go | 1 + .../src-d/go-git.v4/plumbing/object/commit.go | 31 +++--- .../src-d/go-git.v4/plumbing/object/tree.go | 5 +- .../transport/internal/common/common.go | 5 + vendor/gopkg.in/src-d/go-git.v4/repository.go | 8 +- 52 files changed, 1391 insertions(+), 47 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index c2689a1ff..65f765807 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -176,14 +176,14 @@ [[projects]] branch = "master" - digest = "1:de22999d08e1604a7c3186ef64b5a18a90e399b99c4e8ff2a8d6c6abf42b7934" + digest = "1:87aef4c266c820591e859450c3ee5ab98f9b8755d7cfd9e4db606959eb5b483d" name = "golang.org/x/sys" packages = [ "unix", "windows", ] pruneopts = "NUT" - revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe" + revision = "904bdc257025c7b3f43c19360ad3ab85783fad78" [[projects]] digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295" @@ -215,7 +215,7 @@ version = "v4.2.0" [[projects]] - digest = "1:fa265385a5175b4aaed0cccec60059a3f363c3f209bba1b658e9a12baddbc5e0" + digest = "1:e66078da2bd6e53c72518d7f6ae0c3c8c7f34c0df12c39435ce34a6bce165525" name = "gopkg.in/src-d/go-git.v4" packages = [ ".", @@ -260,8 +260,7 @@ "utils/merkletrie/noder", ] pruneopts = "NUT" - revision = "3bd5e82b2512d85becae9677fa06b5a973fd4cfb" - version = "v4.5.0" + revision = "43d17e14b714665ab5bc2ecc220b6740779d733f" [[projects]] digest = "1:b233ad4ec87ac916e7bf5e678e98a2cb9e8b52f6de6ad3e11834fc7a71b8e3bf" diff --git a/Gopkg.toml b/Gopkg.toml index 308fea11f..a47fe5e93 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -36,3 +36,7 @@ [[constraint]] branch = "master" name = "github.com/jesseduffield/gocui" + +[[constraint]] + name = "gopkg.in/src-d/go-git.v4" + revision = "43d17e14b714665ab5bc2ecc220b6740779d733f" diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 166ac0b53..1aabc560d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -199,7 +199,13 @@ func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { return getxattr(link, attr, xattrPointer(dest), len(dest), 0, XATTR_NOFOLLOW) } -//sys setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) +//sys fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) + +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + return fgetxattr(fd, attr, xattrPointer(dest), len(dest), 0, 0) +} + +//sys setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) func Setxattr(path string, attr string, data []byte, flags int) (err error) { // The parameters for the OS X implementation vary slightly compared to the @@ -235,7 +241,13 @@ func Lsetxattr(link string, attr string, data []byte, flags int) (err error) { return setxattr(link, attr, xattrPointer(data), len(data), 0, flags|XATTR_NOFOLLOW) } -//sys removexattr(path string, attr string, options int) (err error) +//sys fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) + +func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) { + return fsetxattr(fd, attr, xattrPointer(data), len(data), 0, 0) +} + +//sys removexattr(path string, attr string, options int) (err error) func Removexattr(path string, attr string) (err error) { // We wrap around and explicitly zero out the options provided to the OS X @@ -248,6 +260,12 @@ func Lremovexattr(link string, attr string) (err error) { return removexattr(link, attr, XATTR_NOFOLLOW) } +//sys fremovexattr(fd int, attr string, options int) (err error) + +func Fremovexattr(fd int, attr string) (err error) { + return fremovexattr(fd, attr, 0) +} + //sys listxattr(path string, dest *byte, size int, options int) (sz int, err error) func Listxattr(path string, dest []byte) (sz int, err error) { @@ -258,6 +276,12 @@ func Llistxattr(link string, dest []byte) (sz int, err error) { return listxattr(link, xattrPointer(dest), len(dest), XATTR_NOFOLLOW) } +//sys flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + return flistxattr(fd, xattrPointer(dest), len(dest), 0) +} + func setattrlistTimes(path string, times []Timespec, flags int) error { _p0, err := BytePtrFromString(path) if err != nil { @@ -529,10 +553,6 @@ func Uname(uname *Utsname) error { // Watchevent // Waitevent // Modwatch -// Fgetxattr -// Fsetxattr -// Fremovexattr -// Flistxattr // Fsctl // Initgroups // Posix_spawn diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 063c03126..e12cc985d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -602,14 +602,6 @@ func Uname(uname *Utsname) error { // Watchevent // Waitevent // Modwatch -// Getxattr -// Fgetxattr -// Setxattr -// Fsetxattr -// Removexattr -// Fremovexattr -// Listxattr -// Flistxattr // Fsctl // Initgroups // Posix_spawn diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 712d17260..eb6335402 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1288,7 +1288,11 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys fcntl(fd int, cmd int, arg int) (val int, err error) //sys Fdatasync(fd int) (err error) +//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) +//sys Flistxattr(fd int, dest []byte) (sz int, err error) //sys Flock(fd int, how int) (err error) +//sys Fremovexattr(fd int, attr string) (err error) +//sys Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) //sys Fsync(fd int) (err error) //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 //sysnb Getpgid(pid int) (pgid int, err error) @@ -1327,6 +1331,7 @@ func Getpgrp() (pid int) { //sys read(fd int, p []byte) (n int, err error) //sys Removexattr(path string, attr string) (err error) //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) +//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) //sys RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) //sys Setdomainname(p []byte) (err error) //sys Sethostname(p []byte) (err error) @@ -1500,11 +1505,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { // EpollPwait // EpollWaitOld // Execve -// Fgetxattr -// Flistxattr // Fork -// Fremovexattr -// Fsetxattr // Futex // GetKernelSyms // GetMempolicy diff --git a/vendor/golang.org/x/sys/unix/types_freebsd.go b/vendor/golang.org/x/sys/unix/types_freebsd.go index 4eb02cd4d..f4b6bf961 100644 --- a/vendor/golang.org/x/sys/unix/types_freebsd.go +++ b/vendor/golang.org/x/sys/unix/types_freebsd.go @@ -204,6 +204,8 @@ const ( // Directory mode bits S_IRUSR = C.S_IRUSR S_IWUSR = C.S_IWUSR S_IXUSR = C.S_IXUSR + S_IRWXG = C.S_IRWXG + S_IRWXO = C.S_IRWXO ) type Stat_t C.struct_stat8 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 60425aa1c..e398aab9d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -1429,6 +1429,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 0d8fd21fe..12a147cfa 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -1430,6 +1430,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 20e3bd84d..ee623b89f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -1436,6 +1436,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index f97a16284..deab46bcc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -1420,6 +1420,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index bb572adeb..3bd5e10cc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -1430,6 +1430,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x6 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 68565e0f4..d3a3cdc85 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -1430,6 +1430,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x6 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 61ba9c06c..012002240 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -1430,6 +1430,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x6 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 530df8ba2..26adfa689 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -1430,6 +1430,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x6 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index e856d341a..24b588b15 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -1486,6 +1486,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 78de4ca93..d184544e9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -1486,6 +1486,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index e54a7192c..1832f0e27 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -1490,6 +1490,9 @@ const ( RAMFS_MAGIC = 0x858458f6 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 + RENAME_EXCHANGE = 0x2 + RENAME_NOREPLACE = 0x1 + RENAME_WHITEOUT = 0x4 RLIMIT_AS = 0x9 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index acfc66469..971073624 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -472,6 +472,7 @@ const ( F_GETLK = 0x7 F_GETOWN = 0x5 F_ISATTY = 0xb + F_OK = 0x0 F_RDLCK = 0x1 F_SETFD = 0x2 F_SETFL = 0x4 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go index ac02d4d84..9ce06df6e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func removexattr(path string, attr string, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fremovexattr(fd int, attr string, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { + r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 1dd3cfa0e..de9927049 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func removexattr(path string, attr string, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fremovexattr(fd int, attr string, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { + r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go index cab46e74b..81c4f0935 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func removexattr(path string, attr string, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fremovexattr(fd int, attr string, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { + r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 13478dd0b..338c32d40 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -420,6 +420,22 @@ func getxattr(path string, attr string, dest *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fgetxattr(fd int, attr string, dest *byte, size int, position uint32, options int) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(position), uintptr(options)) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func setxattr(path string, attr string, data *byte, size int, position uint32, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -440,6 +456,21 @@ func setxattr(path string, attr string, data *byte, size int, position uint32, o // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsetxattr(fd int, attr string, data *byte, size int, position uint32, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(data)), uintptr(size), uintptr(position), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func removexattr(path string, attr string, options int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -460,6 +491,21 @@ func removexattr(path string, attr string, options int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fremovexattr(fd int, attr string, options int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(options)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func listxattr(path string, dest *byte, size int, options int) (sz int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -476,6 +522,17 @@ func listxattr(path string, dest *byte, size int, options int) (sz int, err erro // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func flistxattr(fd int, dest *byte, size int, options int) (sz int, err error) { + r0, _, e1 := Syscall6(SYS_FLISTXATTR, uintptr(fd), uintptr(unsafe.Pointer(dest)), uintptr(size), uintptr(options), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func kill(pid int, signum int, posix int) (err error) { _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index 237e96095..8e8d427d6 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 9b40f580b..2f60780ca 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index d93cc2f3b..d29a11c94 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 5f7d0213b..d03eb2968 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index ac3b8f8c6..dea09328b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index 382e072f5..31bbcff44 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index da33eb12b..e025a33aa 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index 62a71ad84..57d7d931d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index 7cc1bfd12..2f7110d7c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index c3dcb3818..bb3bd5956 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 38f903cd3..c637da95f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -574,6 +574,45 @@ func Fdatasync(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_FGETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), 0, 0) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FLISTXATTR, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + sz = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -584,6 +623,42 @@ func Flock(fd int, how int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_FREMOVEXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_FSETXATTR, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fsync(fd int) (err error) { _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) if e1 != 0 { @@ -1063,6 +1138,26 @@ func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err e // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT2, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) { var _p0 *byte _p0, err = BytePtrFromString(keyType) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go index 10edff07d..bc7fa5795 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go @@ -116,6 +116,7 @@ const ( SYS_PSELECT = 110 // { int sys_pselect(int nd, fd_set *in, fd_set *ou, \ SYS_SIGSUSPEND = 111 // { int sys_sigsuspend(int mask); } SYS_SENDSYSLOG = 112 // { int sys_sendsyslog(const char *buf, size_t nbyte, \ + SYS_UNVEIL = 114 // { int sys_unveil(const char *path, \ SYS_GETSOCKOPT = 118 // { int sys_getsockopt(int s, int level, int name, \ SYS_THRKILL = 119 // { int sys_thrkill(pid_t tid, int signum, void *tcb); } SYS_READV = 120 // { ssize_t sys_readv(int fd, \ diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 878a21ad6..81793a2ad 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -71,6 +71,8 @@ const ( S_IRUSR = 0x100 S_IWUSR = 0x80 S_IXUSR = 0x40 + S_IRWXG = 0x38 + S_IRWXO = 0x7 ) type Stat_t struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 8408af125..6c7589b45 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -71,6 +71,8 @@ const ( S_IRUSR = 0x100 S_IWUSR = 0x80 S_IXUSR = 0x40 + S_IRWXG = 0x38 + S_IRWXO = 0x7 ) type Stat_t struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index 4b2d9a483..f620a125c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -73,6 +73,8 @@ const ( S_IRUSR = 0x100 S_IWUSR = 0x80 S_IXUSR = 0x40 + S_IRWXG = 0x38 + S_IRWXO = 0x7 ) type Stat_t struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 82bf50ddf..cb3729eab 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -441,6 +441,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index d6e77d605..0f3c0fb54 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -445,6 +445,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 3df831003..bd534da87 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -444,6 +444,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index c5b8a6bcb..3a72fd9f1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -446,6 +446,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 86098003f..cd360b270 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -442,6 +442,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 7e4aaa824..d35ec6022 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -446,6 +446,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 8d433fa9a..0f4993024 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -446,6 +446,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index b8b7f6952..55f97c5cc 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -442,6 +442,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 16f246377..f1d426445 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -447,6 +447,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index b976b4459..90ab1f7af 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -447,6 +447,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 8bba23d0a..898ac4514 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -445,6 +445,7 @@ const ( IFLA_ADDRESS = 0x1 IFLA_BROADCAST = 0x2 IFLA_IFNAME = 0x3 + IFLA_INFO_KIND = 0x1 IFLA_MTU = 0x4 IFLA_LINK = 0x5 IFLA_QDISC = 0x6 diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit.go index 3ed85ba3b..b1c0e0180 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit.go @@ -17,8 +17,9 @@ import ( ) const ( - beginpgp string = "-----BEGIN PGP SIGNATURE-----" - endpgp string = "-----END PGP SIGNATURE-----" + beginpgp string = "-----BEGIN PGP SIGNATURE-----" + endpgp string = "-----END PGP SIGNATURE-----" + headerpgp string = "gpgsig" ) // Hash represents the hash of an object @@ -181,23 +182,13 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { } if pgpsig { - // Check if it's the end of a PGP signature. - if bytes.Contains(line, []byte(endpgp)) { - c.PGPSignature += endpgp + "\n" - pgpsig = false - } else { - // Trim the left padding. + if len(line) > 0 && line[0] == ' ' { line = bytes.TrimLeft(line, " ") c.PGPSignature += string(line) + continue + } else { + pgpsig = false } - continue - } - - // Check if it's the beginning of a PGP signature. - if bytes.Contains(line, []byte(beginpgp)) { - c.PGPSignature += beginpgp + "\n" - pgpsig = true - continue } if !message { @@ -217,6 +208,9 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { c.Author.Decode(split[1]) case "committer": c.Committer.Decode(split[1]) + case headerpgp: + c.PGPSignature += string(split[1]) + "\n" + pgpsig = true } } else { c.Message += string(line) @@ -269,13 +263,14 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) { } if b.PGPSignature != "" && includeSig { - if _, err = fmt.Fprint(w, "pgpsig"); err != nil { + if _, err = fmt.Fprint(w, "\n"+headerpgp); err != nil { return err } // Split all the signature lines and write with a left padding and // newline at the end. - lines := strings.Split(b.PGPSignature, "\n") + signature := strings.TrimSuffix(b.PGPSignature, "\n") + lines := strings.Split(signature, "\n") for _, line := range lines { if _, err = fmt.Fprintf(w, " %s\n", line); err != nil { return err diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/tree.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/tree.go index 86d19c01d..c36a1370f 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/tree.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/tree.go @@ -26,6 +26,7 @@ var ( ErrMaxTreeDepth = errors.New("maximum tree depth exceeded") ErrFileNotFound = errors.New("file not found") ErrDirectoryNotFound = errors.New("directory not found") + ErrEntryNotFound = errors.New("entry not found") ) // Tree is basically like a directory - it references a bunch of other trees @@ -167,8 +168,6 @@ func (t *Tree) dir(baseName string) (*Tree, error) { return tree, err } -var errEntryNotFound = errors.New("entry not found") - func (t *Tree) entry(baseName string) (*TreeEntry, error) { if t.m == nil { t.buildMap() @@ -176,7 +175,7 @@ func (t *Tree) entry(baseName string) (*TreeEntry, error) { entry, ok := t.m[baseName] if !ok { - return nil, errEntryNotFound + return nil, ErrEntryNotFound } return entry, nil diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common/common.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common/common.go index 8ec1ea52b..00497f3c1 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common/common.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common/common.go @@ -382,6 +382,7 @@ var ( gitProtocolNotFoundErr = "ERR \n Repository not found." gitProtocolNoSuchErr = "ERR no such repository" gitProtocolAccessDeniedErr = "ERR access denied" + gogsAccessDeniedErr = "Gogs: Repository does not exist or you do not have access" ) func isRepoNotFoundError(s string) bool { @@ -409,6 +410,10 @@ func isRepoNotFoundError(s string) bool { return true } + if strings.HasPrefix(s, gogsAccessDeniedErr) { + return true + } + return false } diff --git a/vendor/gopkg.in/src-d/go-git.v4/repository.go b/vendor/gopkg.in/src-d/go-git.v4/repository.go index 717381bdb..54572bc2b 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/repository.go +++ b/vendor/gopkg.in/src-d/go-git.v4/repository.go @@ -845,8 +845,9 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { return nil, fmt.Errorf("invalid Order=%v", o.Order) } -// Tags returns all the References from Tags. This method returns all the tag -// types, lightweight, and annotated ones. +// Tags returns all the References from Tags. This method returns only lightweight +// tags. Note that not all the tags are lightweight ones. To return annotated tags +// too, you need to call TagObjects() method. func (r *Repository) Tags() (storer.ReferenceIter, error) { refIter, err := r.Storer.IterReferences() if err != nil { @@ -872,7 +873,8 @@ func (r *Repository) Branches() (storer.ReferenceIter, error) { }, refIter), nil } -// Notes returns all the References that are Branches. +// Notes returns all the References that are notes. For more information: +// https://git-scm.com/docs/git-notes func (r *Repository) Notes() (storer.ReferenceIter, error) { refIter, err := r.Storer.IterReferences() if err != nil { From d3abd9eab117e840303d56bff343d258e9448855 Mon Sep 17 00:00:00 2001 From: Ching-Hsuan Yen Date: Wed, 8 Aug 2018 15:52:04 +0800 Subject: [PATCH 03/36] Add `fixup` option into commits panel --- commits_panel.go | 20 ++++++++++++++++++++ gitcommands.go | 34 ++++++++++++++++++++++++++++++++++ keybindings.go | 1 + 3 files changed, 55 insertions(+) diff --git a/commits_panel.go b/commits_panel.go index 88c7b8ebe..b222d346c 100644 --- a/commits_panel.go +++ b/commits_panel.go @@ -65,6 +65,7 @@ func renderCommitsOptions(g *gocui.Gui) error { "s": "squash down", "r": "rename", "g": "reset to this commit", + "f": "fixup commit", "← → ↑ ↓": "navigate", }) } @@ -105,6 +106,25 @@ func handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error { return handleCommitSelect(g, v) } +func handleCommitFixup(g *gocui.Gui, v *gocui.View) error { + if len(state.Commits) == 1 { + return createErrorPanel(g, "You have no commits to squash with") + } + branch := state.Branches[0] + commit, err := getSelectedCommit(g) + if err != nil { + return err + } + if output, err := gitSquashFixupCommit(branch.Name, commit.Sha); err != nil { + return createErrorPanel(g, output) + } + if err := refreshCommits(g); err != nil { + panic(err) + } + refreshStatus(g) + return handleCommitSelect(g, v) +} + func handleRenameCommit(g *gocui.Gui, v *gocui.View) error { if getItemPosition(v) != 0 { return createErrorPanel(g, "Can only rename topmost commit") diff --git a/gitcommands.go b/gitcommands.go index fbe8ddae5..bb49f487c 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -491,6 +491,40 @@ func gitSquashPreviousTwoCommits(message string) (string, error) { return runDirectCommand("git reset --soft HEAD^ && git commit --amend -m \"" + message + "\"") } +func gitSquashFixupCommit(branchName string, shaValue string) (string, error) { + ret := "" + output, err := runDirectCommand("git checkout -q " + shaValue) + ret += output + if err != nil { + goto FIXUP_ERROR + } + output, err = runDirectCommand("git reset --soft " + shaValue + "^") + ret += output + if err != nil { + goto FIXUP_ERROR + } + output, err = runDirectCommand("git commit --amend -C " + shaValue + "^") + ret += output + if err != nil { + goto FIXUP_ERROR + } + output, err = runDirectCommand("git rebase --onto HEAD " + shaValue + " " + branchName) + ret += output + if err != nil { + goto FIXUP_ERROR + } + return ret, err + +FIXUP_ERROR: + //Failed to perform rebase, back to the original branch + output2, err2 := runDirectCommand("git checkout " + branchName) + ret += output2 + if err2 != nil { + return ret, err2 + } + return ret, err +} + func gitRenameCommit(message string) (string, error) { return runDirectCommand("git commit --allow-empty --amend -m \"" + message + "\"") } diff --git a/keybindings.go b/keybindings.go index 0fb800d6e..292f63007 100644 --- a/keybindings.go +++ b/keybindings.go @@ -55,6 +55,7 @@ func keybindings(g *gocui.Gui) error { Binding{ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, Binding{ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, Binding{ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, Handler: handleResetToCommit}, + Binding{ViewName: "commits", Key: 'f', Modifier: gocui.ModNone, Handler: handleCommitFixup}, Binding{ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, Binding{ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, Binding{ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, From de7ab80539a337252aae834ef10fda9574115446 Mon Sep 17 00:00:00 2001 From: Anthony HAMON Date: Fri, 10 Aug 2018 09:54:21 +0200 Subject: [PATCH 04/36] apply gofmt -s -w --- keybindings.go | 106 ++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/keybindings.go b/keybindings.go index 0fb800d6e..07309790f 100644 --- a/keybindings.go +++ b/keybindings.go @@ -14,65 +14,65 @@ type Binding struct { func keybindings(g *gocui.Gui) error { bindings := []Binding{ - Binding{ViewName: "", Key: 'q', Modifier: gocui.ModNone, Handler: quit}, - Binding{ViewName: "", Key: gocui.KeyCtrlC, Modifier: gocui.ModNone, Handler: quit}, - Binding{ViewName: "", Key: gocui.KeyPgup, Modifier: gocui.ModNone, Handler: scrollUpMain}, - Binding{ViewName: "", Key: gocui.KeyPgdn, Modifier: gocui.ModNone, Handler: scrollDownMain}, - Binding{ViewName: "", Key: 'P', Modifier: gocui.ModNone, Handler: pushFiles}, - Binding{ViewName: "", Key: 'p', Modifier: gocui.ModNone, Handler: pullFiles}, - Binding{ViewName: "", Key: 'R', Modifier: gocui.ModNone, Handler: handleRefresh}, - Binding{ViewName: "files", Key: 'c', Modifier: gocui.ModNone, Handler: handleCommitPress}, - Binding{ViewName: "files", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleFilePress}, - Binding{ViewName: "files", Key: 'd', Modifier: gocui.ModNone, Handler: handleFileRemove}, - Binding{ViewName: "files", Key: 'm', Modifier: gocui.ModNone, Handler: handleSwitchToMerge}, - Binding{ViewName: "files", Key: 'e', Modifier: gocui.ModNone, Handler: handleFileEdit}, - Binding{ViewName: "files", Key: 'o', Modifier: gocui.ModNone, Handler: handleFileOpen}, - Binding{ViewName: "files", Key: 's', Modifier: gocui.ModNone, Handler: handleSublimeFileOpen}, - Binding{ViewName: "files", Key: 'v', Modifier: gocui.ModNone, Handler: handleVsCodeFileOpen}, - Binding{ViewName: "files", Key: 'i', Modifier: gocui.ModNone, Handler: handleIgnoreFile}, - Binding{ViewName: "files", Key: 'r', Modifier: gocui.ModNone, Handler: handleRefreshFiles}, - Binding{ViewName: "files", Key: 'S', Modifier: gocui.ModNone, Handler: handleStashSave}, - Binding{ViewName: "files", Key: 'a', Modifier: gocui.ModNone, Handler: handleAbortMerge}, - Binding{ViewName: "files", Key: 't', Modifier: gocui.ModNone, Handler: handleAddPatch}, - Binding{ViewName: "files", Key: 'D', Modifier: gocui.ModNone, Handler: handleResetHard}, - Binding{ViewName: "main", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleEscapeMerge}, - Binding{ViewName: "main", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handlePickHunk}, - Binding{ViewName: "main", Key: 'b', Modifier: gocui.ModNone, Handler: handlePickBothHunks}, - Binding{ViewName: "main", Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, - Binding{ViewName: "main", Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, - Binding{ViewName: "main", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: handleSelectTop}, - Binding{ViewName: "main", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: handleSelectBottom}, - Binding{ViewName: "main", Key: 'h', Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, - Binding{ViewName: "main", Key: 'l', Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, - Binding{ViewName: "main", Key: 'k', Modifier: gocui.ModNone, Handler: handleSelectTop}, - Binding{ViewName: "main", Key: 'j', Modifier: gocui.ModNone, Handler: handleSelectBottom}, - Binding{ViewName: "main", Key: 'z', Modifier: gocui.ModNone, Handler: handlePopFileSnapshot}, - Binding{ViewName: "branches", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleBranchPress}, - Binding{ViewName: "branches", Key: 'c', Modifier: gocui.ModNone, Handler: handleCheckoutByName}, - Binding{ViewName: "branches", Key: 'F', Modifier: gocui.ModNone, Handler: handleForceCheckout}, - Binding{ViewName: "branches", Key: 'n', Modifier: gocui.ModNone, Handler: handleNewBranch}, - Binding{ViewName: "branches", Key: 'm', Modifier: gocui.ModNone, Handler: handleMerge}, - Binding{ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, - Binding{ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, - Binding{ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, Handler: handleResetToCommit}, - Binding{ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, - Binding{ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, - Binding{ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, + {ViewName: "", Key: 'q', Modifier: gocui.ModNone, Handler: quit}, + {ViewName: "", Key: gocui.KeyCtrlC, Modifier: gocui.ModNone, Handler: quit}, + {ViewName: "", Key: gocui.KeyPgup, Modifier: gocui.ModNone, Handler: scrollUpMain}, + {ViewName: "", Key: gocui.KeyPgdn, Modifier: gocui.ModNone, Handler: scrollDownMain}, + {ViewName: "", Key: 'P', Modifier: gocui.ModNone, Handler: pushFiles}, + {ViewName: "", Key: 'p', Modifier: gocui.ModNone, Handler: pullFiles}, + {ViewName: "", Key: 'R', Modifier: gocui.ModNone, Handler: handleRefresh}, + {ViewName: "files", Key: 'c', Modifier: gocui.ModNone, Handler: handleCommitPress}, + {ViewName: "files", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleFilePress}, + {ViewName: "files", Key: 'd', Modifier: gocui.ModNone, Handler: handleFileRemove}, + {ViewName: "files", Key: 'm', Modifier: gocui.ModNone, Handler: handleSwitchToMerge}, + {ViewName: "files", Key: 'e', Modifier: gocui.ModNone, Handler: handleFileEdit}, + {ViewName: "files", Key: 'o', Modifier: gocui.ModNone, Handler: handleFileOpen}, + {ViewName: "files", Key: 's', Modifier: gocui.ModNone, Handler: handleSublimeFileOpen}, + {ViewName: "files", Key: 'v', Modifier: gocui.ModNone, Handler: handleVsCodeFileOpen}, + {ViewName: "files", Key: 'i', Modifier: gocui.ModNone, Handler: handleIgnoreFile}, + {ViewName: "files", Key: 'r', Modifier: gocui.ModNone, Handler: handleRefreshFiles}, + {ViewName: "files", Key: 'S', Modifier: gocui.ModNone, Handler: handleStashSave}, + {ViewName: "files", Key: 'a', Modifier: gocui.ModNone, Handler: handleAbortMerge}, + {ViewName: "files", Key: 't', Modifier: gocui.ModNone, Handler: handleAddPatch}, + {ViewName: "files", Key: 'D', Modifier: gocui.ModNone, Handler: handleResetHard}, + {ViewName: "main", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleEscapeMerge}, + {ViewName: "main", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handlePickHunk}, + {ViewName: "main", Key: 'b', Modifier: gocui.ModNone, Handler: handlePickBothHunks}, + {ViewName: "main", Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, + {ViewName: "main", Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, + {ViewName: "main", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: handleSelectTop}, + {ViewName: "main", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: handleSelectBottom}, + {ViewName: "main", Key: 'h', Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, + {ViewName: "main", Key: 'l', Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, + {ViewName: "main", Key: 'k', Modifier: gocui.ModNone, Handler: handleSelectTop}, + {ViewName: "main", Key: 'j', Modifier: gocui.ModNone, Handler: handleSelectBottom}, + {ViewName: "main", Key: 'z', Modifier: gocui.ModNone, Handler: handlePopFileSnapshot}, + {ViewName: "branches", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleBranchPress}, + {ViewName: "branches", Key: 'c', Modifier: gocui.ModNone, Handler: handleCheckoutByName}, + {ViewName: "branches", Key: 'F', Modifier: gocui.ModNone, Handler: handleForceCheckout}, + {ViewName: "branches", Key: 'n', Modifier: gocui.ModNone, Handler: handleNewBranch}, + {ViewName: "branches", Key: 'm', Modifier: gocui.ModNone, Handler: handleMerge}, + {ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, + {ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, + {ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, Handler: handleResetToCommit}, + {ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, + {ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, + {ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, } // Would make these keybindings global but that interferes with editing // input in the confirmation panel for _, viewName := range []string{"files", "branches", "commits", "stash"} { bindings = append(bindings, []Binding{ - Binding{ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: previousView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: cursorUp}, - Binding{ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: cursorDown}, - Binding{ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: previousView}, - Binding{ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: cursorUp}, - Binding{ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: cursorDown}, + {ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: previousView}, + {ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: cursorUp}, + {ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: cursorDown}, + {ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: previousView}, + {ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: cursorUp}, + {ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: cursorDown}, }...) } From d08241b2ea2f6cbf030be31c116502c92e55b1c7 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 21:33:49 +1000 Subject: [PATCH 05/36] Obtain branches in a more robust way. Begin refactor work on gitcommands --- branch.go | 42 ++++++++ branch_list_builder.go | 122 ++++++++++++++++++++++ branches_panel.go | 4 +- colorer.go | 17 ++++ gitcommands.go | 158 +---------------------------- gui.go | 2 + main.go | 4 +- merge_panel.go | 2 +- {bin => scripts}/push_new_patch.go | 0 status_panel.go | 9 +- utils.go | 23 +++++ view_helpers.go | 16 --- 12 files changed, 221 insertions(+), 178 deletions(-) create mode 100644 branch.go create mode 100644 branch_list_builder.go create mode 100644 colorer.go rename {bin => scripts}/push_new_patch.go (100%) create mode 100644 utils.go diff --git a/branch.go b/branch.go new file mode 100644 index 000000000..382d25bbc --- /dev/null +++ b/branch.go @@ -0,0 +1,42 @@ +package main + +import ( + "strings" + + "github.com/fatih/color" +) + +// Branch : A git branch +type Branch struct { + Name string + Recency string +} + +func (b *Branch) getDisplayString() string { + return withPadding(b.Recency, 4) + coloredString(b.Name, b.getColor()) +} + +func (b *Branch) getColor() color.Attribute { + switch b.getType() { + case "feature": + return color.FgGreen + case "bugfix": + return color.FgYellow + case "hotfix": + return color.FgRed + default: + return color.FgWhite + } +} + +// expected to return feature/bugfix/hotfix or blank string +func (b *Branch) getType() string { + return strings.Split(b.Name, "/")[0] +} + +func withPadding(str string, padding int) string { + if padding-len(str) < 0 { + return str + } + return str + strings.Repeat(" ", padding-len(str)) +} diff --git a/branch_list_builder.go b/branch_list_builder.go new file mode 100644 index 000000000..fdd88c850 --- /dev/null +++ b/branch_list_builder.go @@ -0,0 +1,122 @@ +package main + +import ( + "regexp" + "strings" + + "gopkg.in/src-d/go-git.v4/plumbing" +) + +// context: +// we want to only show 'safe' branches (ones that haven't e.g. been deleted) +// which `git branch -a` gives us, but we also want the recency data that +// git reflog gives us. +// So we get the HEAD, then append get the reflog branches that intersect with +// our safe branches, then add the remaining safe branches, ensuring uniqueness +// along the way + +type branchListBuilder struct{} + +func newBranchListBuilder() *branchListBuilder { + return &branchListBuilder{} +} + +func (b *branchListBuilder) obtainCurrentBranch() Branch { + // Using git-go whenever possible + head, err := r.Head() + if err != nil { + panic(err) + } + name := head.Name().Short() + return Branch{Name: name, Recency: " *"} +} + +func (*branchListBuilder) obtainReflogBranches() []Branch { + branches := make([]Branch, 0) + rawString, err := runDirectCommand("git reflog -n100 --pretty='%cr|%gs' --grep-reflog='checkout: moving' HEAD") + if err != nil { + return branches + } + + branchLines := splitLines(rawString) + for _, line := range branchLines { + timeNumber, timeUnit, branchName := branchInfoFromLine(line) + timeUnit = abbreviatedTimeUnit(timeUnit) + branch := Branch{Name: branchName, Recency: timeNumber + timeUnit} + branches = append(branches, branch) + } + return branches +} + +func (b *branchListBuilder) obtainSafeBranches() []Branch { + branches := make([]Branch, 0) + + bIter, err := r.Branches() + if err != nil { + panic(err) + } + err = bIter.ForEach(func(b *plumbing.Reference) error { + name := b.Name().Short() + branches = append(branches, Branch{Name: name}) + return nil + }) + + return branches +} + +func (b *branchListBuilder) appendNewBranches(finalBranches, newBranches, existingBranches []Branch, included bool) []Branch { + for _, newBranch := range newBranches { + if included == branchIncluded(newBranch.Name, existingBranches) { + finalBranches = append(finalBranches, newBranch) + } + + } + return finalBranches +} + +func (b *branchListBuilder) build() []Branch { + branches := make([]Branch, 0) + head := b.obtainCurrentBranch() + validBranches := b.obtainSafeBranches() + reflogBranches := uniqueByName(append(b.obtainReflogBranches(), head)) + + branches = b.appendNewBranches(branches, reflogBranches, validBranches, true) + branches = b.appendNewBranches(branches, validBranches, branches, false) + + return branches +} + +func uniqueByName(branches []Branch) []Branch { + finalBranches := make([]Branch, 0) + for _, branch := range branches { + if branchIncluded(branch.Name, finalBranches) { + continue + } + finalBranches = append(finalBranches, branch) + } + return finalBranches +} + +// A line will have the form '10 days ago master' so we need to strip out the +// useful information from that into timeNumber, timeUnit, and branchName +func branchInfoFromLine(line string) (string, string, string) { + r := regexp.MustCompile("\\|.*\\s") + line = r.ReplaceAllString(line, " ") + words := strings.Split(line, " ") + return words[0], words[1], words[3] +} + +func abbreviatedTimeUnit(timeUnit string) string { + r := regexp.MustCompile("s$") + timeUnit = r.ReplaceAllString(timeUnit, "") + timeUnitMap := map[string]string{ + "hour": "h", + "minute": "m", + "second": "s", + "week": "w", + "year": "y", + "day": "d", + "month": "m", + } + return timeUnitMap[timeUnit] +} diff --git a/branches_panel.go b/branches_panel.go index 0b8508a3d..3102f0c28 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -91,7 +91,7 @@ func handleBranchSelect(g *gocui.Gui, v *gocui.View) error { } go func() { branch := getSelectedBranch(v) - diff, err := getBranchGraph(branch.Name, branch.BaseBranch) + diff, err := getBranchGraph(branch.Name) if err != nil && strings.HasPrefix(diff, "fatal: ambiguous argument") { diff = "There is no tracking for this branch" } @@ -111,7 +111,7 @@ func refreshBranches(g *gocui.Gui) error { state.Branches = getGitBranches() v.Clear() for _, branch := range state.Branches { - fmt.Fprintln(v, branch.DisplayString) + fmt.Fprintln(v, branch.getDisplayString()) } resetOrigin(v) return refreshStatus(g) diff --git a/colorer.go b/colorer.go new file mode 100644 index 000000000..2b9142264 --- /dev/null +++ b/colorer.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + + "github.com/fatih/color" +) + +func coloredString(str string, colorAttribute color.Attribute) string { + colour := color.New(colorAttribute) + return coloredStringDirect(str, colour) +} + +// used for aggregating a few color attributes rather than just sending a single one +func coloredStringDirect(str string, colour *color.Color) string { + return colour.SprintFunc()(fmt.Sprint(str)) +} diff --git a/gitcommands.go b/gitcommands.go index fbe8ddae5..2e0ad011f 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -7,11 +7,9 @@ import ( "fmt" "os" "os/exec" - "regexp" "strings" "time" - "github.com/fatih/color" "github.com/jesseduffield/gocui" gitconfig "github.com/tcnksm/go-gitconfig" git "gopkg.in/src-d/go-git.v4" @@ -19,9 +17,6 @@ import ( ) var ( - // ErrNoCheckedOutBranch : When we have no checked out branch - ErrNoCheckedOutBranch = errors.New("No currently checked out branch") - // ErrNoOpenCommand : When we don't know which command to use to open a file ErrNoOpenCommand = errors.New("Unsure what command to use to open this file") ) @@ -38,14 +33,6 @@ type GitFile struct { DisplayString string } -// Branch : A git branch -type Branch struct { - Name string - Type string - BaseBranch string - DisplayString string -} - // Commit : A git commit type Commit struct { Sha string @@ -140,29 +127,6 @@ func branchStringParts(branchString string) (string, string) { return splitBranchName[0], splitBranchName[1] } -// branchPropertiesFromName : returns branch type, base, and color -func branchPropertiesFromName(name string) (string, string, color.Attribute) { - if strings.Contains(name, "feature/") { - return "feature", "develop", color.FgGreen - } else if strings.Contains(name, "bugfix/") { - return "bugfix", "develop", color.FgYellow - } else if strings.Contains(name, "hotfix/") { - return "hotfix", "master", color.FgRed - } - return "other", name, color.FgWhite -} - -func coloredString(str string, colour *color.Color) string { - return colour.SprintFunc()(fmt.Sprint(str)) -} - -func withPadding(str string, padding int) string { - if padding-len(str) < 0 { - return str - } - return str + strings.Repeat(" ", padding-len(str)) -} - // TODO: DRY up this function and getGitBranches func getGitStashEntries() []StashEntry { stashEntries := make([]StashEntry, 0) @@ -214,10 +178,6 @@ func getGitStatusFiles() []GitFile { Deleted: unstagedChange == "D" || stagedChange == "D", HasMergeConflicts: change == "UU", } - devLog("tracked", gitFile.Tracked) - devLog("hasUnstagedChanges", gitFile.HasUnstagedChanges) - devLog("HasStagedChanges", gitFile.HasStagedChanges) - devLog("DisplayString", gitFile.DisplayString) gitFiles = append(gitFiles, gitFile) } devLog(gitFiles) @@ -328,12 +288,8 @@ func runSubProcess(g *gocui.Gui, cmdName string, commandArgs ...string) { }) } -func getBranchGraph(branch string, baseBranch string) (string, error) { +func getBranchGraph(branch string) (string, error) { return runCommand("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 " + branch) - - // Leaving this guy commented out in case there's backlash from the design - // change and I want to make this configurable - // return runCommand("git log -p -30 --color --no-merges " + branch) } func verifyInGitRepo() { @@ -480,11 +436,7 @@ func gitPull() (string, error) { } func gitPush() (string, error) { - branchName := gitCurrentBranchName() - if branchName == "" { - return "", ErrNoCheckedOutBranch - } - return runDirectCommand("git push -u origin " + branchName) + return runDirectCommand("git push -u origin " + state.Branches[0].Name) } func gitSquashPreviousTwoCommits(message string) (string, error) { @@ -539,91 +491,12 @@ func gitCommitsToPush() []string { return splitLines(pushables) } -func gitCurrentBranchName() string { - branchName, err := runDirectCommand("git symbolic-ref --short HEAD") - // if there is an error, assume there are no branches yet - if err != nil { - return "" - } - return strings.TrimSpace(branchName) -} - -// A line will have the form '10 days ago master' so we need to strip out the -// useful information from that into timeNumber, timeUnit, and branchName -func branchInfoFromLine(line string) (string, string, string) { - r := regexp.MustCompile("\\|.*\\s") - line = r.ReplaceAllString(line, " ") - words := strings.Split(line, " ") - return words[0], words[1], words[3] -} - -func abbreviatedTimeUnit(timeUnit string) string { - r := regexp.MustCompile("s$") - timeUnit = r.ReplaceAllString(timeUnit, "") - timeUnitMap := map[string]string{ - "hour": "h", - "minute": "m", - "second": "s", - "week": "w", - "year": "y", - "day": "d", - "month": "m", - } - return timeUnitMap[timeUnit] -} - -func getBranches() []Branch { - branches := make([]Branch, 0) - rawString, err := runDirectCommand("git reflog -n100 --pretty='%cr|%gs' --grep-reflog='checkout: moving' HEAD") - if err != nil { - return branches - } - - branchLines := splitLines(rawString) - for i, line := range branchLines { - timeNumber, timeUnit, branchName := branchInfoFromLine(line) - timeUnit = abbreviatedTimeUnit(timeUnit) - - if branchAlreadyStored(branchName, branches) { - continue - } - - branch := constructBranch(timeNumber+timeUnit, branchName, i) - branches = append(branches, branch) - } - return branches -} - -func constructBranch(prefix, name string, index int) Branch { - branchType, branchBase, colourAttr := branchPropertiesFromName(name) - if index == 0 { - prefix = " *" - } - colour := color.New(colourAttr) - displayString := withPadding(prefix, 4) + coloredString(name, colour) - return Branch{ - Name: name, - Type: branchType, - BaseBranch: branchBase, - DisplayString: displayString, - } -} - func getGitBranches() []Branch { - // check if there are any branches - branchCheck, _ := runCommand("git branch") - if branchCheck == "" { - return []Branch{constructBranch("", gitCurrentBranchName(), 0)} - } - branches := getBranches() - if len(branches) == 0 { - branches = append(branches, constructBranch("", gitCurrentBranchName(), 0)) - } - branches = getAndMergeFetchedBranches(branches) - return branches + builder := newBranchListBuilder() + return builder.build() } -func branchAlreadyStored(branchName string, branches []Branch) bool { +func branchIncluded(branchName string, branches []Branch) bool { for _, existingBranch := range branches { if existingBranch.Name == branchName { return true @@ -632,27 +505,6 @@ func branchAlreadyStored(branchName string, branches []Branch) bool { return false } -// here branches contains all the branches that we've checked out, along with -// the recency. In this function we append the branches that are in our heads -// directory i.e. things we've fetched but haven't necessarily checked out. -// Worth mentioning this has nothing to do with the 'git merge' operation -func getAndMergeFetchedBranches(branches []Branch) []Branch { - rawString, err := runDirectCommand("git branch --sort=-committerdate --no-color") - if err != nil { - return branches - } - branchLines := splitLines(rawString) - for _, line := range branchLines { - line = strings.Replace(line, "* ", "", -1) - line = strings.TrimSpace(line) - if branchAlreadyStored(line, branches) { - continue - } - branches = append(branches, constructBranch("", line, len(branches))) - } - return branches -} - func gitResetHard() error { return w.Reset(&git.ResetOptions{Mode: git.HardReset}) } diff --git a/gui.go b/gui.go index 4d5d0b679..af1b07a93 100644 --- a/gui.go +++ b/gui.go @@ -261,6 +261,8 @@ func run() (err error) { } defer g.Close() + g.FgColor = gocui.ColorMagenta + goEvery(g, time.Second*60, fetch) goEvery(g, time.Second*10, refreshFiles) goEvery(g, time.Millisecond*10, updateLoader) diff --git a/main.go b/main.go index c918c7348..c36ca468b 100644 --- a/main.go +++ b/main.go @@ -28,6 +28,7 @@ var ( versionFlag = flag.Bool("v", false, "Print the current version") w *git.Worktree + r *git.Repository ) func homeDirectory() string { @@ -88,7 +89,8 @@ func fallbackVersion() string { } func setupWorktree() { - r, err := git.PlainOpen(".") + var err error + r, err = git.PlainOpen(".") if err != nil { panic(err) } diff --git a/merge_panel.go b/merge_panel.go index 6602dbbf1..f5ca12a23 100644 --- a/merge_panel.go +++ b/merge_panel.go @@ -56,7 +56,7 @@ func coloredConflictFile(content string, conflicts []conflict, conflictIndex int if i == conflict.end && len(remainingConflicts) > 0 { conflict, remainingConflicts = shiftConflict(remainingConflicts) } - outputBuffer.WriteString(coloredString(line, colour) + "\n") + outputBuffer.WriteString(coloredStringDirect(line, colour) + "\n") } return outputBuffer.String(), nil } diff --git a/bin/push_new_patch.go b/scripts/push_new_patch.go similarity index 100% rename from bin/push_new_patch.go rename to scripts/push_new_patch.go diff --git a/status_panel.go b/status_panel.go index 393c62344..46bc394ae 100644 --- a/status_panel.go +++ b/status_panel.go @@ -24,16 +24,15 @@ func refreshStatus(g *gocui.Gui) error { return err } if state.HasMergeConflicts { - colour := color.New(color.FgYellow) - fmt.Fprint(v, coloredString(" (merging)", colour)) + fmt.Fprint(v, coloredString(" (merging)", color.FgYellow)) } + if len(branches) == 0 { return nil } branch := branches[0] - // utilising the fact these all have padding to only grab the name - // from the display string with the existing coloring applied - fmt.Fprint(v, " "+branch.DisplayString[4:]) + name := coloredString(branch.Name, branch.getColor()) + fmt.Fprint(v, " "+name) return nil }) diff --git a/utils.go b/utils.go new file mode 100644 index 000000000..2b9671eb1 --- /dev/null +++ b/utils.go @@ -0,0 +1,23 @@ +package main + +import ( + "strings" + + "github.com/jesseduffield/gocui" +) + +func splitLines(multilineString string) []string { + multilineString = strings.Replace(multilineString, "\r", "", -1) + if multilineString == "" || multilineString == "\n" { + return make([]string, 0) + } + lines := strings.Split(multilineString, "\n") + if lines[len(lines)-1] == "" { + return lines[:len(lines)-1] + } + return lines +} + +func trimmedContent(v *gocui.View) string { + return strings.TrimSpace(v.Buffer()) +} diff --git a/view_helpers.go b/view_helpers.go index bb8b86da7..2f5f2caf0 100644 --- a/view_helpers.go +++ b/view_helpers.go @@ -121,10 +121,6 @@ func getItemPosition(v *gocui.View) int { return oy + cy } -func trimmedContent(v *gocui.View) string { - return strings.TrimSpace(v.Buffer()) -} - func cursorUp(g *gocui.Gui, v *gocui.View) error { // swallowing cursor movements in main // TODO: pull this out @@ -199,18 +195,6 @@ func renderString(g *gocui.Gui, viewName, s string) error { return nil } -func splitLines(multilineString string) []string { - multilineString = strings.Replace(multilineString, "\r", "", -1) - if multilineString == "" || multilineString == "\n" { - return make([]string, 0) - } - lines := strings.Split(multilineString, "\n") - if lines[len(lines)-1] == "" { - return lines[:len(lines)-1] - } - return lines -} - func optionsMapToString(optionsMap map[string]string) string { optionsArray := make([]string, 0) for key, description := range optionsMap { From c470c1f575eee8f8b3a7dc8a39297c32d6dc3abb Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 21:38:51 +1000 Subject: [PATCH 06/36] keep asterisk at the checked out branch --- branch_list_builder.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/branch_list_builder.go b/branch_list_builder.go index fdd88c850..5393bea3e 100644 --- a/branch_list_builder.go +++ b/branch_list_builder.go @@ -78,7 +78,8 @@ func (b *branchListBuilder) build() []Branch { branches := make([]Branch, 0) head := b.obtainCurrentBranch() validBranches := b.obtainSafeBranches() - reflogBranches := uniqueByName(append(b.obtainReflogBranches(), head)) + reflogBranches := b.obtainReflogBranches() + reflogBranches = uniqueByName(append([]Branch{head}, reflogBranches...)) branches = b.appendNewBranches(branches, reflogBranches, validBranches, true) branches = b.appendNewBranches(branches, validBranches, branches, false) From 1fded005c4e63724ca2e5e7d4239db391834fc36 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 21:40:21 +1000 Subject: [PATCH 07/36] revert to using default border color --- gui.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui.go b/gui.go index af1b07a93..4cf7d7df5 100644 --- a/gui.go +++ b/gui.go @@ -261,7 +261,7 @@ func run() (err error) { } defer g.Close() - g.FgColor = gocui.ColorMagenta + g.FgColor = gocui.ColorDefault goEvery(g, time.Second*60, fetch) goEvery(g, time.Second*10, refreshFiles) From eb9f01ecfa6bf509833ada9f1aef0700d54af393 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 21:51:21 +1000 Subject: [PATCH 08/36] move withPadding into utils file --- branch.go | 7 ------- utils.go | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/branch.go b/branch.go index 382d25bbc..78c2e55aa 100644 --- a/branch.go +++ b/branch.go @@ -33,10 +33,3 @@ func (b *Branch) getColor() color.Attribute { func (b *Branch) getType() string { return strings.Split(b.Name, "/")[0] } - -func withPadding(str string, padding int) string { - if padding-len(str) < 0 { - return str - } - return str + strings.Repeat(" ", padding-len(str)) -} diff --git a/utils.go b/utils.go index 2b9671eb1..08d27806d 100644 --- a/utils.go +++ b/utils.go @@ -21,3 +21,10 @@ func splitLines(multilineString string) []string { func trimmedContent(v *gocui.View) string { return strings.TrimSpace(v.Buffer()) } + +func withPadding(str string, padding int) string { + if padding-len(str) < 0 { + return str + } + return str + strings.Repeat(" ", padding-len(str)) +} From 95b7c1d0a45503fc327f474714142bc0077c1a0c Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 22:08:12 +1000 Subject: [PATCH 09/36] revert to using the direct git command for getting the current branch because it breaks if you've just done a git init --- branch_list_builder.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/branch_list_builder.go b/branch_list_builder.go index 5393bea3e..113a5a44a 100644 --- a/branch_list_builder.go +++ b/branch_list_builder.go @@ -22,13 +22,10 @@ func newBranchListBuilder() *branchListBuilder { } func (b *branchListBuilder) obtainCurrentBranch() Branch { - // Using git-go whenever possible - head, err := r.Head() - if err != nil { - panic(err) - } - name := head.Name().Short() - return Branch{Name: name, Recency: " *"} + // I used go-git for this, but that breaks if you've just done a git init, + // even though you're on 'master' + branchName, _ := runDirectCommand("git symbolic-ref --short HEAD") + return Branch{Name: strings.TrimSpace(branchName), Recency: " *"} } func (*branchListBuilder) obtainReflogBranches() []Branch { @@ -77,12 +74,15 @@ func (b *branchListBuilder) appendNewBranches(finalBranches, newBranches, existi func (b *branchListBuilder) build() []Branch { branches := make([]Branch, 0) head := b.obtainCurrentBranch() - validBranches := b.obtainSafeBranches() + safeBranches := b.obtainSafeBranches() + if len(safeBranches) == 0 { + return append(branches, head) + } reflogBranches := b.obtainReflogBranches() reflogBranches = uniqueByName(append([]Branch{head}, reflogBranches...)) - branches = b.appendNewBranches(branches, reflogBranches, validBranches, true) - branches = b.appendNewBranches(branches, validBranches, branches, false) + branches = b.appendNewBranches(branches, reflogBranches, safeBranches, true) + branches = b.appendNewBranches(branches, safeBranches, branches, false) return branches } From 28505dddaf221cdd05f3a044f58ced49f132a5e1 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 22:09:10 +1000 Subject: [PATCH 10/36] move color functions into utils --- colorer.go | 17 ----------------- utils.go | 12 ++++++++++++ 2 files changed, 12 insertions(+), 17 deletions(-) delete mode 100644 colorer.go diff --git a/colorer.go b/colorer.go deleted file mode 100644 index 2b9142264..000000000 --- a/colorer.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/fatih/color" -) - -func coloredString(str string, colorAttribute color.Attribute) string { - colour := color.New(colorAttribute) - return coloredStringDirect(str, colour) -} - -// used for aggregating a few color attributes rather than just sending a single one -func coloredStringDirect(str string, colour *color.Color) string { - return colour.SprintFunc()(fmt.Sprint(str)) -} diff --git a/utils.go b/utils.go index 08d27806d..1ab5a9ed2 100644 --- a/utils.go +++ b/utils.go @@ -1,8 +1,10 @@ package main import ( + "fmt" "strings" + "github.com/fatih/color" "github.com/jesseduffield/gocui" ) @@ -28,3 +30,13 @@ func withPadding(str string, padding int) string { } return str + strings.Repeat(" ", padding-len(str)) } + +func coloredString(str string, colorAttribute color.Attribute) string { + colour := color.New(colorAttribute) + return coloredStringDirect(str, colour) +} + +// used for aggregating a few color attributes rather than just sending a single one +func coloredStringDirect(str string, colour *color.Color) string { + return colour.SprintFunc()(fmt.Sprint(str)) +} From 59650cff2644e8e7f3b1c77ade4145c886aa6f73 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 22:24:10 +1000 Subject: [PATCH 11/36] compare branches for name equality regardless of case --- gitcommands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitcommands.go b/gitcommands.go index 2e0ad011f..2d073aec9 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -498,7 +498,7 @@ func getGitBranches() []Branch { func branchIncluded(branchName string, branches []Branch) bool { for _, existingBranch := range branches { - if existingBranch.Name == branchName { + if strings.ToLower(existingBranch.Name) == strings.ToLower(branchName) { return true } } From 4853d186ee48e4769cb8102a2b4b8d801ea2537e Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 22:46:04 +1000 Subject: [PATCH 12/36] add git plumbing to Gopkg.lock --- Gopkg.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Gopkg.lock b/Gopkg.lock index 65f765807..f0eeb5c47 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -279,6 +279,7 @@ "github.com/jesseduffield/gocui", "github.com/tcnksm/go-gitconfig", "gopkg.in/src-d/go-git.v4", + "gopkg.in/src-d/go-git.v4/plumbing", "gopkg.in/src-d/go-git.v4/plumbing/object", ] solver-name = "gps-cdcl" From aa4160d57ae460a7735fb2beb2ab7904151de50e Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 22:49:54 +1000 Subject: [PATCH 13/36] merge feature/clearing-commit-panel into master --- branches_panel.go | 4 ++-- commits_panel.go | 2 +- confirmation_panel.go | 17 ++++++++++++++--- files_panel.go | 7 ++++--- stash_panel.go | 2 +- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/branches_panel.go b/branches_panel.go index 3102f0c28..00091ffb8 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -30,7 +30,7 @@ func handleForceCheckout(g *gocui.Gui, v *gocui.View) error { } func handleCheckoutByName(g *gocui.Gui, v *gocui.View) error { - createPromptPanel(g, v, "Branch Name:", func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "Branch Name:", nil, func(g *gocui.Gui, v *gocui.View) error { if output, err := gitCheckout(trimmedContent(v), false); err != nil { return createErrorPanel(g, output) } @@ -41,7 +41,7 @@ func handleCheckoutByName(g *gocui.Gui, v *gocui.View) error { func handleNewBranch(g *gocui.Gui, v *gocui.View) error { branch := state.Branches[0] - createPromptPanel(g, v, "New Branch Name (Branch is off of "+branch.Name+")", func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "New Branch Name (Branch is off of "+branch.Name+")", nil, func(g *gocui.Gui, v *gocui.View) error { if output, err := gitNewBranch(trimmedContent(v)); err != nil { return createErrorPanel(g, output) } diff --git a/commits_panel.go b/commits_panel.go index 88c7b8ebe..e8ff68678 100644 --- a/commits_panel.go +++ b/commits_panel.go @@ -109,7 +109,7 @@ func handleRenameCommit(g *gocui.Gui, v *gocui.View) error { if getItemPosition(v) != 0 { return createErrorPanel(g, "Can only rename topmost commit") } - createPromptPanel(g, v, "Rename Commit", func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "Rename Commit", nil, func(g *gocui.Gui, v *gocui.View) error { if output, err := gitRenameCommit(v.Buffer()); err != nil { return createErrorPanel(g, output) } diff --git a/confirmation_panel.go b/confirmation_panel.go index 362b75c49..520c8b593 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -55,7 +55,7 @@ func getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, height/2 + panelHeight/2 } -func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, handleConfirm func(*gocui.Gui, *gocui.View) error) error { +func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, initialValue *[]byte, handleConfirm func(*gocui.Gui, *gocui.View) error) error { // only need to fit one line x0, y0, x1, y1 := getConfirmationPanelDimensions(g, "") if confirmationView, err := g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { @@ -65,11 +65,22 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, hand g.Cursor = true + handleConfirmAndClear := func(gui *gocui.Gui, view *gocui.View) error { + *initialValue = nil + return handleConfirm(g, view) + } + + handleClose := func(gui *gocui.Gui, view *gocui.View) error { + *initialValue = []byte(strings.TrimSpace(view.Buffer())) + return nil + } + confirmationView.Editable = true confirmationView.Title = title - confirmationView.FgColor = gocui.ColorWhite + confirmationView.Write(*initialValue) + confirmationView.SetCursor(len(*initialValue), 0) switchFocus(g, currentView, confirmationView) - return setKeyBindings(g, handleConfirm, nil) + return setKeyBindings(g, handleConfirmAndClear, handleClose) } return nil } diff --git a/files_panel.go b/files_panel.go index 32ed36ad4..b2de2c226 100644 --- a/files_panel.go +++ b/files_panel.go @@ -15,8 +15,9 @@ import ( ) var ( - errNoFiles = errors.New("No changed files") - errNoUsername = errors.New(`No username set. Please do: git config --global user.name "Your Name"`) + savedCommitMessage = &[]byte{} + errNoFiles = errors.New("No changed files") + errNoUsername = errors.New(`No username set. Please do: git config --global user.name "Your Name"`) ) func stagedFiles(files []GitFile) []GitFile { @@ -177,7 +178,7 @@ func handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { if len(stagedFiles(state.GitFiles)) == 0 && !state.HasMergeConflicts { return createErrorPanel(g, "There are no staged files to commit") } - createPromptPanel(g, filesView, "Commit message", func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, filesView, "Commit message", savedCommitMessage, func(g *gocui.Gui, v *gocui.View) error { message := trimmedContent(v) if message == "" { return createErrorPanel(g, "You cannot commit without a commit message") diff --git a/stash_panel.go b/stash_panel.go index 33c7e297b..a4a2207d8 100644 --- a/stash_panel.go +++ b/stash_panel.go @@ -82,7 +82,7 @@ func stashDo(g *gocui.Gui, v *gocui.View, method string) error { } func handleStashSave(g *gocui.Gui, filesView *gocui.View) error { - createPromptPanel(g, filesView, "Stash changes", func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, filesView, "Stash changes", nil, func(g *gocui.Gui, v *gocui.View) error { if output, err := gitStashSave(trimmedContent(v)); err != nil { createErrorPanel(g, output) } From f20121cb0bca9355d6a08d8d8153b2a34ccf5120 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 23:08:03 +1000 Subject: [PATCH 14/36] add FIXME note about trimming the trailing newline upon confirming in a prompt panel --- confirmation_panel.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/confirmation_panel.go b/confirmation_panel.go index 520c8b593..7ae55eaf9 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -71,6 +71,8 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, init } handleClose := func(gui *gocui.Gui, view *gocui.View) error { + // FIXME: trimming a newline that is no doubt caused by the enter keybinding + // on the editor. We should just define a new editor that doesn't do that *initialValue = []byte(strings.TrimSpace(view.Buffer())) return nil } From 7eb673e574debea04f46bfc50d4a2fdf9fa6aebe Mon Sep 17 00:00:00 2001 From: Glenn Vriesman Date: Fri, 10 Aug 2018 15:10:15 +0200 Subject: [PATCH 15/36] Feature: Added repository name to status --- status_panel.go | 3 ++- utils.go | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/status_panel.go b/status_panel.go index 46bc394ae..f3fcb8078 100644 --- a/status_panel.go +++ b/status_panel.go @@ -32,7 +32,8 @@ func refreshStatus(g *gocui.Gui) error { } branch := branches[0] name := coloredString(branch.Name, branch.getColor()) - fmt.Fprint(v, " "+name) + repo := getCurrentProject() + fmt.Fprint(v, " "+repo+" → "+name) return nil }) diff --git a/utils.go b/utils.go index 1ab5a9ed2..e2de46233 100644 --- a/utils.go +++ b/utils.go @@ -2,6 +2,9 @@ package main import ( "fmt" + "log" + "os" + "path/filepath" "strings" "github.com/fatih/color" @@ -40,3 +43,12 @@ func coloredString(str string, colorAttribute color.Attribute) string { func coloredStringDirect(str string, colour *color.Color) string { return colour.SprintFunc()(fmt.Sprint(str)) } + +// used to get the project name +func getCurrentProject() string { + pwd, err := os.Getwd() + if err != nil { + log.Fatalln(err.Error()) + } + return filepath.Base(pwd) +} From 7aa884ed8f19eacb03a5ee28baba989783746706 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 10 Aug 2018 23:36:54 +1000 Subject: [PATCH 16/36] step one on restoring multiline commits --- confirmation_panel.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/confirmation_panel.go b/confirmation_panel.go index 7ae55eaf9..c82b6b65b 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -56,6 +56,9 @@ func getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, } func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, initialValue *[]byte, handleConfirm func(*gocui.Gui, *gocui.View) error) error { + if initialValue == nil { + initialValue = &[]byte{} + } // only need to fit one line x0, y0, x1, y1 := getConfirmationPanelDimensions(g, "") if confirmationView, err := g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { @@ -79,14 +82,29 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, init confirmationView.Editable = true confirmationView.Title = title - confirmationView.Write(*initialValue) - confirmationView.SetCursor(len(*initialValue), 0) + restorePreviousBuffer(confirmationView, initialValue) switchFocus(g, currentView, confirmationView) return setKeyBindings(g, handleConfirmAndClear, handleClose) } return nil } +func restorePreviousBuffer(confirmationView *gocui.View, initialValue *[]byte) { + confirmationView.Write(*initialValue) + x, y := getCursorPositionFromBuffer(initialValue) + devLog("New cursor position:", x, y) + confirmationView.SetCursor(0, 0) + confirmationView.MoveCursor(x, y, false) +} + +func getCursorPositionFromBuffer(initialValue *[]byte) (int, int) { + split := strings.Split(string(*initialValue), "\n") + lastLine := split[len(split)-1] + x := len(lastLine) + y := len(split) + return x, y +} + func createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error { g.Update(func(g *gocui.Gui) error { // delete the existing confirmation panel if it exists From 48cea4e1c43d6a191062d33bf8b5cc9ecef3e528 Mon Sep 17 00:00:00 2001 From: Hubert Baumgartner Date: Fri, 10 Aug 2018 16:46:03 +0200 Subject: [PATCH 17/36] added branch delete functionallity --- branches_panel.go | 10 ++++++++++ docs/Keybindings.md | 1 + gitcommands.go | 4 ++++ keybindings.go | 1 + 4 files changed, 16 insertions(+) diff --git a/branches_panel.go b/branches_panel.go index 00091ffb8..968096610 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -51,6 +51,15 @@ func handleNewBranch(g *gocui.Gui, v *gocui.View) error { return nil } +func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { + branch := getSelectedBranch(v) + if output, err := gitDeleteBranch(branch.Name); err != nil { + return createErrorPanel(g, output) + } + return refreshSidePanels(g) +} + + func handleMerge(g *gocui.Gui, v *gocui.View) error { checkedOutBranch := state.Branches[0] selectedBranch := getSelectedBranch(v) @@ -76,6 +85,7 @@ func renderBranchesOptions(g *gocui.Gui) error { "m": "merge", "c": "checkout by name", "n": "new branch", + "d": "delte branch", "← → ↑ ↓": "navigate", }) } diff --git a/docs/Keybindings.md b/docs/Keybindings.md index cefafeba5..c46960676 100644 --- a/docs/Keybindings.md +++ b/docs/Keybindings.md @@ -29,6 +29,7 @@ m: merge into currently checked out branch c: checkout by name n: new branch + d: delete branch ## Commits Panel: diff --git a/gitcommands.go b/gitcommands.go index 2d073aec9..2c68f561e 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -459,6 +459,10 @@ func gitNewBranch(name string) (string, error) { return runDirectCommand("git checkout -b " + name) } +func gitDeleteBranch(branch string) (string, error) { + return runCommand("git branch -d " + branch) +} + func gitListStash() (string, error) { return runDirectCommand("git stash list") } diff --git a/keybindings.go b/keybindings.go index 07309790f..d68c6c5a6 100644 --- a/keybindings.go +++ b/keybindings.go @@ -51,6 +51,7 @@ func keybindings(g *gocui.Gui) error { {ViewName: "branches", Key: 'c', Modifier: gocui.ModNone, Handler: handleCheckoutByName}, {ViewName: "branches", Key: 'F', Modifier: gocui.ModNone, Handler: handleForceCheckout}, {ViewName: "branches", Key: 'n', Modifier: gocui.ModNone, Handler: handleNewBranch}, + {ViewName: "branches", Key: 'd', Modifier: gocui.ModNone, Handler: handleDeleteBranch}, {ViewName: "branches", Key: 'm', Modifier: gocui.ModNone, Handler: handleMerge}, {ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, {ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, From bfa47d3b91d930697d3c6318bfc29f171475b543 Mon Sep 17 00:00:00 2001 From: Hubert Baumgartner Date: Fri, 10 Aug 2018 20:19:12 +0200 Subject: [PATCH 18/36] extenden delete branch with error message and confirmation --- branches_panel.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/branches_panel.go b/branches_panel.go index 968096610..0327b576e 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -51,12 +51,18 @@ func handleNewBranch(g *gocui.Gui, v *gocui.View) error { return nil } -func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { - branch := getSelectedBranch(v) - if output, err := gitDeleteBranch(branch.Name); err != nil { +func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { + checkedOutBranch := state.Branches[0] + selectedBranch := getSelectedBranch(v) + if checkedOutBranch.Name == selectedBranch.Name { + return createErrorPanel(g, "You cannot delete the checked out branch!") + } + return createConfirmationPanel(g, v, "Delete Branch", "Are you sure you want delete the branch "+selectedBranch.Name+" ?", func(g *gocui.Gui, v *gocui.View) error { + if output, err := gitDeleteBranch(selectedBranch.Name); err != nil { return createErrorPanel(g, output) } return refreshSidePanels(g) + }, nil) } From 1ef794e09f2bbdee7364a1738801e1a4eee78421 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 09:43:22 +1000 Subject: [PATCH 19/36] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 0bd9b310f..9449977cd 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Are YOU tired of typing every git command directly into the terminal, but you're ![Gif](https://image.ibb.co/mmeXho/optimisedgif.gif) +[Twitch Stream](https://www.twitch.tv/jesseduffield) + ## Installation ### Homebrew @@ -74,3 +76,6 @@ We love your input! Please check out the [contributing guide](CONTRIBUTING.md). ## Work in progress This is still a work in progress so there's still bugs to iron out and as this is my first project in Go the code could no doubt use an increase in quality, but I'll be improving on it whenever I find the time. If you have any feedback feel free to [raise an issue](https://github.com/jesseduffield/lazygit/issues)/[submit a PR](https://github.com/jesseduffield/lazygit/pulls). + +## Social +If you want to see what I (Jesse) am up to in terms of development, follow me on [twitter](https://twitter.com/DuffieldJesse) or watch me program on [twitch](https://www.twitch.tv/jesseduffield) From 542fd8e88a06ccb7676611d2c95004879436bc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredy=20Alberto=20Garc=C3=ADa=20G=C3=BCiza?= Date: Fri, 10 Aug 2018 19:47:16 -0500 Subject: [PATCH 20/36] Fixing grammar about arch linux packages in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index daf8f633c..7f082abd0 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ sudo apt-get install lazygit ### Arch Linux Packages for Arch Linux are available via AUR (Arch User Repository). -There are two packages. The stable which is built with the last releases and the git version which takes the last commit and build based on. +There are two packages. The stable one which is built with the latest release and the git version which builds from the most recent commit. Stable: https://aur.archlinux.org/packages/lazygit/ From b2fbccd39233feddf5543dd57c6f04533895cdb2 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 12:35:17 +1000 Subject: [PATCH 21/36] remove time logging --- ZHgalGrWSF | 1 + gitcommands.go | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 ZHgalGrWSF diff --git a/ZHgalGrWSF b/ZHgalGrWSF new file mode 100644 index 000000000..f1f0d2371 --- /dev/null +++ b/ZHgalGrWSF @@ -0,0 +1 @@ +GaUMygWjJa \ No newline at end of file diff --git a/gitcommands.go b/gitcommands.go index 2d073aec9..7c1ec84bd 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -107,13 +107,11 @@ func mergeGitStatusFiles(oldGitFiles, newGitFiles []GitFile) []GitFile { } func runDirectCommand(command string) (string, error) { - timeStart := time.Now() commandLog(command) cmdOut, err := exec. Command(state.Platform.shell, state.Platform.shellArg, command). CombinedOutput() - devLog("run direct command time for command: ", command, time.Now().Sub(timeStart)) return sanitisedCommandOutput(cmdOut, err) } @@ -218,12 +216,10 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { } func runCommand(command string) (string, error) { - commandStartTime := time.Now() commandLog(command) splitCmd := strings.Split(command, " ") devLog(splitCmd) cmdOut, err := exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput() - devLog("run command time: ", time.Now().Sub(commandStartTime)) return sanitisedCommandOutput(cmdOut, err) } From 3b018e040fa023bf64f84e5f57ed7f5440b94830 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 13:17:20 +1000 Subject: [PATCH 22/36] make commit messages multilined and add ability save commit message between edits --- commit_message_panel.go | 42 +++++++++++++++++++++++++++++++++++++++++ confirmation_panel.go | 21 +++++++++++++-------- files_panel.go | 23 +++++++--------------- gitcommands.go | 1 - gui.go | 17 ++++++++++++++--- keybindings.go | 3 +++ view_helpers.go | 18 ++++++++++++++++++ 7 files changed, 97 insertions(+), 28 deletions(-) create mode 100644 commit_message_panel.go diff --git a/commit_message_panel.go b/commit_message_panel.go new file mode 100644 index 000000000..7ff609976 --- /dev/null +++ b/commit_message_panel.go @@ -0,0 +1,42 @@ +package main + +import "github.com/jesseduffield/gocui" + +func handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { + message := trimmedContent(v) + if message == "" { + return createErrorPanel(g, "You cannot commit without a commit message") + } + if output, err := gitCommit(g, message); err != nil { + if err == errNoUsername { + return createErrorPanel(g, err.Error()) + } + return createErrorPanel(g, output) + } + refreshFiles(g) + g.SetViewOnBottom("commitMessage") + return refreshCommits(g) +} + +func handleCommitClose(g *gocui.Gui, v *gocui.View) error { + g.SetViewOnBottom("commitMessage") + return switchFocus(g, v, getFilesView(g)) +} + +func handleNewlineCommitMessage(g *gocui.Gui, v *gocui.View) error { + // resising ahead of time so that the top line doesn't get hidden to make + // room for the cursor on the second line + x0, y0, x1, y1 := getConfirmationPanelDimensions(g, v.Buffer()) + if _, err := g.SetView("commitMessage", x0, y0, x1, y1+1, 0); err != nil { + if err != gocui.ErrUnknownView { + return err + } + } + + v.EditNewLine() + return nil +} + +func handleCommitFocused(g *gocui.Gui, v *gocui.View) error { + return renderString(g, "options", "esc: close, enter: confirm") +} diff --git a/confirmation_panel.go b/confirmation_panel.go index c82b6b65b..03e078155 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -56,6 +56,7 @@ func getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, } func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, initialValue *[]byte, handleConfirm func(*gocui.Gui, *gocui.View) error) error { + g.SetViewOnBottom("commitMessage") if initialValue == nil { initialValue = &[]byte{} } @@ -66,9 +67,7 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, init return err } - g.Cursor = true - - handleConfirmAndClear := func(gui *gocui.Gui, view *gocui.View) error { + handleConfirm := func(gui *gocui.Gui, view *gocui.View) error { *initialValue = nil return handleConfirm(g, view) } @@ -84,7 +83,7 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, init confirmationView.Title = title restorePreviousBuffer(confirmationView, initialValue) switchFocus(g, currentView, confirmationView) - return setKeyBindings(g, handleConfirmAndClear, handleClose) + return setKeyBindings(g, handleConfirm, handleClose) } return nil } @@ -106,6 +105,7 @@ func getCursorPositionFromBuffer(initialValue *[]byte) (int, int) { } func createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error { + g.SetViewOnBottom("commitMessage") g.Update(func(g *gocui.Gui) error { // delete the existing confirmation panel if it exists if view, _ := g.View("confirmation"); view != nil { @@ -172,15 +172,20 @@ func trimTrailingNewline(str string) string { return str } -func resizeConfirmationPanel(g *gocui.Gui) error { +func resizeConfirmationPanel(g *gocui.Gui, viewName string) error { // If the confirmation panel is already displayed, just resize the width, // otherwise continue - if v, err := g.View("confirmation"); err == nil { + g.Update(func(g *gocui.Gui) error { + v, err := g.View(viewName) + if err != nil { + return nil + } content := trimTrailingNewline(v.Buffer()) x0, y0, x1, y1 := getConfirmationPanelDimensions(g, content) - if _, err = g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { + if _, err := g.SetView(viewName, x0, y0, x1, y1, 0); err != nil { return err } - } + return nil + }) return nil } diff --git a/files_panel.go b/files_panel.go index b2de2c226..75e20885f 100644 --- a/files_panel.go +++ b/files_panel.go @@ -15,9 +15,8 @@ import ( ) var ( - savedCommitMessage = &[]byte{} - errNoFiles = errors.New("No changed files") - errNoUsername = errors.New(`No username set. Please do: git config --global user.name "Your Name"`) + errNoFiles = errors.New("No changed files") + errNoUsername = errors.New(`No username set. Please do: git config --global user.name "Your Name"`) ) func stagedFiles(files []GitFile) []GitFile { @@ -178,19 +177,11 @@ func handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { if len(stagedFiles(state.GitFiles)) == 0 && !state.HasMergeConflicts { return createErrorPanel(g, "There are no staged files to commit") } - createPromptPanel(g, filesView, "Commit message", savedCommitMessage, func(g *gocui.Gui, v *gocui.View) error { - message := trimmedContent(v) - if message == "" { - return createErrorPanel(g, "You cannot commit without a commit message") - } - if output, err := gitCommit(g, message); err != nil { - if err == errNoUsername { - return createErrorPanel(g, err.Error()) - } - return createErrorPanel(g, output) - } - refreshFiles(g) - return refreshCommits(g) + commitMessageView := getCommitMessageView(g) + g.Update(func(g *gocui.Gui) error { + g.SetViewOnTop("commitMessage") + switchFocus(g, filesView, commitMessageView) + return nil }) return nil } diff --git a/gitcommands.go b/gitcommands.go index 7c1ec84bd..798627c24 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -218,7 +218,6 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { func runCommand(command string) (string, error) { commandLog(command) splitCmd := strings.Split(command, " ") - devLog(splitCmd) cmdOut, err := exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput() return sanitisedCommandOutput(cmdOut, err) } diff --git a/gui.go b/gui.go index 4cf7d7df5..b6258ec95 100644 --- a/gui.go +++ b/gui.go @@ -199,15 +199,26 @@ func layout(g *gocui.Gui) error { if err != gocui.ErrUnknownView { return err } - v.BgColor = gocui.ColorDefault v.FgColor = gocui.ColorBlue v.Frame = false } - if err = resizeConfirmationPanel(g); err != nil { - return err + if getCommitMessageView(g) == nil { + // doesn't matter where this view starts because it will be hidden + if commitMessageView, err := g.SetView("commitMessage", 0, 0, width, height, 0); err != nil { + if err != gocui.ErrUnknownView { + return err + } + g.SetViewOnBottom("commitMessage") + commitMessageView.Title = "Commit message" + commitMessageView.FgColor = gocui.ColorWhite + commitMessageView.Editable = true + } } + resizeConfirmationPanel(g, "commitMessage") + resizeConfirmationPanel(g, "confirmation") + if v, err := g.SetView("version", width-len(version)-1, optionsTop, width, optionsTop+2, 0); err != nil { if err != gocui.ErrUnknownView { return err diff --git a/keybindings.go b/keybindings.go index 07309790f..bc4a67015 100644 --- a/keybindings.go +++ b/keybindings.go @@ -58,6 +58,9 @@ func keybindings(g *gocui.Gui) error { {ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, {ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, {ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, + {ViewName: "commitMessage", Key: gocui.KeyEnter, Modifier: gocui.ModNone, Handler: handleCommitConfirm}, + {ViewName: "commitMessage", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleCommitClose}, + {ViewName: "commitMessage", Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: handleNewlineCommitMessage}, } // Would make these keybindings global but that interferes with editing diff --git a/view_helpers.go b/view_helpers.go index 2f5f2caf0..fdf3a802f 100644 --- a/view_helpers.go +++ b/view_helpers.go @@ -75,6 +75,8 @@ func newLineFocused(g *gocui.Gui, v *gocui.View) error { return handleBranchSelect(g, v) case "confirmation": return nil + case "commitMessage": + return handleCommitFocused(g, v) case "main": // TODO: pull this out into a 'view focused' function refreshMergePanel(g) @@ -215,3 +217,19 @@ func loader() string { index := nanos / 50000000 % int64(len(characters)) return characters[index : index+1] } + +// TODO: refactor properly +func getFilesView(g *gocui.Gui) *gocui.View { + v, _ := g.View("files") + return v +} + +func getCommitsView(g *gocui.Gui) *gocui.View { + v, _ := g.View("commits") + return v +} + +func getCommitMessageView(g *gocui.Gui) *gocui.View { + v, _ := g.View("commitMessage") + return v +} From 47bf649a69f11df1d0713b075f9a5c4b53f26f87 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 13:18:33 +1000 Subject: [PATCH 23/36] switch focus back to files view after confirming commit message --- commit_message_panel.go | 1 + 1 file changed, 1 insertion(+) diff --git a/commit_message_panel.go b/commit_message_panel.go index 7ff609976..49551c1eb 100644 --- a/commit_message_panel.go +++ b/commit_message_panel.go @@ -15,6 +15,7 @@ func handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { } refreshFiles(g) g.SetViewOnBottom("commitMessage") + switchFocus(g, v, getFilesView(g)) return refreshCommits(g) } From b8daf71db6a8f0908f0c114f30afc673c07bbe92 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 13:19:54 +1000 Subject: [PATCH 24/36] Delete ZHgalGrWSF --- ZHgalGrWSF | 1 - 1 file changed, 1 deletion(-) delete mode 100644 ZHgalGrWSF diff --git a/ZHgalGrWSF b/ZHgalGrWSF deleted file mode 100644 index f1f0d2371..000000000 --- a/ZHgalGrWSF +++ /dev/null @@ -1 +0,0 @@ -GaUMygWjJa \ No newline at end of file From 8ae346787aaef5261acd0026b61a18883f2d0149 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 13:24:05 +1000 Subject: [PATCH 25/36] revert use of stored values in confirmation panels --- branches_panel.go | 4 ++-- commits_panel.go | 2 +- confirmation_panel.go | 36 ++---------------------------------- stash_panel.go | 2 +- 4 files changed, 6 insertions(+), 38 deletions(-) diff --git a/branches_panel.go b/branches_panel.go index 00091ffb8..3102f0c28 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -30,7 +30,7 @@ func handleForceCheckout(g *gocui.Gui, v *gocui.View) error { } func handleCheckoutByName(g *gocui.Gui, v *gocui.View) error { - createPromptPanel(g, v, "Branch Name:", nil, func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "Branch Name:", func(g *gocui.Gui, v *gocui.View) error { if output, err := gitCheckout(trimmedContent(v), false); err != nil { return createErrorPanel(g, output) } @@ -41,7 +41,7 @@ func handleCheckoutByName(g *gocui.Gui, v *gocui.View) error { func handleNewBranch(g *gocui.Gui, v *gocui.View) error { branch := state.Branches[0] - createPromptPanel(g, v, "New Branch Name (Branch is off of "+branch.Name+")", nil, func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "New Branch Name (Branch is off of "+branch.Name+")", func(g *gocui.Gui, v *gocui.View) error { if output, err := gitNewBranch(trimmedContent(v)); err != nil { return createErrorPanel(g, output) } diff --git a/commits_panel.go b/commits_panel.go index e8ff68678..88c7b8ebe 100644 --- a/commits_panel.go +++ b/commits_panel.go @@ -109,7 +109,7 @@ func handleRenameCommit(g *gocui.Gui, v *gocui.View) error { if getItemPosition(v) != 0 { return createErrorPanel(g, "Can only rename topmost commit") } - createPromptPanel(g, v, "Rename Commit", nil, func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, v, "Rename Commit", func(g *gocui.Gui, v *gocui.View) error { if output, err := gitRenameCommit(v.Buffer()); err != nil { return createErrorPanel(g, output) } diff --git a/confirmation_panel.go b/confirmation_panel.go index 03e078155..563db72d8 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -55,11 +55,8 @@ func getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, height/2 + panelHeight/2 } -func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, initialValue *[]byte, handleConfirm func(*gocui.Gui, *gocui.View) error) error { +func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, handleConfirm func(*gocui.Gui, *gocui.View) error) error { g.SetViewOnBottom("commitMessage") - if initialValue == nil { - initialValue = &[]byte{} - } // only need to fit one line x0, y0, x1, y1 := getConfirmationPanelDimensions(g, "") if confirmationView, err := g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { @@ -67,43 +64,14 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, init return err } - handleConfirm := func(gui *gocui.Gui, view *gocui.View) error { - *initialValue = nil - return handleConfirm(g, view) - } - - handleClose := func(gui *gocui.Gui, view *gocui.View) error { - // FIXME: trimming a newline that is no doubt caused by the enter keybinding - // on the editor. We should just define a new editor that doesn't do that - *initialValue = []byte(strings.TrimSpace(view.Buffer())) - return nil - } - confirmationView.Editable = true confirmationView.Title = title - restorePreviousBuffer(confirmationView, initialValue) switchFocus(g, currentView, confirmationView) - return setKeyBindings(g, handleConfirm, handleClose) + return setKeyBindings(g, handleConfirm, nil) } return nil } -func restorePreviousBuffer(confirmationView *gocui.View, initialValue *[]byte) { - confirmationView.Write(*initialValue) - x, y := getCursorPositionFromBuffer(initialValue) - devLog("New cursor position:", x, y) - confirmationView.SetCursor(0, 0) - confirmationView.MoveCursor(x, y, false) -} - -func getCursorPositionFromBuffer(initialValue *[]byte) (int, int) { - split := strings.Split(string(*initialValue), "\n") - lastLine := split[len(split)-1] - x := len(lastLine) - y := len(split) - return x, y -} - func createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error { g.SetViewOnBottom("commitMessage") g.Update(func(g *gocui.Gui) error { diff --git a/stash_panel.go b/stash_panel.go index a4a2207d8..33c7e297b 100644 --- a/stash_panel.go +++ b/stash_panel.go @@ -82,7 +82,7 @@ func stashDo(g *gocui.Gui, v *gocui.View, method string) error { } func handleStashSave(g *gocui.Gui, filesView *gocui.View) error { - createPromptPanel(g, filesView, "Stash changes", nil, func(g *gocui.Gui, v *gocui.View) error { + createPromptPanel(g, filesView, "Stash changes", func(g *gocui.Gui, v *gocui.View) error { if output, err := gitStashSave(trimmedContent(v)); err != nil { createErrorPanel(g, output) } From 6d3d40c41fb8703409dc6e3fcd8cb6efbff21d8d Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 13:27:34 +1000 Subject: [PATCH 26/36] handle error on confirmation panel resize --- gui.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gui.go b/gui.go index b6258ec95..033dbe06a 100644 --- a/gui.go +++ b/gui.go @@ -216,8 +216,12 @@ func layout(g *gocui.Gui) error { } } - resizeConfirmationPanel(g, "commitMessage") - resizeConfirmationPanel(g, "confirmation") + if err = resizeConfirmationPanel(g, "commitMessage"); err != nil { + return err + } + if err = resizeConfirmationPanel(g, "confirmation"); err != nil { + return err + } if v, err := g.SetView("version", width-len(version)-1, optionsTop, width, optionsTop+2, 0); err != nil { if err != gocui.ErrUnknownView { From f1eaeec9eeddc4c676524d6c9dd6f8737a70e6ac Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 12:35:17 +1000 Subject: [PATCH 27/36] remove time logging --- ZHgalGrWSF | 1 + gitcommands.go | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 ZHgalGrWSF diff --git a/ZHgalGrWSF b/ZHgalGrWSF new file mode 100644 index 000000000..f1f0d2371 --- /dev/null +++ b/ZHgalGrWSF @@ -0,0 +1 @@ +GaUMygWjJa \ No newline at end of file diff --git a/gitcommands.go b/gitcommands.go index bb49f487c..59331ad53 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -120,13 +120,11 @@ func mergeGitStatusFiles(oldGitFiles, newGitFiles []GitFile) []GitFile { } func runDirectCommand(command string) (string, error) { - timeStart := time.Now() commandLog(command) cmdOut, err := exec. Command(state.Platform.shell, state.Platform.shellArg, command). CombinedOutput() - devLog("run direct command time for command: ", command, time.Now().Sub(timeStart)) return sanitisedCommandOutput(cmdOut, err) } @@ -258,12 +256,10 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { } func runCommand(command string) (string, error) { - commandStartTime := time.Now() commandLog(command) splitCmd := strings.Split(command, " ") devLog(splitCmd) cmdOut, err := exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput() - devLog("run command time: ", time.Now().Sub(commandStartTime)) return sanitisedCommandOutput(cmdOut, err) } From 73e740d1ba45e6c01988953234f8e217b811d1dc Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:04:02 +1000 Subject: [PATCH 28/36] clean up fixup code reduce log clutter add log dumping with spew --- commits_panel.go | 34 ++++++++--- files_panel.go | 4 -- gitcommands.go | 59 ++++++++----------- main.go | 10 ++++ test/lots_of_commits.sh | 28 +++++++++ ...nerate_basic_repo.sh => merge_conflict.sh} | 2 +- view_helpers.go | 2 +- 7 files changed, 91 insertions(+), 48 deletions(-) create mode 100755 test/lots_of_commits.sh rename test/{generate_basic_repo.sh => merge_conflict.sh} (95%) diff --git a/commits_panel.go b/commits_panel.go index b222d346c..2b9ccbf87 100644 --- a/commits_panel.go +++ b/commits_panel.go @@ -42,7 +42,6 @@ func refreshCommits(g *gocui.Gui) error { func handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error { return createConfirmationPanel(g, commitView, "Reset To Commit", "Are you sure you want to reset to this commit?", func(g *gocui.Gui, v *gocui.View) error { commit, err := getSelectedCommit(g) - devLog(commit) if err != nil { panic(err) } @@ -106,23 +105,40 @@ func handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error { return handleCommitSelect(g, v) } +// TODO: move to files panel +func anyUnStagedChanges(files []GitFile) bool { + for _, file := range files { + if file.Tracked && file.HasUnstagedChanges { + return true + } + } + return false +} + func handleCommitFixup(g *gocui.Gui, v *gocui.View) error { if len(state.Commits) == 1 { return createErrorPanel(g, "You have no commits to squash with") } + objectLog(state.GitFiles) + if anyUnStagedChanges(state.GitFiles) { + return createErrorPanel(g, "Can't fixup while there are unstaged changes") + } branch := state.Branches[0] commit, err := getSelectedCommit(g) if err != nil { return err } - if output, err := gitSquashFixupCommit(branch.Name, commit.Sha); err != nil { - return createErrorPanel(g, output) - } - if err := refreshCommits(g); err != nil { - panic(err) - } - refreshStatus(g) - return handleCommitSelect(g, v) + createConfirmationPanel(g, v, "Fixup", "Are you sure you want to fixup this commit? The commit beneath will be squashed up into this one", func(g *gocui.Gui, v *gocui.View) error { + if output, err := gitSquashFixupCommit(branch.Name, commit.Sha); err != nil { + return createErrorPanel(g, output) + } + if err := refreshCommits(g); err != nil { + panic(err) + } + refreshStatus(g) + return handleCommitSelect(g, v) + }, nil) + return nil } func handleRenameCommit(g *gocui.Gui, v *gocui.View) error { diff --git a/files_panel.go b/files_panel.go index 32ed36ad4..e645c6cb6 100644 --- a/files_panel.go +++ b/files_panel.go @@ -295,7 +295,6 @@ func refreshFiles(g *gocui.Gui) error { } func pullFiles(g *gocui.Gui, v *gocui.View) error { - devLog("pulling...") createMessagePanel(g, v, "", "Pulling...") go func() { if output, err := gitPull(); err != nil { @@ -304,7 +303,6 @@ func pullFiles(g *gocui.Gui, v *gocui.View) error { closeConfirmationPrompt(g) refreshCommits(g) refreshStatus(g) - devLog("pulled.") } refreshFiles(g) }() @@ -312,7 +310,6 @@ func pullFiles(g *gocui.Gui, v *gocui.View) error { } func pushFiles(g *gocui.Gui, v *gocui.View) error { - devLog("pushing...") createMessagePanel(g, v, "", "Pushing...") go func() { if output, err := gitPush(); err != nil { @@ -321,7 +318,6 @@ func pushFiles(g *gocui.Gui, v *gocui.View) error { closeConfirmationPrompt(g) refreshCommits(g) refreshStatus(g) - devLog("pushed.") } }() return nil diff --git a/gitcommands.go b/gitcommands.go index 59331ad53..3db1df1ee 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -119,6 +119,12 @@ func mergeGitStatusFiles(oldGitFiles, newGitFiles []GitFile) []GitFile { return result } +// only to be used when you're already in an error state +func runDirectCommandIgnoringError(command string) string { + output, _ := runDirectCommand(command) + return output +} + func runDirectCommand(command string) (string, error) { commandLog(command) @@ -212,13 +218,9 @@ func getGitStatusFiles() []GitFile { Deleted: unstagedChange == "D" || stagedChange == "D", HasMergeConflicts: change == "UU", } - devLog("tracked", gitFile.Tracked) - devLog("hasUnstagedChanges", gitFile.HasUnstagedChanges) - devLog("HasStagedChanges", gitFile.HasStagedChanges) - devLog("DisplayString", gitFile.DisplayString) gitFiles = append(gitFiles, gitFile) } - devLog(gitFiles) + objectLog(gitFiles) return gitFiles } @@ -258,7 +260,6 @@ func sanitisedCommandOutput(output []byte, err error) (string, error) { func runCommand(command string) (string, error) { commandLog(command) splitCmd := strings.Split(command, " ") - devLog(splitCmd) cmdOut, err := exec.Command(splitCmd[0], splitCmd[1:]...).CombinedOutput() return sanitisedCommandOutput(cmdOut, err) } @@ -419,7 +420,6 @@ func unStageFile(file string, tracked bool) error { } else { command = "git rm --cached " } - devLog(command) _, err := runCommand(command + file) return err } @@ -488,35 +488,28 @@ func gitSquashPreviousTwoCommits(message string) (string, error) { } func gitSquashFixupCommit(branchName string, shaValue string) (string, error) { + var err error + commands := []string{ + "git checkout -q " + shaValue, + "git reset --soft " + shaValue + "^", + "git commit --amend -C " + shaValue + "^", + "git rebase --onto HEAD " + shaValue + " " + branchName, + } ret := "" - output, err := runDirectCommand("git checkout -q " + shaValue) - ret += output - if err != nil { - goto FIXUP_ERROR + for _, command := range commands { + devLog(command) + output, err := runDirectCommand(command) + ret += output + if err != nil { + devLog(ret) + break + } } - output, err = runDirectCommand("git reset --soft " + shaValue + "^") - ret += output if err != nil { - goto FIXUP_ERROR - } - output, err = runDirectCommand("git commit --amend -C " + shaValue + "^") - ret += output - if err != nil { - goto FIXUP_ERROR - } - output, err = runDirectCommand("git rebase --onto HEAD " + shaValue + " " + branchName) - ret += output - if err != nil { - goto FIXUP_ERROR - } - return ret, err - -FIXUP_ERROR: - //Failed to perform rebase, back to the original branch - output2, err2 := runDirectCommand("git checkout " + branchName) - ret += output2 - if err2 != nil { - return ret, err2 + // We are already in an error state here so we're just going to append + // the output of these commands + ret += runDirectCommandIgnoringError("git branch -d " + shaValue) + ret += runDirectCommandIgnoringError("git checkout " + branchName) } return ret, err } diff --git a/main.go b/main.go index c918c7348..426f47eee 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,8 @@ import ( "os/user" "path/filepath" + "github.com/davecgh/go-spew/spew" + "github.com/jesseduffield/gocui" git "gopkg.in/src-d/go-git.v4" ) @@ -47,6 +49,14 @@ func devLog(objects ...interface{}) { localLog("development.log", objects...) } +func objectLog(object interface{}) { + if !*debuggingFlag { + return + } + str := spew.Sdump(object) + localLog("development.log", str) +} + func commandLog(objects ...interface{}) { localLog("commands.log", objects...) } diff --git a/test/lots_of_commits.sh b/test/lots_of_commits.sh new file mode 100755 index 000000000..d85034f4e --- /dev/null +++ b/test/lots_of_commits.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# this script makes a repo with lots of commits + +# call this command from the test directory: +# ./lots_of_commits.sh; cd testrepo; gg; cd .. + +# -e means exit if something fails +# -x means print out simple commands before running them +set -ex + +reponame="testrepo" + +rm -rf ${reponame} +mkdir ${reponame} +cd ${reponame} + +git init + +i=2 +end=100 +while [ $i -le $end ]; do + echo "file${i}" > file${i} + git add file${i} + git commit -m file${i} + + i=$(($i+1)) +done diff --git a/test/generate_basic_repo.sh b/test/merge_conflict.sh similarity index 95% rename from test/generate_basic_repo.sh rename to test/merge_conflict.sh index ef04333c7..9bd12bf56 100755 --- a/test/generate_basic_repo.sh +++ b/test/merge_conflict.sh @@ -4,7 +4,7 @@ # on the master branch and if we try and merge master we get a merge conflict # call this command from the test directory: -# ./generate_basic_repo.sh; cd testrepo; gg; cd .. +# ./merge_conflict.sh; cd testrepo; gg; cd .. # -e means exit if something fails # -x means print out simple commands before running them diff --git a/view_helpers.go b/view_helpers.go index bb8b86da7..0d7d7618c 100644 --- a/view_helpers.go +++ b/view_helpers.go @@ -107,7 +107,7 @@ func switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error { state.PreviousView = oldView.Name() } newView.Highlight = true - devLog(newView.Name()) + devLog("new focused view is " + newView.Name()) if _, err := g.SetCurrentView(newView.Name()); err != nil { return err } From e46f3b33935c666066c5f0716efc2439698a7101 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:04:42 +1000 Subject: [PATCH 29/36] add spew dependency to vendor --- Gopkg.lock | 9 + vendor/github.com/davecgh/go-spew/LICENSE | 15 + .../github.com/davecgh/go-spew/spew/bypass.go | 152 ++++++ .../davecgh/go-spew/spew/bypasssafe.go | 38 ++ .../github.com/davecgh/go-spew/spew/common.go | 341 ++++++++++++ .../github.com/davecgh/go-spew/spew/config.go | 306 +++++++++++ vendor/github.com/davecgh/go-spew/spew/doc.go | 211 ++++++++ .../github.com/davecgh/go-spew/spew/dump.go | 509 ++++++++++++++++++ .../github.com/davecgh/go-spew/spew/format.go | 419 ++++++++++++++ .../github.com/davecgh/go-spew/spew/spew.go | 148 +++++ 10 files changed, 2148 insertions(+) create mode 100644 vendor/github.com/davecgh/go-spew/LICENSE create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypass.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypasssafe.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/common.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/config.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/doc.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/dump.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/format.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/spew.go diff --git a/Gopkg.lock b/Gopkg.lock index 65f765807..f15d99700 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,14 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "NUT" + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + [[projects]] digest = "1:de4a74b504df31145ffa8ca0c4edbffa2f3eb7f466753962184611b618fa5981" name = "github.com/emirpasic/gods" @@ -274,6 +282,7 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ + "github.com/davecgh/go-spew/spew", "github.com/fatih/color", "github.com/golang-collections/collections/stack", "github.com/jesseduffield/gocui", diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE new file mode 100644 index 000000000..c83641619 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2016 Dave Collins + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go new file mode 100644 index 000000000..8a4a6589a --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -0,0 +1,152 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build !js,!appengine,!safe,!disableunsafe + +package spew + +import ( + "reflect" + "unsafe" +) + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = false + + // ptrSize is the size of a pointer on the current arch. + ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +var ( + // offsetPtr, offsetScalar, and offsetFlag are the offsets for the + // internal reflect.Value fields. These values are valid before golang + // commit ecccf07e7f9d which changed the format. The are also valid + // after commit 82f48826c6c7 which changed the format again to mirror + // the original format. Code in the init function updates these offsets + // as necessary. + offsetPtr = uintptr(ptrSize) + offsetScalar = uintptr(0) + offsetFlag = uintptr(ptrSize * 2) + + // flagKindWidth and flagKindShift indicate various bits that the + // reflect package uses internally to track kind information. + // + // flagRO indicates whether or not the value field of a reflect.Value is + // read-only. + // + // flagIndir indicates whether the value field of a reflect.Value is + // the actual data or a pointer to the data. + // + // These values are valid before golang commit 90a7c3c86944 which + // changed their positions. Code in the init function updates these + // flags as necessary. + flagKindWidth = uintptr(5) + flagKindShift = uintptr(flagKindWidth - 1) + flagRO = uintptr(1 << 0) + flagIndir = uintptr(1 << 1) +) + +func init() { + // Older versions of reflect.Value stored small integers directly in the + // ptr field (which is named val in the older versions). Versions + // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named + // scalar for this purpose which unfortunately came before the flag + // field, so the offset of the flag field is different for those + // versions. + // + // This code constructs a new reflect.Value from a known small integer + // and checks if the size of the reflect.Value struct indicates it has + // the scalar field. When it does, the offsets are updated accordingly. + vv := reflect.ValueOf(0xf00) + if unsafe.Sizeof(vv) == (ptrSize * 4) { + offsetScalar = ptrSize * 2 + offsetFlag = ptrSize * 3 + } + + // Commit 90a7c3c86944 changed the flag positions such that the low + // order bits are the kind. This code extracts the kind from the flags + // field and ensures it's the correct type. When it's not, the flag + // order has been changed to the newer format, so the flags are updated + // accordingly. + upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) + upfv := *(*uintptr)(upf) + flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { + flagKindShift = 0 + flagRO = 1 << 5 + flagIndir = 1 << 6 + + // Commit adf9b30e5594 modified the flags to separate the + // flagRO flag into two bits which specifies whether or not the + // field is embedded. This causes flagIndir to move over a bit + // and means that flagRO is the combination of either of the + // original flagRO bit and the new bit. + // + // This code detects the change by extracting what used to be + // the indirect bit to ensure it's set. When it's not, the flag + // order has been changed to the newer format, so the flags are + // updated accordingly. + if upfv&flagIndir == 0 { + flagRO = 3 << 5 + flagIndir = 1 << 7 + } + } +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data. It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { + indirects := 1 + vt := v.Type() + upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) + rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) + if rvf&flagIndir != 0 { + vt = reflect.PtrTo(v.Type()) + indirects++ + } else if offsetScalar != 0 { + // The value is in the scalar field when it's not one of the + // reference types. + switch vt.Kind() { + case reflect.Uintptr: + case reflect.Chan: + case reflect.Func: + case reflect.Map: + case reflect.Ptr: + case reflect.UnsafePointer: + default: + upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + + offsetScalar) + } + } + + pv := reflect.NewAt(vt, upv) + rv = pv + for i := 0; i < indirects; i++ { + rv = rv.Elem() + } + return rv +} diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go new file mode 100644 index 000000000..1fe3cf3d5 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is running on Google App Engine, compiled by GopherJS, or +// "-tags safe" is added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build js appengine safe disableunsafe + +package spew + +import "reflect" + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = true +) + +// unsafeReflectValue typically converts the passed reflect.Value into a one +// that bypasses the typical safety restrictions preventing access to +// unaddressable and unexported data. However, doing this relies on access to +// the unsafe package. This is a stub version which simply returns the passed +// reflect.Value when the unsafe package is not available. +func unsafeReflectValue(v reflect.Value) reflect.Value { + return v +} diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go new file mode 100644 index 000000000..7c519ff47 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "reflect" + "sort" + "strconv" +) + +// Some constants in the form of bytes to avoid string overhead. This mirrors +// the technique used in the fmt package. +var ( + panicBytes = []byte("(PANIC=") + plusBytes = []byte("+") + iBytes = []byte("i") + trueBytes = []byte("true") + falseBytes = []byte("false") + interfaceBytes = []byte("(interface {})") + commaNewlineBytes = []byte(",\n") + newlineBytes = []byte("\n") + openBraceBytes = []byte("{") + openBraceNewlineBytes = []byte("{\n") + closeBraceBytes = []byte("}") + asteriskBytes = []byte("*") + colonBytes = []byte(":") + colonSpaceBytes = []byte(": ") + openParenBytes = []byte("(") + closeParenBytes = []byte(")") + spaceBytes = []byte(" ") + pointerChainBytes = []byte("->") + nilAngleBytes = []byte("") + maxNewlineBytes = []byte("\n") + maxShortBytes = []byte("") + circularBytes = []byte("") + circularShortBytes = []byte("") + invalidAngleBytes = []byte("") + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + percentBytes = []byte("%") + precisionBytes = []byte(".") + openAngleBytes = []byte("<") + closeAngleBytes = []byte(">") + openMapBytes = []byte("map[") + closeMapBytes = []byte("]") + lenEqualsBytes = []byte("len=") + capEqualsBytes = []byte("cap=") +) + +// hexDigits is used to map a decimal value to a hex digit. +var hexDigits = "0123456789abcdef" + +// catchPanic handles any panics that might occur during the handleMethods +// calls. +func catchPanic(w io.Writer, v reflect.Value) { + if err := recover(); err != nil { + w.Write(panicBytes) + fmt.Fprintf(w, "%v", err) + w.Write(closeParenBytes) + } +} + +// handleMethods attempts to call the Error and String methods on the underlying +// type the passed reflect.Value represents and outputes the result to Writer w. +// +// It handles panics in any called methods by catching and displaying the error +// as the formatted value. +func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { + // We need an interface to check if the type implements the error or + // Stringer interface. However, the reflect package won't give us an + // interface on certain things like unexported struct fields in order + // to enforce visibility rules. We use unsafe, when it's available, + // to bypass these restrictions since this package does not mutate the + // values. + if !v.CanInterface() { + if UnsafeDisabled { + return false + } + + v = unsafeReflectValue(v) + } + + // Choose whether or not to do error and Stringer interface lookups against + // the base type or a pointer to the base type depending on settings. + // Technically calling one of these methods with a pointer receiver can + // mutate the value, however, types which choose to satisify an error or + // Stringer interface with a pointer receiver should not be mutating their + // state inside these interface methods. + if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { + v = unsafeReflectValue(v) + } + if v.CanAddr() { + v = v.Addr() + } + + // Is it an error or Stringer? + switch iface := v.Interface().(type) { + case error: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.Error())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + + w.Write([]byte(iface.Error())) + return true + + case fmt.Stringer: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.String())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + w.Write([]byte(iface.String())) + return true + } + return false +} + +// printBool outputs a boolean value as true or false to Writer w. +func printBool(w io.Writer, val bool) { + if val { + w.Write(trueBytes) + } else { + w.Write(falseBytes) + } +} + +// printInt outputs a signed integer value to Writer w. +func printInt(w io.Writer, val int64, base int) { + w.Write([]byte(strconv.FormatInt(val, base))) +} + +// printUint outputs an unsigned integer value to Writer w. +func printUint(w io.Writer, val uint64, base int) { + w.Write([]byte(strconv.FormatUint(val, base))) +} + +// printFloat outputs a floating point value using the specified precision, +// which is expected to be 32 or 64bit, to Writer w. +func printFloat(w io.Writer, val float64, precision int) { + w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) +} + +// printComplex outputs a complex value using the specified float precision +// for the real and imaginary parts to Writer w. +func printComplex(w io.Writer, c complex128, floatPrecision int) { + r := real(c) + w.Write(openParenBytes) + w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) + i := imag(c) + if i >= 0 { + w.Write(plusBytes) + } + w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) + w.Write(iBytes) + w.Write(closeParenBytes) +} + +// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// prefix to Writer w. +func printHexPtr(w io.Writer, p uintptr) { + // Null pointer. + num := uint64(p) + if num == 0 { + w.Write(nilAngleBytes) + return + } + + // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix + buf := make([]byte, 18) + + // It's simpler to construct the hex string right to left. + base := uint64(16) + i := len(buf) - 1 + for num >= base { + buf[i] = hexDigits[num%base] + num /= base + i-- + } + buf[i] = hexDigits[num] + + // Add '0x' prefix. + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + + // Strip unused leading bytes. + buf = buf[i:] + w.Write(buf) +} + +// valuesSorter implements sort.Interface to allow a slice of reflect.Value +// elements to be sorted. +type valuesSorter struct { + values []reflect.Value + strings []string // either nil or same len and values + cs *ConfigState +} + +// newValuesSorter initializes a valuesSorter instance, which holds a set of +// surrogate keys on which the data should be sorted. It uses flags in +// ConfigState to decide if and how to populate those surrogate keys. +func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { + vs := &valuesSorter{values: values, cs: cs} + if canSortSimply(vs.values[0].Kind()) { + return vs + } + if !cs.DisableMethods { + vs.strings = make([]string, len(values)) + for i := range vs.values { + b := bytes.Buffer{} + if !handleMethods(cs, &b, vs.values[i]) { + vs.strings = nil + break + } + vs.strings[i] = b.String() + } + } + if vs.strings == nil && cs.SpewKeys { + vs.strings = make([]string, len(values)) + for i := range vs.values { + vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) + } + } + return vs +} + +// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted +// directly, or whether it should be considered for sorting by surrogate keys +// (if the ConfigState allows it). +func canSortSimply(kind reflect.Kind) bool { + // This switch parallels valueSortLess, except for the default case. + switch kind { + case reflect.Bool: + return true + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return true + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Uintptr: + return true + case reflect.Array: + return true + } + return false +} + +// Len returns the number of values in the slice. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Len() int { + return len(s.values) +} + +// Swap swaps the values at the passed indices. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Swap(i, j int) { + s.values[i], s.values[j] = s.values[j], s.values[i] + if s.strings != nil { + s.strings[i], s.strings[j] = s.strings[j], s.strings[i] + } +} + +// valueSortLess returns whether the first value should sort before the second +// value. It is used by valueSorter.Less as part of the sort.Interface +// implementation. +func valueSortLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Bool: + return !a.Bool() && b.Bool() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return a.Int() < b.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return a.Uint() < b.Uint() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.String: + return a.String() < b.String() + case reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Array: + // Compare the contents of both arrays. + l := a.Len() + for i := 0; i < l; i++ { + av := a.Index(i) + bv := b.Index(i) + if av.Interface() == bv.Interface() { + continue + } + return valueSortLess(av, bv) + } + } + return a.String() < b.String() +} + +// Less returns whether the value at index i should sort before the +// value at index j. It is part of the sort.Interface implementation. +func (s *valuesSorter) Less(i, j int) bool { + if s.strings == nil { + return valueSortLess(s.values[i], s.values[j]) + } + return s.strings[i] < s.strings[j] +} + +// sortValues is a sort function that handles both native types and any type that +// can be converted to error or Stringer. Other inputs are sorted according to +// their Value.String() value to ensure display stability. +func sortValues(values []reflect.Value, cs *ConfigState) { + if len(values) == 0 { + return + } + sort.Sort(newValuesSorter(values, cs)) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 000000000..2e3d22f31 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 000000000..aacaac6f1 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * DisablePointerAddresses + DisablePointerAddresses specifies whether to disable the printing of + pointer addresses. This is useful when diffing data structures in tests. + + * DisableCapacities + DisableCapacities specifies whether to disable the printing of + capacities for arrays, slices, maps and channels. This is useful when + diffing data structures in tests. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go new file mode 100644 index 000000000..df1d582a7 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" +) + +var ( + // uint8Type is a reflect.Type representing a uint8. It is used to + // convert cgo types to uint8 slices for hexdumping. + uint8Type = reflect.TypeOf(uint8(0)) + + // cCharRE is a regular expression that matches a cgo char. + // It is used to detect character arrays to hexdump them. + cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + + // cUnsignedCharRE is a regular expression that matches a cgo unsigned + // char. It is used to detect unsigned character arrays to hexdump + // them. + cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + + // cUint8tCharRE is a regular expression that matches a cgo uint8_t. + // It is used to detect uint8_t arrays to hexdump them. + cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") +) + +// dumpState contains information about the state of a dump operation. +type dumpState struct { + w io.Writer + depth int + pointers map[uintptr]int + ignoreNextType bool + ignoreNextIndent bool + cs *ConfigState +} + +// indent performs indentation according to the depth level and cs.Indent +// option. +func (d *dumpState) indent() { + if d.ignoreNextIndent { + d.ignoreNextIndent = false + return + } + d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) +} + +// unpackValue returns values inside of non-nil interfaces when possible. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + } + return v +} + +// dumpPtr handles formatting of pointers by indirecting them as necessary. +func (d *dumpState) dumpPtr(v reflect.Value) { + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range d.pointers { + if depth >= d.depth { + delete(d.pointers, k) + } + } + + // Keep list of all dereferenced pointers to show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by dereferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := d.pointers[addr]; ok && pd < d.depth { + cycleFound = true + indirects-- + break + } + d.pointers[addr] = d.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type information. + d.w.Write(openParenBytes) + d.w.Write(bytes.Repeat(asteriskBytes, indirects)) + d.w.Write([]byte(ve.Type().String())) + d.w.Write(closeParenBytes) + + // Display pointer information. + if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { + d.w.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + d.w.Write(pointerChainBytes) + } + printHexPtr(d.w, addr) + } + d.w.Write(closeParenBytes) + } + + // Display dereferenced value. + d.w.Write(openParenBytes) + switch { + case nilFound == true: + d.w.Write(nilAngleBytes) + + case cycleFound == true: + d.w.Write(circularBytes) + + default: + d.ignoreNextType = true + d.dump(ve) + } + d.w.Write(closeParenBytes) +} + +// dumpSlice handles formatting of arrays and slices. Byte (uint8 under +// reflection) arrays and slices are dumped in hexdump -C fashion. +func (d *dumpState) dumpSlice(v reflect.Value) { + // Determine whether this type should be hex dumped or not. Also, + // for types which should be hexdumped, try to use the underlying data + // first, then fall back to trying to convert them to a uint8 slice. + var buf []uint8 + doConvert := false + doHexDump := false + numEntries := v.Len() + if numEntries > 0 { + vt := v.Index(0).Type() + vts := vt.String() + switch { + // C types that need to be converted. + case cCharRE.MatchString(vts): + fallthrough + case cUnsignedCharRE.MatchString(vts): + fallthrough + case cUint8tCharRE.MatchString(vts): + doConvert = true + + // Try to use existing uint8 slices and fall back to converting + // and copying if that fails. + case vt.Kind() == reflect.Uint8: + // We need an addressable interface to convert the type + // to a byte slice. However, the reflect package won't + // give us an interface on certain things like + // unexported struct fields in order to enforce + // visibility rules. We use unsafe, when available, to + // bypass these restrictions since this package does not + // mutate the values. + vs := v + if !vs.CanInterface() || !vs.CanAddr() { + vs = unsafeReflectValue(vs) + } + if !UnsafeDisabled { + vs = vs.Slice(0, numEntries) + + // Use the existing uint8 slice if it can be + // type asserted. + iface := vs.Interface() + if slice, ok := iface.([]uint8); ok { + buf = slice + doHexDump = true + break + } + } + + // The underlying data needs to be converted if it can't + // be type asserted to a uint8 slice. + doConvert = true + } + + // Copy and convert the underlying type if needed. + if doConvert && vt.ConvertibleTo(uint8Type) { + // Convert and copy each element into a uint8 byte + // slice. + buf = make([]uint8, numEntries) + for i := 0; i < numEntries; i++ { + vv := v.Index(i) + buf[i] = uint8(vv.Convert(uint8Type).Uint()) + } + doHexDump = true + } + } + + // Hexdump the entire slice as needed. + if doHexDump { + indent := strings.Repeat(d.cs.Indent, d.depth) + str := indent + hex.Dump(buf) + str = strings.Replace(str, "\n", "\n"+indent, -1) + str = strings.TrimRight(str, d.cs.Indent) + d.w.Write([]byte(str)) + return + } + + // Recursively call dump for each item. + for i := 0; i < numEntries; i++ { + d.dump(d.unpackValue(v.Index(i))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } +} + +// dump is the main workhorse for dumping a value. It uses the passed reflect +// value to figure out what kind of object we are dealing with and formats it +// appropriately. It is a recursive function, however circular data structures +// are detected and handled properly. +func (d *dumpState) dump(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + d.w.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + d.indent() + d.dumpPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !d.ignoreNextType { + d.indent() + d.w.Write(openParenBytes) + d.w.Write([]byte(v.Type().String())) + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + d.ignoreNextType = false + + // Display length and capacity if the built-in len and cap functions + // work with the value's kind and the len/cap itself is non-zero. + valueLen, valueCap := 0, 0 + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + valueLen, valueCap = v.Len(), v.Cap() + case reflect.Map, reflect.String: + valueLen = v.Len() + } + if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { + d.w.Write(openParenBytes) + if valueLen != 0 { + d.w.Write(lenEqualsBytes) + printInt(d.w, int64(valueLen), 10) + } + if !d.cs.DisableCapacities && valueCap != 0 { + if valueLen != 0 { + d.w.Write(spaceBytes) + } + d.w.Write(capEqualsBytes) + printInt(d.w, int64(valueCap), 10) + } + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + + // Call Stringer/error interfaces if they exist and the handle methods flag + // is enabled + if !d.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(d.cs, d.w, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(d.w, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(d.w, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(d.w, v.Uint(), 10) + + case reflect.Float32: + printFloat(d.w, v.Float(), 32) + + case reflect.Float64: + printFloat(d.w, v.Float(), 64) + + case reflect.Complex64: + printComplex(d.w, v.Complex(), 32) + + case reflect.Complex128: + printComplex(d.w, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + d.dumpSlice(v) + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.String: + d.w.Write([]byte(strconv.Quote(v.String()))) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + d.w.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + numEntries := v.Len() + keys := v.MapKeys() + if d.cs.SortKeys { + sortValues(keys, d.cs) + } + for i, key := range keys { + d.dump(d.unpackValue(key)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.MapIndex(key))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Struct: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + vt := v.Type() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + d.indent() + vtf := vt.Field(i) + d.w.Write([]byte(vtf.Name)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.Field(i))) + if i < (numFields - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(d.w, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(d.w, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it in case any new + // types are added. + default: + if v.CanInterface() { + fmt.Fprintf(d.w, "%v", v.Interface()) + } else { + fmt.Fprintf(d.w, "%v", v.String()) + } + } +} + +// fdump is a helper function to consolidate the logic from the various public +// methods which take varying writers and config states. +func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { + for _, arg := range a { + if arg == nil { + w.Write(interfaceBytes) + w.Write(spaceBytes) + w.Write(nilAngleBytes) + w.Write(newlineBytes) + continue + } + + d := dumpState{w: w, cs: cs} + d.pointers = make(map[uintptr]int) + d.dump(reflect.ValueOf(arg)) + d.w.Write(newlineBytes) + } +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func Fdump(w io.Writer, a ...interface{}) { + fdump(&Config, w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(&Config, &buf, a...) + return buf.String() +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by an exported package global, +spew.Config. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func Dump(a ...interface{}) { + fdump(&Config, os.Stdout, a...) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go new file mode 100644 index 000000000..c49875bac --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" +) + +// supportedFlags is a list of all the character flags supported by fmt package. +const supportedFlags = "0-+# " + +// formatState implements the fmt.Formatter interface and contains information +// about the state of a formatting operation. The NewFormatter function can +// be used to get a new Formatter which can be used directly as arguments +// in standard fmt package printing calls. +type formatState struct { + value interface{} + fs fmt.State + depth int + pointers map[uintptr]int + ignoreNextType bool + cs *ConfigState +} + +// buildDefaultFormat recreates the original format string without precision +// and width information to pass in to fmt.Sprintf in the case of an +// unrecognized type. Unless new types are added to the language, this +// function won't ever be called. +func (f *formatState) buildDefaultFormat() (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + buf.WriteRune('v') + + format = buf.String() + return format +} + +// constructOrigFormat recreates the original format string including precision +// and width information to pass along to the standard fmt package. This allows +// automatic deferral of all format strings this package doesn't support. +func (f *formatState) constructOrigFormat(verb rune) (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + if width, ok := f.fs.Width(); ok { + buf.WriteString(strconv.Itoa(width)) + } + + if precision, ok := f.fs.Precision(); ok { + buf.Write(precisionBytes) + buf.WriteString(strconv.Itoa(precision)) + } + + buf.WriteRune(verb) + + format = buf.String() + return format +} + +// unpackValue returns values inside of non-nil interfaces when possible and +// ensures that types for values which have been unpacked from an interface +// are displayed when the show types flag is also set. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (f *formatState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface { + f.ignoreNextType = false + if !v.IsNil() { + v = v.Elem() + } + } + return v +} + +// formatPtr handles formatting of pointers by indirecting them as necessary. +func (f *formatState) formatPtr(v reflect.Value) { + // Display nil if top level pointer is nil. + showTypes := f.fs.Flag('#') + if v.IsNil() && (!showTypes || f.ignoreNextType) { + f.fs.Write(nilAngleBytes) + return + } + + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range f.pointers { + if depth >= f.depth { + delete(f.pointers, k) + } + } + + // Keep list of all dereferenced pointers to possibly show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by derferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := f.pointers[addr]; ok && pd < f.depth { + cycleFound = true + indirects-- + break + } + f.pointers[addr] = f.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type or indirection level depending on flags. + if showTypes && !f.ignoreNextType { + f.fs.Write(openParenBytes) + f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) + f.fs.Write([]byte(ve.Type().String())) + f.fs.Write(closeParenBytes) + } else { + if nilFound || cycleFound { + indirects += strings.Count(ve.Type().String(), "*") + } + f.fs.Write(openAngleBytes) + f.fs.Write([]byte(strings.Repeat("*", indirects))) + f.fs.Write(closeAngleBytes) + } + + // Display pointer information depending on flags. + if f.fs.Flag('+') && (len(pointerChain) > 0) { + f.fs.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + f.fs.Write(pointerChainBytes) + } + printHexPtr(f.fs, addr) + } + f.fs.Write(closeParenBytes) + } + + // Display dereferenced value. + switch { + case nilFound == true: + f.fs.Write(nilAngleBytes) + + case cycleFound == true: + f.fs.Write(circularShortBytes) + + default: + f.ignoreNextType = true + f.format(ve) + } +} + +// format is the main workhorse for providing the Formatter interface. It +// uses the passed reflect value to figure out what kind of object we are +// dealing with and formats it appropriately. It is a recursive function, +// however circular data structures are detected and handled properly. +func (f *formatState) format(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + f.fs.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + f.formatPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !f.ignoreNextType && f.fs.Flag('#') { + f.fs.Write(openParenBytes) + f.fs.Write([]byte(v.Type().String())) + f.fs.Write(closeParenBytes) + } + f.ignoreNextType = false + + // Call Stringer/error interfaces if they exist and the handle methods + // flag is enabled. + if !f.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(f.cs, f.fs, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(f.fs, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(f.fs, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(f.fs, v.Uint(), 10) + + case reflect.Float32: + printFloat(f.fs, v.Float(), 32) + + case reflect.Float64: + printFloat(f.fs, v.Float(), 64) + + case reflect.Complex64: + printComplex(f.fs, v.Complex(), 32) + + case reflect.Complex128: + printComplex(f.fs, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + f.fs.Write(openBracketBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + numEntries := v.Len() + for i := 0; i < numEntries; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(v.Index(i))) + } + } + f.depth-- + f.fs.Write(closeBracketBytes) + + case reflect.String: + f.fs.Write([]byte(v.String())) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + f.fs.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + + f.fs.Write(openMapBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + keys := v.MapKeys() + if f.cs.SortKeys { + sortValues(keys, f.cs) + } + for i, key := range keys { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(key)) + f.fs.Write(colonBytes) + f.ignoreNextType = true + f.format(f.unpackValue(v.MapIndex(key))) + } + } + f.depth-- + f.fs.Write(closeMapBytes) + + case reflect.Struct: + numFields := v.NumField() + f.fs.Write(openBraceBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + vt := v.Type() + for i := 0; i < numFields; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + vtf := vt.Field(i) + if f.fs.Flag('+') || f.fs.Flag('#') { + f.fs.Write([]byte(vtf.Name)) + f.fs.Write(colonBytes) + } + f.format(f.unpackValue(v.Field(i))) + } + } + f.depth-- + f.fs.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(f.fs, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(f.fs, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it if any get added. + default: + format := f.buildDefaultFormat() + if v.CanInterface() { + fmt.Fprintf(f.fs, format, v.Interface()) + } else { + fmt.Fprintf(f.fs, format, v.String()) + } + } +} + +// Format satisfies the fmt.Formatter interface. See NewFormatter for usage +// details. +func (f *formatState) Format(fs fmt.State, verb rune) { + f.fs = fs + + // Use standard formatting for verbs that are not v. + if verb != 'v' { + format := f.constructOrigFormat(verb) + fmt.Fprintf(fs, format, f.value) + return + } + + if f.value == nil { + if fs.Flag('#') { + fs.Write(interfaceBytes) + } + fs.Write(nilAngleBytes) + return + } + + f.format(reflect.ValueOf(f.value)) +} + +// newFormatter is a helper function to consolidate the logic from the various +// public methods which take varying config states. +func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { + fs := &formatState{value: v, cs: cs} + fs.pointers = make(map[uintptr]int) + return fs +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +Printf, Println, or Fprintf. +*/ +func NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(&Config, v) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go new file mode 100644 index 000000000..32c0e3388 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/spew.go @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "fmt" + "io" +) + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the formatted string as a value that satisfies error. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a default Formatter interface returned by NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) +func Print(a ...interface{}) (n int, err error) { + return fmt.Print(convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) +func Println(a ...interface{}) (n int, err error) { + return fmt.Println(convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprint(a ...interface{}) string { + return fmt.Sprint(convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintln(a ...interface{}) string { + return fmt.Sprintln(convertArgs(a)...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a default spew Formatter interface. +func convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = NewFormatter(arg) + } + return formatters +} From 7e141283f64c87a526aec20599e1bd76e8829778 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:09:37 +1000 Subject: [PATCH 30/36] merge branch master --- Gopkg.lock | 1 + README.md | 5 + branch.go | 35 +++++++ branch_list_builder.go | 123 +++++++++++++++++++++++ branches_panel.go | 4 +- commit_message_panel.go | 43 ++++++++ confirmation_panel.go | 18 ++-- files_panel.go | 18 +--- gitcommands.go | 156 ++--------------------------- gui.go | 21 +++- keybindings.go | 111 ++++++++++---------- main.go | 4 +- merge_panel.go | 2 +- {bin => scripts}/push_new_patch.go | 0 status_panel.go | 10 +- utils.go | 54 ++++++++++ view_helpers.go | 34 ++++--- 17 files changed, 388 insertions(+), 251 deletions(-) create mode 100644 branch.go create mode 100644 branch_list_builder.go create mode 100644 commit_message_panel.go rename {bin => scripts}/push_new_patch.go (100%) create mode 100644 utils.go diff --git a/Gopkg.lock b/Gopkg.lock index f15d99700..4323983be 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -288,6 +288,7 @@ "github.com/jesseduffield/gocui", "github.com/tcnksm/go-gitconfig", "gopkg.in/src-d/go-git.v4", + "gopkg.in/src-d/go-git.v4/plumbing", "gopkg.in/src-d/go-git.v4/plumbing/object", ] solver-name = "gps-cdcl" diff --git a/README.md b/README.md index 0bd9b310f..9449977cd 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Are YOU tired of typing every git command directly into the terminal, but you're ![Gif](https://image.ibb.co/mmeXho/optimisedgif.gif) +[Twitch Stream](https://www.twitch.tv/jesseduffield) + ## Installation ### Homebrew @@ -74,3 +76,6 @@ We love your input! Please check out the [contributing guide](CONTRIBUTING.md). ## Work in progress This is still a work in progress so there's still bugs to iron out and as this is my first project in Go the code could no doubt use an increase in quality, but I'll be improving on it whenever I find the time. If you have any feedback feel free to [raise an issue](https://github.com/jesseduffield/lazygit/issues)/[submit a PR](https://github.com/jesseduffield/lazygit/pulls). + +## Social +If you want to see what I (Jesse) am up to in terms of development, follow me on [twitter](https://twitter.com/DuffieldJesse) or watch me program on [twitch](https://www.twitch.tv/jesseduffield) diff --git a/branch.go b/branch.go new file mode 100644 index 000000000..78c2e55aa --- /dev/null +++ b/branch.go @@ -0,0 +1,35 @@ +package main + +import ( + "strings" + + "github.com/fatih/color" +) + +// Branch : A git branch +type Branch struct { + Name string + Recency string +} + +func (b *Branch) getDisplayString() string { + return withPadding(b.Recency, 4) + coloredString(b.Name, b.getColor()) +} + +func (b *Branch) getColor() color.Attribute { + switch b.getType() { + case "feature": + return color.FgGreen + case "bugfix": + return color.FgYellow + case "hotfix": + return color.FgRed + default: + return color.FgWhite + } +} + +// expected to return feature/bugfix/hotfix or blank string +func (b *Branch) getType() string { + return strings.Split(b.Name, "/")[0] +} diff --git a/branch_list_builder.go b/branch_list_builder.go new file mode 100644 index 000000000..113a5a44a --- /dev/null +++ b/branch_list_builder.go @@ -0,0 +1,123 @@ +package main + +import ( + "regexp" + "strings" + + "gopkg.in/src-d/go-git.v4/plumbing" +) + +// context: +// we want to only show 'safe' branches (ones that haven't e.g. been deleted) +// which `git branch -a` gives us, but we also want the recency data that +// git reflog gives us. +// So we get the HEAD, then append get the reflog branches that intersect with +// our safe branches, then add the remaining safe branches, ensuring uniqueness +// along the way + +type branchListBuilder struct{} + +func newBranchListBuilder() *branchListBuilder { + return &branchListBuilder{} +} + +func (b *branchListBuilder) obtainCurrentBranch() Branch { + // I used go-git for this, but that breaks if you've just done a git init, + // even though you're on 'master' + branchName, _ := runDirectCommand("git symbolic-ref --short HEAD") + return Branch{Name: strings.TrimSpace(branchName), Recency: " *"} +} + +func (*branchListBuilder) obtainReflogBranches() []Branch { + branches := make([]Branch, 0) + rawString, err := runDirectCommand("git reflog -n100 --pretty='%cr|%gs' --grep-reflog='checkout: moving' HEAD") + if err != nil { + return branches + } + + branchLines := splitLines(rawString) + for _, line := range branchLines { + timeNumber, timeUnit, branchName := branchInfoFromLine(line) + timeUnit = abbreviatedTimeUnit(timeUnit) + branch := Branch{Name: branchName, Recency: timeNumber + timeUnit} + branches = append(branches, branch) + } + return branches +} + +func (b *branchListBuilder) obtainSafeBranches() []Branch { + branches := make([]Branch, 0) + + bIter, err := r.Branches() + if err != nil { + panic(err) + } + err = bIter.ForEach(func(b *plumbing.Reference) error { + name := b.Name().Short() + branches = append(branches, Branch{Name: name}) + return nil + }) + + return branches +} + +func (b *branchListBuilder) appendNewBranches(finalBranches, newBranches, existingBranches []Branch, included bool) []Branch { + for _, newBranch := range newBranches { + if included == branchIncluded(newBranch.Name, existingBranches) { + finalBranches = append(finalBranches, newBranch) + } + + } + return finalBranches +} + +func (b *branchListBuilder) build() []Branch { + branches := make([]Branch, 0) + head := b.obtainCurrentBranch() + safeBranches := b.obtainSafeBranches() + if len(safeBranches) == 0 { + return append(branches, head) + } + reflogBranches := b.obtainReflogBranches() + reflogBranches = uniqueByName(append([]Branch{head}, reflogBranches...)) + + branches = b.appendNewBranches(branches, reflogBranches, safeBranches, true) + branches = b.appendNewBranches(branches, safeBranches, branches, false) + + return branches +} + +func uniqueByName(branches []Branch) []Branch { + finalBranches := make([]Branch, 0) + for _, branch := range branches { + if branchIncluded(branch.Name, finalBranches) { + continue + } + finalBranches = append(finalBranches, branch) + } + return finalBranches +} + +// A line will have the form '10 days ago master' so we need to strip out the +// useful information from that into timeNumber, timeUnit, and branchName +func branchInfoFromLine(line string) (string, string, string) { + r := regexp.MustCompile("\\|.*\\s") + line = r.ReplaceAllString(line, " ") + words := strings.Split(line, " ") + return words[0], words[1], words[3] +} + +func abbreviatedTimeUnit(timeUnit string) string { + r := regexp.MustCompile("s$") + timeUnit = r.ReplaceAllString(timeUnit, "") + timeUnitMap := map[string]string{ + "hour": "h", + "minute": "m", + "second": "s", + "week": "w", + "year": "y", + "day": "d", + "month": "m", + } + return timeUnitMap[timeUnit] +} diff --git a/branches_panel.go b/branches_panel.go index 0b8508a3d..3102f0c28 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -91,7 +91,7 @@ func handleBranchSelect(g *gocui.Gui, v *gocui.View) error { } go func() { branch := getSelectedBranch(v) - diff, err := getBranchGraph(branch.Name, branch.BaseBranch) + diff, err := getBranchGraph(branch.Name) if err != nil && strings.HasPrefix(diff, "fatal: ambiguous argument") { diff = "There is no tracking for this branch" } @@ -111,7 +111,7 @@ func refreshBranches(g *gocui.Gui) error { state.Branches = getGitBranches() v.Clear() for _, branch := range state.Branches { - fmt.Fprintln(v, branch.DisplayString) + fmt.Fprintln(v, branch.getDisplayString()) } resetOrigin(v) return refreshStatus(g) diff --git a/commit_message_panel.go b/commit_message_panel.go new file mode 100644 index 000000000..49551c1eb --- /dev/null +++ b/commit_message_panel.go @@ -0,0 +1,43 @@ +package main + +import "github.com/jesseduffield/gocui" + +func handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { + message := trimmedContent(v) + if message == "" { + return createErrorPanel(g, "You cannot commit without a commit message") + } + if output, err := gitCommit(g, message); err != nil { + if err == errNoUsername { + return createErrorPanel(g, err.Error()) + } + return createErrorPanel(g, output) + } + refreshFiles(g) + g.SetViewOnBottom("commitMessage") + switchFocus(g, v, getFilesView(g)) + return refreshCommits(g) +} + +func handleCommitClose(g *gocui.Gui, v *gocui.View) error { + g.SetViewOnBottom("commitMessage") + return switchFocus(g, v, getFilesView(g)) +} + +func handleNewlineCommitMessage(g *gocui.Gui, v *gocui.View) error { + // resising ahead of time so that the top line doesn't get hidden to make + // room for the cursor on the second line + x0, y0, x1, y1 := getConfirmationPanelDimensions(g, v.Buffer()) + if _, err := g.SetView("commitMessage", x0, y0, x1, y1+1, 0); err != nil { + if err != gocui.ErrUnknownView { + return err + } + } + + v.EditNewLine() + return nil +} + +func handleCommitFocused(g *gocui.Gui, v *gocui.View) error { + return renderString(g, "options", "esc: close, enter: confirm") +} diff --git a/confirmation_panel.go b/confirmation_panel.go index 362b75c49..563db72d8 100644 --- a/confirmation_panel.go +++ b/confirmation_panel.go @@ -56,6 +56,7 @@ func getConfirmationPanelDimensions(g *gocui.Gui, prompt string) (int, int, int, } func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, handleConfirm func(*gocui.Gui, *gocui.View) error) error { + g.SetViewOnBottom("commitMessage") // only need to fit one line x0, y0, x1, y1 := getConfirmationPanelDimensions(g, "") if confirmationView, err := g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { @@ -63,11 +64,8 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, hand return err } - g.Cursor = true - confirmationView.Editable = true confirmationView.Title = title - confirmationView.FgColor = gocui.ColorWhite switchFocus(g, currentView, confirmationView) return setKeyBindings(g, handleConfirm, nil) } @@ -75,6 +73,7 @@ func createPromptPanel(g *gocui.Gui, currentView *gocui.View, title string, hand } func createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error { + g.SetViewOnBottom("commitMessage") g.Update(func(g *gocui.Gui) error { // delete the existing confirmation panel if it exists if view, _ := g.View("confirmation"); view != nil { @@ -141,15 +140,20 @@ func trimTrailingNewline(str string) string { return str } -func resizeConfirmationPanel(g *gocui.Gui) error { +func resizeConfirmationPanel(g *gocui.Gui, viewName string) error { // If the confirmation panel is already displayed, just resize the width, // otherwise continue - if v, err := g.View("confirmation"); err == nil { + g.Update(func(g *gocui.Gui) error { + v, err := g.View(viewName) + if err != nil { + return nil + } content := trimTrailingNewline(v.Buffer()) x0, y0, x1, y1 := getConfirmationPanelDimensions(g, content) - if _, err = g.SetView("confirmation", x0, y0, x1, y1, 0); err != nil { + if _, err := g.SetView(viewName, x0, y0, x1, y1, 0); err != nil { return err } - } + return nil + }) return nil } diff --git a/files_panel.go b/files_panel.go index e645c6cb6..2d7406c45 100644 --- a/files_panel.go +++ b/files_panel.go @@ -177,19 +177,11 @@ func handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { if len(stagedFiles(state.GitFiles)) == 0 && !state.HasMergeConflicts { return createErrorPanel(g, "There are no staged files to commit") } - createPromptPanel(g, filesView, "Commit message", func(g *gocui.Gui, v *gocui.View) error { - message := trimmedContent(v) - if message == "" { - return createErrorPanel(g, "You cannot commit without a commit message") - } - if output, err := gitCommit(g, message); err != nil { - if err == errNoUsername { - return createErrorPanel(g, err.Error()) - } - return createErrorPanel(g, output) - } - refreshFiles(g) - return refreshCommits(g) + commitMessageView := getCommitMessageView(g) + g.Update(func(g *gocui.Gui) error { + g.SetViewOnTop("commitMessage") + switchFocus(g, filesView, commitMessageView) + return nil }) return nil } diff --git a/gitcommands.go b/gitcommands.go index 3db1df1ee..f157fa79c 100644 --- a/gitcommands.go +++ b/gitcommands.go @@ -7,11 +7,9 @@ import ( "fmt" "os" "os/exec" - "regexp" "strings" "time" - "github.com/fatih/color" "github.com/jesseduffield/gocui" gitconfig "github.com/tcnksm/go-gitconfig" git "gopkg.in/src-d/go-git.v4" @@ -19,9 +17,6 @@ import ( ) var ( - // ErrNoCheckedOutBranch : When we have no checked out branch - ErrNoCheckedOutBranch = errors.New("No currently checked out branch") - // ErrNoOpenCommand : When we don't know which command to use to open a file ErrNoOpenCommand = errors.New("Unsure what command to use to open this file") ) @@ -38,14 +33,6 @@ type GitFile struct { DisplayString string } -// Branch : A git branch -type Branch struct { - Name string - Type string - BaseBranch string - DisplayString string -} - // Commit : A git commit type Commit struct { Sha string @@ -144,29 +131,6 @@ func branchStringParts(branchString string) (string, string) { return splitBranchName[0], splitBranchName[1] } -// branchPropertiesFromName : returns branch type, base, and color -func branchPropertiesFromName(name string) (string, string, color.Attribute) { - if strings.Contains(name, "feature/") { - return "feature", "develop", color.FgGreen - } else if strings.Contains(name, "bugfix/") { - return "bugfix", "develop", color.FgYellow - } else if strings.Contains(name, "hotfix/") { - return "hotfix", "master", color.FgRed - } - return "other", name, color.FgWhite -} - -func coloredString(str string, colour *color.Color) string { - return colour.SprintFunc()(fmt.Sprint(str)) -} - -func withPadding(str string, padding int) string { - if padding-len(str) < 0 { - return str - } - return str + strings.Repeat(" ", padding-len(str)) -} - // TODO: DRY up this function and getGitBranches func getGitStashEntries() []StashEntry { stashEntries := make([]StashEntry, 0) @@ -325,12 +289,8 @@ func runSubProcess(g *gocui.Gui, cmdName string, commandArgs ...string) { }) } -func getBranchGraph(branch string, baseBranch string) (string, error) { +func getBranchGraph(branch string) (string, error) { return runCommand("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 " + branch) - - // Leaving this guy commented out in case there's backlash from the design - // change and I want to make this configurable - // return runCommand("git log -p -30 --color --no-merges " + branch) } func verifyInGitRepo() { @@ -476,11 +436,7 @@ func gitPull() (string, error) { } func gitPush() (string, error) { - branchName := gitCurrentBranchName() - if branchName == "" { - return "", ErrNoCheckedOutBranch - } - return runDirectCommand("git push -u origin " + branchName) + return runDirectCommand("git push -u origin " + state.Branches[0].Name) } func gitSquashPreviousTwoCommits(message string) (string, error) { @@ -562,120 +518,20 @@ func gitCommitsToPush() []string { return splitLines(pushables) } -func gitCurrentBranchName() string { - branchName, err := runDirectCommand("git symbolic-ref --short HEAD") - // if there is an error, assume there are no branches yet - if err != nil { - return "" - } - return strings.TrimSpace(branchName) -} - -// A line will have the form '10 days ago master' so we need to strip out the -// useful information from that into timeNumber, timeUnit, and branchName -func branchInfoFromLine(line string) (string, string, string) { - r := regexp.MustCompile("\\|.*\\s") - line = r.ReplaceAllString(line, " ") - words := strings.Split(line, " ") - return words[0], words[1], words[3] -} - -func abbreviatedTimeUnit(timeUnit string) string { - r := regexp.MustCompile("s$") - timeUnit = r.ReplaceAllString(timeUnit, "") - timeUnitMap := map[string]string{ - "hour": "h", - "minute": "m", - "second": "s", - "week": "w", - "year": "y", - "day": "d", - "month": "m", - } - return timeUnitMap[timeUnit] -} - -func getBranches() []Branch { - branches := make([]Branch, 0) - rawString, err := runDirectCommand("git reflog -n100 --pretty='%cr|%gs' --grep-reflog='checkout: moving' HEAD") - if err != nil { - return branches - } - - branchLines := splitLines(rawString) - for i, line := range branchLines { - timeNumber, timeUnit, branchName := branchInfoFromLine(line) - timeUnit = abbreviatedTimeUnit(timeUnit) - - if branchAlreadyStored(branchName, branches) { - continue - } - - branch := constructBranch(timeNumber+timeUnit, branchName, i) - branches = append(branches, branch) - } - return branches -} - -func constructBranch(prefix, name string, index int) Branch { - branchType, branchBase, colourAttr := branchPropertiesFromName(name) - if index == 0 { - prefix = " *" - } - colour := color.New(colourAttr) - displayString := withPadding(prefix, 4) + coloredString(name, colour) - return Branch{ - Name: name, - Type: branchType, - BaseBranch: branchBase, - DisplayString: displayString, - } -} - func getGitBranches() []Branch { - // check if there are any branches - branchCheck, _ := runCommand("git branch") - if branchCheck == "" { - return []Branch{constructBranch("", gitCurrentBranchName(), 0)} - } - branches := getBranches() - if len(branches) == 0 { - branches = append(branches, constructBranch("", gitCurrentBranchName(), 0)) - } - branches = getAndMergeFetchedBranches(branches) - return branches + builder := newBranchListBuilder() + return builder.build() } -func branchAlreadyStored(branchName string, branches []Branch) bool { +func branchIncluded(branchName string, branches []Branch) bool { for _, existingBranch := range branches { - if existingBranch.Name == branchName { + if strings.ToLower(existingBranch.Name) == strings.ToLower(branchName) { return true } } return false } -// here branches contains all the branches that we've checked out, along with -// the recency. In this function we append the branches that are in our heads -// directory i.e. things we've fetched but haven't necessarily checked out. -// Worth mentioning this has nothing to do with the 'git merge' operation -func getAndMergeFetchedBranches(branches []Branch) []Branch { - rawString, err := runDirectCommand("git branch --sort=-committerdate --no-color") - if err != nil { - return branches - } - branchLines := splitLines(rawString) - for _, line := range branchLines { - line = strings.Replace(line, "* ", "", -1) - line = strings.TrimSpace(line) - if branchAlreadyStored(line, branches) { - continue - } - branches = append(branches, constructBranch("", line, len(branches))) - } - return branches -} - func gitResetHard() error { return w.Reset(&git.ResetOptions{Mode: git.HardReset}) } diff --git a/gui.go b/gui.go index 4d5d0b679..033dbe06a 100644 --- a/gui.go +++ b/gui.go @@ -199,12 +199,27 @@ func layout(g *gocui.Gui) error { if err != gocui.ErrUnknownView { return err } - v.BgColor = gocui.ColorDefault v.FgColor = gocui.ColorBlue v.Frame = false } - if err = resizeConfirmationPanel(g); err != nil { + if getCommitMessageView(g) == nil { + // doesn't matter where this view starts because it will be hidden + if commitMessageView, err := g.SetView("commitMessage", 0, 0, width, height, 0); err != nil { + if err != gocui.ErrUnknownView { + return err + } + g.SetViewOnBottom("commitMessage") + commitMessageView.Title = "Commit message" + commitMessageView.FgColor = gocui.ColorWhite + commitMessageView.Editable = true + } + } + + if err = resizeConfirmationPanel(g, "commitMessage"); err != nil { + return err + } + if err = resizeConfirmationPanel(g, "confirmation"); err != nil { return err } @@ -261,6 +276,8 @@ func run() (err error) { } defer g.Close() + g.FgColor = gocui.ColorDefault + goEvery(g, time.Second*60, fetch) goEvery(g, time.Second*10, refreshFiles) goEvery(g, time.Millisecond*10, updateLoader) diff --git a/keybindings.go b/keybindings.go index 292f63007..401a5a477 100644 --- a/keybindings.go +++ b/keybindings.go @@ -14,66 +14,69 @@ type Binding struct { func keybindings(g *gocui.Gui) error { bindings := []Binding{ - Binding{ViewName: "", Key: 'q', Modifier: gocui.ModNone, Handler: quit}, - Binding{ViewName: "", Key: gocui.KeyCtrlC, Modifier: gocui.ModNone, Handler: quit}, - Binding{ViewName: "", Key: gocui.KeyPgup, Modifier: gocui.ModNone, Handler: scrollUpMain}, - Binding{ViewName: "", Key: gocui.KeyPgdn, Modifier: gocui.ModNone, Handler: scrollDownMain}, - Binding{ViewName: "", Key: 'P', Modifier: gocui.ModNone, Handler: pushFiles}, - Binding{ViewName: "", Key: 'p', Modifier: gocui.ModNone, Handler: pullFiles}, - Binding{ViewName: "", Key: 'R', Modifier: gocui.ModNone, Handler: handleRefresh}, - Binding{ViewName: "files", Key: 'c', Modifier: gocui.ModNone, Handler: handleCommitPress}, - Binding{ViewName: "files", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleFilePress}, - Binding{ViewName: "files", Key: 'd', Modifier: gocui.ModNone, Handler: handleFileRemove}, - Binding{ViewName: "files", Key: 'm', Modifier: gocui.ModNone, Handler: handleSwitchToMerge}, - Binding{ViewName: "files", Key: 'e', Modifier: gocui.ModNone, Handler: handleFileEdit}, - Binding{ViewName: "files", Key: 'o', Modifier: gocui.ModNone, Handler: handleFileOpen}, - Binding{ViewName: "files", Key: 's', Modifier: gocui.ModNone, Handler: handleSublimeFileOpen}, - Binding{ViewName: "files", Key: 'v', Modifier: gocui.ModNone, Handler: handleVsCodeFileOpen}, - Binding{ViewName: "files", Key: 'i', Modifier: gocui.ModNone, Handler: handleIgnoreFile}, - Binding{ViewName: "files", Key: 'r', Modifier: gocui.ModNone, Handler: handleRefreshFiles}, - Binding{ViewName: "files", Key: 'S', Modifier: gocui.ModNone, Handler: handleStashSave}, - Binding{ViewName: "files", Key: 'a', Modifier: gocui.ModNone, Handler: handleAbortMerge}, - Binding{ViewName: "files", Key: 't', Modifier: gocui.ModNone, Handler: handleAddPatch}, - Binding{ViewName: "files", Key: 'D', Modifier: gocui.ModNone, Handler: handleResetHard}, - Binding{ViewName: "main", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleEscapeMerge}, - Binding{ViewName: "main", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handlePickHunk}, - Binding{ViewName: "main", Key: 'b', Modifier: gocui.ModNone, Handler: handlePickBothHunks}, - Binding{ViewName: "main", Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, - Binding{ViewName: "main", Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, - Binding{ViewName: "main", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: handleSelectTop}, - Binding{ViewName: "main", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: handleSelectBottom}, - Binding{ViewName: "main", Key: 'h', Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, - Binding{ViewName: "main", Key: 'l', Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, - Binding{ViewName: "main", Key: 'k', Modifier: gocui.ModNone, Handler: handleSelectTop}, - Binding{ViewName: "main", Key: 'j', Modifier: gocui.ModNone, Handler: handleSelectBottom}, - Binding{ViewName: "main", Key: 'z', Modifier: gocui.ModNone, Handler: handlePopFileSnapshot}, - Binding{ViewName: "branches", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleBranchPress}, - Binding{ViewName: "branches", Key: 'c', Modifier: gocui.ModNone, Handler: handleCheckoutByName}, - Binding{ViewName: "branches", Key: 'F', Modifier: gocui.ModNone, Handler: handleForceCheckout}, - Binding{ViewName: "branches", Key: 'n', Modifier: gocui.ModNone, Handler: handleNewBranch}, - Binding{ViewName: "branches", Key: 'm', Modifier: gocui.ModNone, Handler: handleMerge}, - Binding{ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, - Binding{ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, - Binding{ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, Handler: handleResetToCommit}, - Binding{ViewName: "commits", Key: 'f', Modifier: gocui.ModNone, Handler: handleCommitFixup}, - Binding{ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, - Binding{ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, - Binding{ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, + {ViewName: "", Key: 'q', Modifier: gocui.ModNone, Handler: quit}, + {ViewName: "", Key: gocui.KeyCtrlC, Modifier: gocui.ModNone, Handler: quit}, + {ViewName: "", Key: gocui.KeyPgup, Modifier: gocui.ModNone, Handler: scrollUpMain}, + {ViewName: "", Key: gocui.KeyPgdn, Modifier: gocui.ModNone, Handler: scrollDownMain}, + {ViewName: "", Key: 'P', Modifier: gocui.ModNone, Handler: pushFiles}, + {ViewName: "", Key: 'p', Modifier: gocui.ModNone, Handler: pullFiles}, + {ViewName: "", Key: 'R', Modifier: gocui.ModNone, Handler: handleRefresh}, + {ViewName: "files", Key: 'c', Modifier: gocui.ModNone, Handler: handleCommitPress}, + {ViewName: "files", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleFilePress}, + {ViewName: "files", Key: 'd', Modifier: gocui.ModNone, Handler: handleFileRemove}, + {ViewName: "files", Key: 'm', Modifier: gocui.ModNone, Handler: handleSwitchToMerge}, + {ViewName: "files", Key: 'e', Modifier: gocui.ModNone, Handler: handleFileEdit}, + {ViewName: "files", Key: 'o', Modifier: gocui.ModNone, Handler: handleFileOpen}, + {ViewName: "files", Key: 's', Modifier: gocui.ModNone, Handler: handleSublimeFileOpen}, + {ViewName: "files", Key: 'v', Modifier: gocui.ModNone, Handler: handleVsCodeFileOpen}, + {ViewName: "files", Key: 'i', Modifier: gocui.ModNone, Handler: handleIgnoreFile}, + {ViewName: "files", Key: 'r', Modifier: gocui.ModNone, Handler: handleRefreshFiles}, + {ViewName: "files", Key: 'S', Modifier: gocui.ModNone, Handler: handleStashSave}, + {ViewName: "files", Key: 'a', Modifier: gocui.ModNone, Handler: handleAbortMerge}, + {ViewName: "files", Key: 't', Modifier: gocui.ModNone, Handler: handleAddPatch}, + {ViewName: "files", Key: 'D', Modifier: gocui.ModNone, Handler: handleResetHard}, + {ViewName: "main", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleEscapeMerge}, + {ViewName: "main", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handlePickHunk}, + {ViewName: "main", Key: 'b', Modifier: gocui.ModNone, Handler: handlePickBothHunks}, + {ViewName: "main", Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, + {ViewName: "main", Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, + {ViewName: "main", Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: handleSelectTop}, + {ViewName: "main", Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: handleSelectBottom}, + {ViewName: "main", Key: 'h', Modifier: gocui.ModNone, Handler: handleSelectPrevConflict}, + {ViewName: "main", Key: 'l', Modifier: gocui.ModNone, Handler: handleSelectNextConflict}, + {ViewName: "main", Key: 'k', Modifier: gocui.ModNone, Handler: handleSelectTop}, + {ViewName: "main", Key: 'j', Modifier: gocui.ModNone, Handler: handleSelectBottom}, + {ViewName: "main", Key: 'z', Modifier: gocui.ModNone, Handler: handlePopFileSnapshot}, + {ViewName: "branches", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleBranchPress}, + {ViewName: "branches", Key: 'c', Modifier: gocui.ModNone, Handler: handleCheckoutByName}, + {ViewName: "branches", Key: 'F', Modifier: gocui.ModNone, Handler: handleForceCheckout}, + {ViewName: "branches", Key: 'n', Modifier: gocui.ModNone, Handler: handleNewBranch}, + {ViewName: "branches", Key: 'm', Modifier: gocui.ModNone, Handler: handleMerge}, + {ViewName: "commits", Key: 's', Modifier: gocui.ModNone, Handler: handleCommitSquashDown}, + {ViewName: "commits", Key: 'r', Modifier: gocui.ModNone, Handler: handleRenameCommit}, + {ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, Handler: handleResetToCommit}, + {ViewName: "commits", Key: 'f', Modifier: gocui.ModNone, Handler: handleCommitFixup}, + {ViewName: "stash", Key: gocui.KeySpace, Modifier: gocui.ModNone, Handler: handleStashApply}, + {ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, Handler: handleStashPop}, + {ViewName: "stash", Key: 'd', Modifier: gocui.ModNone, Handler: handleStashDrop}, + {ViewName: "commitMessage", Key: gocui.KeyEnter, Modifier: gocui.ModNone, Handler: handleCommitConfirm}, + {ViewName: "commitMessage", Key: gocui.KeyEsc, Modifier: gocui.ModNone, Handler: handleCommitClose}, + {ViewName: "commitMessage", Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: handleNewlineCommitMessage}, } // Would make these keybindings global but that interferes with editing // input in the confirmation panel for _, viewName := range []string{"files", "branches", "commits", "stash"} { bindings = append(bindings, []Binding{ - Binding{ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: previousView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: cursorUp}, - Binding{ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: cursorDown}, - Binding{ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: previousView}, - Binding{ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: nextView}, - Binding{ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: cursorUp}, - Binding{ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: cursorDown}, + {ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: previousView}, + {ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: cursorUp}, + {ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: cursorDown}, + {ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: previousView}, + {ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: nextView}, + {ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: cursorUp}, + {ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: cursorDown}, }...) } diff --git a/main.go b/main.go index 426f47eee..aec4051bf 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,7 @@ var ( versionFlag = flag.Bool("v", false, "Print the current version") w *git.Worktree + r *git.Repository ) func homeDirectory() string { @@ -98,7 +99,8 @@ func fallbackVersion() string { } func setupWorktree() { - r, err := git.PlainOpen(".") + var err error + r, err = git.PlainOpen(".") if err != nil { panic(err) } diff --git a/merge_panel.go b/merge_panel.go index 6602dbbf1..f5ca12a23 100644 --- a/merge_panel.go +++ b/merge_panel.go @@ -56,7 +56,7 @@ func coloredConflictFile(content string, conflicts []conflict, conflictIndex int if i == conflict.end && len(remainingConflicts) > 0 { conflict, remainingConflicts = shiftConflict(remainingConflicts) } - outputBuffer.WriteString(coloredString(line, colour) + "\n") + outputBuffer.WriteString(coloredStringDirect(line, colour) + "\n") } return outputBuffer.String(), nil } diff --git a/bin/push_new_patch.go b/scripts/push_new_patch.go similarity index 100% rename from bin/push_new_patch.go rename to scripts/push_new_patch.go diff --git a/status_panel.go b/status_panel.go index 393c62344..f3fcb8078 100644 --- a/status_panel.go +++ b/status_panel.go @@ -24,16 +24,16 @@ func refreshStatus(g *gocui.Gui) error { return err } if state.HasMergeConflicts { - colour := color.New(color.FgYellow) - fmt.Fprint(v, coloredString(" (merging)", colour)) + fmt.Fprint(v, coloredString(" (merging)", color.FgYellow)) } + if len(branches) == 0 { return nil } branch := branches[0] - // utilising the fact these all have padding to only grab the name - // from the display string with the existing coloring applied - fmt.Fprint(v, " "+branch.DisplayString[4:]) + name := coloredString(branch.Name, branch.getColor()) + repo := getCurrentProject() + fmt.Fprint(v, " "+repo+" → "+name) return nil }) diff --git a/utils.go b/utils.go new file mode 100644 index 000000000..e2de46233 --- /dev/null +++ b/utils.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/fatih/color" + "github.com/jesseduffield/gocui" +) + +func splitLines(multilineString string) []string { + multilineString = strings.Replace(multilineString, "\r", "", -1) + if multilineString == "" || multilineString == "\n" { + return make([]string, 0) + } + lines := strings.Split(multilineString, "\n") + if lines[len(lines)-1] == "" { + return lines[:len(lines)-1] + } + return lines +} + +func trimmedContent(v *gocui.View) string { + return strings.TrimSpace(v.Buffer()) +} + +func withPadding(str string, padding int) string { + if padding-len(str) < 0 { + return str + } + return str + strings.Repeat(" ", padding-len(str)) +} + +func coloredString(str string, colorAttribute color.Attribute) string { + colour := color.New(colorAttribute) + return coloredStringDirect(str, colour) +} + +// used for aggregating a few color attributes rather than just sending a single one +func coloredStringDirect(str string, colour *color.Color) string { + return colour.SprintFunc()(fmt.Sprint(str)) +} + +// used to get the project name +func getCurrentProject() string { + pwd, err := os.Getwd() + if err != nil { + log.Fatalln(err.Error()) + } + return filepath.Base(pwd) +} diff --git a/view_helpers.go b/view_helpers.go index 0d7d7618c..b28e84efb 100644 --- a/view_helpers.go +++ b/view_helpers.go @@ -75,6 +75,8 @@ func newLineFocused(g *gocui.Gui, v *gocui.View) error { return handleBranchSelect(g, v) case "confirmation": return nil + case "commitMessage": + return handleCommitFocused(g, v) case "main": // TODO: pull this out into a 'view focused' function refreshMergePanel(g) @@ -121,10 +123,6 @@ func getItemPosition(v *gocui.View) int { return oy + cy } -func trimmedContent(v *gocui.View) string { - return strings.TrimSpace(v.Buffer()) -} - func cursorUp(g *gocui.Gui, v *gocui.View) error { // swallowing cursor movements in main // TODO: pull this out @@ -199,18 +197,6 @@ func renderString(g *gocui.Gui, viewName, s string) error { return nil } -func splitLines(multilineString string) []string { - multilineString = strings.Replace(multilineString, "\r", "", -1) - if multilineString == "" || multilineString == "\n" { - return make([]string, 0) - } - lines := strings.Split(multilineString, "\n") - if lines[len(lines)-1] == "" { - return lines[:len(lines)-1] - } - return lines -} - func optionsMapToString(optionsMap map[string]string) string { optionsArray := make([]string, 0) for key, description := range optionsMap { @@ -231,3 +217,19 @@ func loader() string { index := nanos / 50000000 % int64(len(characters)) return characters[index : index+1] } + +// TODO: refactor properly +func getFilesView(g *gocui.Gui) *gocui.View { + v, _ := g.View("files") + return v +} + +func getCommitsView(g *gocui.Gui) *gocui.View { + v, _ := g.View("commits") + return v +} + +func getCommitMessageView(g *gocui.Gui) *gocui.View { + v, _ := g.View("commitMessage") + return v +} From 5c185572a754b9dc1bb1c918f136b4acefc53976 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:12:30 +1000 Subject: [PATCH 31/36] delete test file that was accidentally committed --- ZHgalGrWSF | 1 - 1 file changed, 1 deletion(-) delete mode 100644 ZHgalGrWSF diff --git a/ZHgalGrWSF b/ZHgalGrWSF deleted file mode 100644 index f1f0d2371..000000000 --- a/ZHgalGrWSF +++ /dev/null @@ -1 +0,0 @@ -GaUMygWjJa \ No newline at end of file From 000a7097832a65c2b8dbdf7a96b93251071dd2c0 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:22:41 +1000 Subject: [PATCH 32/36] update test repo generators including test for unicode characters --- test/lots_of_commits.sh | 2 ++ test/unicode_characters.sh | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100755 test/unicode_characters.sh diff --git a/test/lots_of_commits.sh b/test/lots_of_commits.sh index d85034f4e..6a92d32e2 100755 --- a/test/lots_of_commits.sh +++ b/test/lots_of_commits.sh @@ -26,3 +26,5 @@ while [ $i -le $end ]; do i=$(($i+1)) done + +echo "unstaged change" > file100 diff --git a/test/unicode_characters.sh b/test/unicode_characters.sh new file mode 100755 index 000000000..92640d52f --- /dev/null +++ b/test/unicode_characters.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# this script will make a repo with a master and develop branch, where we end up +# on the master branch and if we try and merge master we get a merge conflict + +# call this command from the test directory: +# ./generate_basic_repo.sh; cd testrepo; gg; cd .. + +# -e means exit if something fails +# -x means print out simple commands before running them +set -ex + +reponame="testrepo" + +rm -rf ${reponame} +mkdir ${reponame} +cd ${reponame} + +git init + +# Add some ansi, unicode, zero width joiner caracters +cat <> charstest.txt +ANSI Œ (U+0152 Œ Latin capital ligature OE Latin Extended-A) + ¥ (0xA5 U+00A5 ¥ yes sign) + ƒ (0x83 U+0192 ƒ Latin small letter f with hook) +ZWJ https://en.wikipedia.org/wiki/Zero-width_joiner / https://unicode.org/Public/emoji/4.0/emoji-zwj-sequences.txt 👶(👨‍👦) +UNICODE ☆ 🤓 え 术 +EOT +git add charstest.txt +git commit -m "Test chars Œ¥ƒ👶👨‍👦☆ 🤓 え 术 commit" +echo "我喜歡編碼" >> charstest.txt +echo "நான் குறியீடு விரும்புகிறேன்" >> charstest.txt +git add charstest.txt +git commit -m "Test chars 我喜歡編碼 நான் குறியீடு விரும்புகிறேன் commit" + From 5c8f0d4c9dc1b5d441e6d2b2998c2daeb1a77653 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:23:57 +1000 Subject: [PATCH 33/36] gitignore test repo --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5210291e4..4a37f6ec0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ extra/lgit.rb notes/go.notes TODO.notes TODO.md +test/testrepo/ From 753ca75e55f134deb68a463aff49ea34e47002f9 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:24:24 +1000 Subject: [PATCH 34/36] clear commit panel after confirming --- commit_message_panel.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commit_message_panel.go b/commit_message_panel.go index 49551c1eb..baef870cf 100644 --- a/commit_message_panel.go +++ b/commit_message_panel.go @@ -14,6 +14,8 @@ func handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { return createErrorPanel(g, output) } refreshFiles(g) + v.Clear() + v.SetCursor(0, 0) g.SetViewOnBottom("commitMessage") switchFocus(g, v, getFilesView(g)) return refreshCommits(g) From 62a231abb78db5f807ff55ad77f39bcf633539b2 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:31:55 +1000 Subject: [PATCH 35/36] handle commit select on any commits panel refresh --- commits_panel.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/commits_panel.go b/commits_panel.go index 2b9ccbf87..1a9976ffe 100644 --- a/commits_panel.go +++ b/commits_panel.go @@ -34,6 +34,9 @@ func refreshCommits(g *gocui.Gui) error { white.Fprintln(v, commit.Name) } refreshStatus(g) + if g.CurrentView().Name() == "commits" { + handleCommitSelect(g, v) + } return nil }) return nil @@ -135,8 +138,7 @@ func handleCommitFixup(g *gocui.Gui, v *gocui.View) error { if err := refreshCommits(g); err != nil { panic(err) } - refreshStatus(g) - return handleCommitSelect(g, v) + return refreshStatus(g) }, nil) return nil } From 9626ebdf3577090cff24fab82880fe9d330adb59 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 11 Aug 2018 15:45:38 +1000 Subject: [PATCH 36/36] correct typo in keybinding for delete branch --- branches_panel.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/branches_panel.go b/branches_panel.go index 64dba4f55..a73d28bb3 100644 --- a/branches_panel.go +++ b/branches_panel.go @@ -51,7 +51,7 @@ func handleNewBranch(g *gocui.Gui, v *gocui.View) error { return nil } -func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { +func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { checkedOutBranch := state.Branches[0] selectedBranch := getSelectedBranch(v) if checkedOutBranch.Name == selectedBranch.Name { @@ -59,13 +59,12 @@ func handleDeleteBranch(g *gocui.Gui, v *gocui.View) error { } return createConfirmationPanel(g, v, "Delete Branch", "Are you sure you want delete the branch "+selectedBranch.Name+" ?", func(g *gocui.Gui, v *gocui.View) error { if output, err := gitDeleteBranch(selectedBranch.Name); err != nil { - return createErrorPanel(g, output) - } - return refreshSidePanels(g) - }, nil) + return createErrorPanel(g, output) + } + return refreshSidePanels(g) + }, nil) } - func handleMerge(g *gocui.Gui, v *gocui.View) error { checkedOutBranch := state.Branches[0] selectedBranch := getSelectedBranch(v) @@ -91,7 +90,7 @@ func renderBranchesOptions(g *gocui.Gui) error { "m": "merge", "c": "checkout by name", "n": "new branch", - "d": "delte branch", + "d": "delete branch", "← → ↑ ↓": "navigate", }) }