Added a global cache lock
diff --git a/action/get.go b/action/get.go
index 5665ef6..58384de 100644
--- a/action/get.go
+++ b/action/get.go
@@ -5,6 +5,7 @@
"path/filepath"
"strings"
+ "github.com/Masterminds/glide/cache"
"github.com/Masterminds/glide/cfg"
"github.com/Masterminds/glide/godep"
"github.com/Masterminds/glide/msg"
@@ -17,6 +18,10 @@
//
// This includes resolving dependency resolution and re-generating the lock file.
func Get(names []string, installer *repo.Installer, insecure, skipRecursive, strip, stripVendor bool) {
+ if installer.UseCache {
+ cache.SystemLock()
+ }
+
base := gpath.Basepath()
EnsureGopath()
EnsureVendorDir()
diff --git a/action/install.go b/action/install.go
index 3ae39c0..25a5f08 100644
--- a/action/install.go
+++ b/action/install.go
@@ -4,6 +4,7 @@
"io/ioutil"
"path/filepath"
+ "github.com/Masterminds/glide/cache"
"github.com/Masterminds/glide/cfg"
"github.com/Masterminds/glide/dependency"
"github.com/Masterminds/glide/msg"
@@ -13,6 +14,10 @@
// Install installs a vendor directory based on an existing Glide configuration.
func Install(installer *repo.Installer, strip, stripVendor bool) {
+ if installer.UseCache {
+ cache.SystemLock()
+ }
+
base := "."
// Ensure GOPATH
EnsureGopath()
diff --git a/action/update.go b/action/update.go
index 4b0da7b..eb49baa 100644
--- a/action/update.go
+++ b/action/update.go
@@ -3,6 +3,7 @@
import (
"path/filepath"
+ "github.com/Masterminds/glide/cache"
"github.com/Masterminds/glide/cfg"
"github.com/Masterminds/glide/dependency"
"github.com/Masterminds/glide/godep"
@@ -13,6 +14,10 @@
// Update updates repos and the lock file from the main glide yaml.
func Update(installer *repo.Installer, skipRecursive, strip, stripVendor bool) {
+ if installer.UseCache {
+ cache.SystemLock()
+ }
+
base := "."
EnsureGopath()
EnsureVendorDir()
diff --git a/cache/global_lock.go b/cache/global_lock.go
new file mode 100644
index 0000000..f823a6d
--- /dev/null
+++ b/cache/global_lock.go
@@ -0,0 +1,109 @@
+package cache
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/Masterminds/glide/msg"
+ gpath "github.com/Masterminds/glide/path"
+)
+
+var isStarted bool
+
+// SystemLock starts a system rather than application lock. This way multiple
+// app instances don't cause race conditions when working in the cache.
+func SystemLock() error {
+ if isStarted {
+ return nil
+ }
+ err := waitOnLock()
+ if err != nil {
+ return err
+ }
+ err = startLock()
+ isStarted = true
+ return err
+}
+
+// SystemUnlock removes the system wide Glide cache lock.
+func SystemUnlock() {
+ lockdone <- struct{}{}
+ os.Remove(lockFileName)
+}
+
+var lockdone = make(chan struct{}, 1)
+
+type lockdata struct {
+ Comment string `json:"comment"`
+ Pid int `json:"pid"`
+ Time string `json:"time"`
+}
+
+var lockFileName = filepath.Join(gpath.Home(), "lock.json")
+
+// Write a lock for now.
+func writeLock() error {
+ ld := &lockdata{
+ Comment: "File managed by Glide (https://glide.sh)",
+ Pid: os.Getpid(),
+ Time: time.Now().Format(time.RFC3339Nano),
+ }
+
+ out, err := json.Marshal(ld)
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(lockFileName, out, 0755)
+ return err
+}
+
+func startLock() error {
+ err := writeLock()
+ if err != nil {
+ return err
+ }
+
+ go func() {
+ select {
+ case <-lockdone:
+ return
+ default:
+ //time.Sleep(10 * time.Second)
+ err := writeLock()
+ if err != nil {
+ msg.Die("Error using Glide lock: %s", err)
+ }
+ }
+ }()
+
+ return nil
+}
+
+func waitOnLock() error {
+ var announced bool
+ for {
+ fi, err := os.Stat(lockFileName)
+ if err != nil && os.IsNotExist(err) {
+ return nil
+ } else if err != nil {
+ return err
+ }
+
+ diff := time.Now().Sub(fi.ModTime())
+ if diff.Seconds() > 15 {
+ return nil
+ }
+
+ if !announced {
+ announced = true
+ msg.Info("Waiting on global cache access")
+ }
+
+ // Check on the lock file every 15 seconds.
+ // TODO(mattfarina): should this be a different length?
+ time.Sleep(15 * time.Second)
+ }
+}
diff --git a/glide.go b/glide.go
index a9f43ea..2ce9fcc 100644
--- a/glide.go
+++ b/glide.go
@@ -40,6 +40,7 @@
"path/filepath"
"github.com/Masterminds/glide/action"
+ "github.com/Masterminds/glide/cache"
"github.com/Masterminds/glide/msg"
gpath "github.com/Masterminds/glide/path"
"github.com/Masterminds/glide/repo"
@@ -110,6 +111,7 @@
action.Plugin(command, os.Args)
}
app.Before = startup
+ app.After = shutdown
app.Commands = commands()
// Detect errors from the Before and After calls and exit on them.
@@ -669,6 +671,11 @@
return nil
}
+func shutdown(c *cli.Context) error {
+ cache.SystemUnlock()
+ return nil
+}
+
// Get the path to the glide.yaml file.
//
// This returns the name of the path, even if the file does not exist. The value