Skip to content

Commit e4ac3c9

Browse files
ayang64zknill
authored andcommitted
Disable file locking when DEPNOLOCK set (golang#1206)
* Disable file locking when DEPNOLOCK set * 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]> * Revert stray edit. Signed-off-by: Ayan George <[email protected]> * Improve comment for DisableLocking Signed-off-by: Ayan George <[email protected]> * Fix comment type-os * Fix comment type-os Signed-off-by: Ayan George <[email protected]> * Fix yet more type-os. Signed-off-by: Ayan George <[email protected]>
1 parent c87c7b4 commit e4ac3c9

File tree

3 files changed

+61
-15
lines changed

3 files changed

+61
-15
lines changed

cmd/dep/main.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,10 @@ func (c *Config) Run() (exitCode int) {
147147

148148
// Set up dep context.
149149
ctx := &dep.Ctx{
150-
Out: outLogger,
151-
Err: errLogger,
152-
Verbose: *verbose,
150+
Out: outLogger,
151+
Err: errLogger,
152+
Verbose: *verbose,
153+
DisableLocking: getEnv(c.Env, "DEPNOLOCK") != "",
153154
}
154155

155156
GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))

context.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ import (
3434
// }
3535
//
3636
type Ctx struct {
37-
WorkingDir string // Where to execute.
38-
GOPATH string // Selected Go path, containing WorkingDir.
39-
GOPATHs []string // Other Go paths.
40-
Out, Err *log.Logger // Required loggers.
41-
Verbose bool // Enables more verbose logging.
37+
WorkingDir string // Where to execute.
38+
GOPATH string // Selected Go path, containing WorkingDir.
39+
GOPATHs []string // Other Go paths.
40+
Out, Err *log.Logger // Required loggers.
41+
Verbose bool // Enables more verbose logging.
42+
DisableLocking bool // When set, no lock file will be created to protect against simultaneous dep processes.
4243
}
4344

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

internal/gps/source_manager.go

+48-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,41 @@ import (
2828
// Used to compute a friendly filepath from a URL-shaped input.
2929
var sanitizer = strings.NewReplacer("-", "--", ":", "-", "/", "-", "+", "-")
3030

31+
// A locker is responsible for preventing multiple instances of dep from
32+
// interfering with one-another.
33+
//
34+
// Currently, anything that can either TryLock(), Unlock(), or GetOwner()
35+
// satifies that need.
36+
type locker interface {
37+
TryLock() error
38+
Unlock() error
39+
GetOwner() (*os.Process, error)
40+
}
41+
42+
// A falselocker adheres to the locker interface and its purpose is to quietly
43+
// fail to lock when the DEPNOLOCK environment variable is set.
44+
//
45+
// This allows dep to run on systems where file locking doesn't work --
46+
// particularly those that use union mount type filesystems that don't
47+
// implement hard links or fnctl() style locking.
48+
type falseLocker struct{}
49+
50+
// Always returns an error to indicate there's no current ower PID for our
51+
// lock.
52+
func (fl falseLocker) GetOwner() (*os.Process, error) {
53+
return nil, fmt.Errorf("falseLocker always fails")
54+
}
55+
56+
// Does nothing and returns a nil error so caller beleives locking succeeded.
57+
func (fl falseLocker) TryLock() error {
58+
return nil
59+
}
60+
61+
// Does nothing and returns a nil error so caller beleives unlocking succeeded.
62+
func (fl falseLocker) Unlock() error {
63+
return nil
64+
}
65+
3166
// A SourceManager is responsible for retrieving, managing, and interrogating
3267
// source repositories. Its primary purpose is to serve the needs of a Solver,
3368
// but it is handy for other purposes, as well.
@@ -122,7 +157,7 @@ func (p ProjectAnalyzerInfo) String() string {
122157
// tools; control via dependency injection is intended to be sufficient.
123158
type SourceMgr struct {
124159
cachedir string // path to root of cache dir
125-
lf *lockfile.Lockfile // handle for the sm lock file on disk
160+
lf locker // handle for the sm lock file on disk
126161
suprvsr *supervisor // subsystem that supervises running calls/io
127162
cancelAll context.CancelFunc // cancel func to kill all running work
128163
deduceCoord *deductionCoordinator // subsystem that manages import path deduction
@@ -143,8 +178,9 @@ var _ SourceManager = &SourceMgr{}
143178

144179
// SourceManagerConfig holds configuration information for creating SourceMgrs.
145180
type SourceManagerConfig struct {
146-
Cachedir string // Where to store local instances of upstream sources.
147-
Logger *log.Logger // Optional info/warn logger. Discards if nil.
181+
Cachedir string // Where to store local instances of upstream sources.
182+
Logger *log.Logger // Optional info/warn logger. Discards if nil.
183+
DisableLocking bool // True if the SourceManager should NOT use a lock file to protect the Cachedir from multiple processes.
148184
}
149185

150186
// NewSourceManager produces an instance of gps's built-in SourceManager.
@@ -176,7 +212,14 @@ func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) {
176212
// we can spin on.
177213

178214
glpath := filepath.Join(c.Cachedir, "sm.lock")
179-
lockfile, err := lockfile.New(glpath)
215+
216+
lockfile, err := func() (locker, error) {
217+
if c.DisableLocking {
218+
return falseLocker{}, nil
219+
}
220+
return lockfile.New(glpath)
221+
}()
222+
180223
if err != nil {
181224
return nil, CouldNotCreateLockError{
182225
Path: glpath,
@@ -239,7 +282,7 @@ func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) {
239282

240283
sm := &SourceMgr{
241284
cachedir: c.Cachedir,
242-
lf: &lockfile,
285+
lf: lockfile,
243286
suprvsr: superv,
244287
cancelAll: cf,
245288
deduceCoord: deducer,

0 commit comments

Comments
 (0)