Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
Disable file locking when DEPNOLOCK set
Browse files Browse the repository at this point in the history
* Add DisableLocking bool members to Ctx and gps.SourceManagerConfig structs.
  This effectively communicates DEPNOLOCK from the shell, to Ctx, to
  SourceManager.

  The member is named DisableLocking to make its zero-value useful.

* Add locker interface which implements TryLock(), Unlock(), and GetOwner()
  which lockfile.Lockfile alredy adheres to.  This interface replaces the new
  type for the lf member of the SourceMgr struct.

* Add a FalseLocker type which adheres to the Locker interface which does
  nothing.

* Conditionally set the lf member of SourceMgr to either an instance of
  lockfile.Lockfile or FalseLocker depending on the value of
  SourceManagerConfig.DisableLocking.

Signed-off-by: Ayan George <[email protected]>
  • Loading branch information
ayang64 committed Sep 27, 2017
1 parent 203c059 commit c0a4551
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 16 deletions.
7 changes: 4 additions & 3 deletions cmd/dep/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,10 @@ func (c *Config) Run() (exitCode int) {

// Set up dep context.
ctx := &dep.Ctx{
Out: outLogger,
Err: errLogger,
Verbose: *verbose,
Out: outLogger,
Err: errLogger,
Verbose: *verbose,
DisableLocking: getEnv(c.Env, "DEPNOLOCK") != "",
}

GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))
Expand Down
16 changes: 9 additions & 7 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ import (
// }
//
type Ctx struct {
WorkingDir string // Where to execute.
GOPATH string // Selected Go path, containing WorkingDir.
GOPATHs []string // Other Go paths.
Out, Err *log.Logger // Required loggers.
Verbose bool // Enables more verbose logging.
WorkingDir string // Where to execute.
GOPATH string // Selected Go path, containing WorkingDir.
GOPATHs []string // Other Go paths.
Out, Err *log.Logger // Required loggers.
Verbose bool // Enables more verbose logging.
DisableLocking bool // When set, disables locking.
}

// SetPaths sets the WorkingDir and GOPATHs fields. If GOPATHs is empty, then
Expand Down Expand Up @@ -87,8 +88,9 @@ func defaultGOPATH() string {
// initialized to log to the receiver's logger.
func (c *Ctx) SourceManager() (*gps.SourceMgr, error) {
return gps.NewSourceManager(gps.SourceManagerConfig{
Cachedir: filepath.Join(c.GOPATH, "pkg", "dep"),
Logger: c.Out,
Cachedir: filepath.Join(c.GOPATH, "pkg", "dep"),
Logger: c.Out,
DisableLocking: c.DisableLocking,
})
}

Expand Down
55 changes: 49 additions & 6 deletions internal/gps/source_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,41 @@ import (
// Used to compute a friendly filepath from a URL-shaped input.
var sanitizer = strings.NewReplacer("-", "--", ":", "-", "/", "-", "+", "-")

// A locker is responsible for preventing multiple instances of dep from interfereing
// with one-another.
//
// Currently, anything that can either TryLock(), Unlock(), or GetOwner() satifies
// that need.
type locker interface {
TryLock() error
Unlock() error
GetOwner() (*os.Process, error)
}

// A falselocker adheres to the locker inteface and it's purpose is to quietly
// fail to lock when the DEPNOLOCK environment variable is set.
//
// This allows dep to run on systems where file locking doesn't work --
// particularly those that use union mount type filesystems that don't
// implement hard links or fnctl() style locking.
type falseLocker struct{}

// Always returns an error to indicate there's no current ower PID for our
// lock.
func (fl falseLocker) GetOwner() (*os.Process, error) {
return nil, fmt.Errorf("falseLocker always fails")
}

// Does nothing and returns a nil error so caller beleives locking succeeded.
func (fl falseLocker) TryLock() error {
return nil
}

// Does nothing and returns a nil error so caller beleives unlocking succeeded.
func (fl falseLocker) Unlock() error {
return nil
}

// A SourceManager is responsible for retrieving, managing, and interrogating
// source repositories. Its primary purpose is to serve the needs of a Solver,
// but it is handy for other purposes, as well.
Expand Down Expand Up @@ -121,7 +156,7 @@ func (p ProjectAnalyzerInfo) String() string {
// tools; control via dependency injection is intended to be sufficient.
type SourceMgr struct {
cachedir string // path to root of cache dir
lf *lockfile.Lockfile // handle for the sm lock file on disk
lf locker // handle for the sm lock file on disk
suprvsr *supervisor // subsystem that supervises running calls/io
cancelAll context.CancelFunc // cancel func to kill all running work
deduceCoord *deductionCoordinator // subsystem that manages import path deduction
Expand All @@ -142,8 +177,9 @@ var _ SourceManager = &SourceMgr{}

// SourceManagerConfig holds configuration information for creating SourceMgrs.
type SourceManagerConfig struct {
Cachedir string // Where to store local instances of upstream sources.
Logger *log.Logger // Optional info/warn logger. Discards if nil.
Cachedir string // Where to store local instances of upstream sources.
Logger *log.Logger // Optional info/warn logger. Discards if nil.
DisableLocking bool // True if dep SourceManager shoud NOT lock.
}

// NewSourceManager produces an instance of gps's built-in SourceManager.
Expand Down Expand Up @@ -175,7 +211,14 @@ func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) {
// we can spin on.

glpath := filepath.Join(c.Cachedir, "sm.lock")
lockfile, err := lockfile.New(glpath)

lockfile, err := func() (locker, error) {
if c.DisableLocking {
return falseLocker{}, nil
}
return lockfile.New(glpath)
}()

if err != nil {
return nil, CouldNotCreateLockError{
Path: glpath,
Expand Down Expand Up @@ -214,7 +257,7 @@ func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) {
// The first time this is evaluated, duration will be very large as lasttime is 0.
// Unless time travel is invented and someone travels back to the year 1, we should
// be ok.
if duration > 15*time.Second {
if duration > 14*time.Second {
fmt.Fprintf(os.Stderr, "waiting for lockfile %s: %s\n", glpath, err.Error())
lasttime = nowtime
}
Expand All @@ -238,7 +281,7 @@ func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) {

sm := &SourceMgr{
cachedir: c.Cachedir,
lf: &lockfile,
lf: lockfile,
suprvsr: superv,
cancelAll: cf,
deduceCoord: deducer,
Expand Down

0 comments on commit c0a4551

Please sign in to comment.