basefs: add noBuildLock flag

If the flag is enabled, `.hugo_build.lock` will not be created.
This ensures safe running on read-only filesystem etc.
Close #9780
This commit is contained in:
satotake 2022-05-23 02:14:17 +09:00 committed by Bjørn Erik Pedersen
parent 2fc2e9c871
commit 6f7fbe03b1
3 changed files with 24 additions and 9 deletions

View file

@ -305,6 +305,7 @@ func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
cmd.Flags().BoolP("forceSyncStatic", "", false, "copy all files when static is changed.") cmd.Flags().BoolP("forceSyncStatic", "", false, "copy all files when static is changed.")
cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files") cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files")
cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files") cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files")
cmd.Flags().BoolP("noBuildLock", "", false, "don't create .hugo_build.lock file")
cmd.Flags().BoolP("printI18nWarnings", "", false, "print missing translations") cmd.Flags().BoolP("printI18nWarnings", "", false, "print missing translations")
cmd.Flags().BoolP("printPathWarnings", "", false, "print warnings on duplicate target paths etc.") cmd.Flags().BoolP("printPathWarnings", "", false, "print warnings on duplicate target paths etc.")
cmd.Flags().BoolP("printUnusedTemplates", "", false, "print warnings on unused templates.") cmd.Flags().BoolP("printUnusedTemplates", "", false, "print warnings on unused templates.")

View file

@ -200,6 +200,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) {
"forceSyncStatic", "forceSyncStatic",
"noTimes", "noTimes",
"noChmod", "noChmod",
"noBuildLock",
"ignoreVendorPaths", "ignoreVendorPaths",
"templateMetrics", "templateMetrics",
"templateMetricsHints", "templateMetricsHints",

View file

@ -76,18 +76,24 @@ type BaseFs struct {
theBigFs *filesystemsCollector theBigFs *filesystemsCollector
// Locks. // Locks.
buildMu *lockedfile.Mutex // <project>/.hugo_build.lock buildMu Lockable // <project>/.hugo_build.lock
buildMuTests sync.Mutex // Used in tests. }
type Lockable interface {
Lock() (unlock func(), err error)
}
type fakeLockfileMutex struct {
mu sync.Mutex
}
func (f *fakeLockfileMutex) Lock() (func(), error) {
f.mu.Lock()
return func() { f.mu.Unlock() }, nil
} }
// Tries to acquire a build lock. // Tries to acquire a build lock.
func (fs *BaseFs) LockBuild() (unlock func(), err error) { func (fs *BaseFs) LockBuild() (unlock func(), err error) {
if htesting.IsTest {
fs.buildMuTests.Lock()
return func() {
fs.buildMuTests.Unlock()
}, nil
}
return fs.buildMu.Lock() return fs.buildMu.Lock()
} }
@ -445,12 +451,19 @@ func NewBase(p *paths.Paths, logger loggers.Logger, options ...func(*BaseFs) err
sourceFs := hugofs.NewBaseFileDecorator(afero.NewBasePathFs(fs.Source, p.WorkingDir)) sourceFs := hugofs.NewBaseFileDecorator(afero.NewBasePathFs(fs.Source, p.WorkingDir))
publishFsStatic := fs.PublishDirStatic publishFsStatic := fs.PublishDirStatic
var buildMu Lockable
if p.Cfg.GetBool("noBuildLock") || htesting.IsTest {
buildMu = &fakeLockfileMutex{}
} else {
buildMu = lockedfile.MutexAt(filepath.Join(p.WorkingDir, lockFileBuild))
}
b := &BaseFs{ b := &BaseFs{
SourceFs: sourceFs, SourceFs: sourceFs,
WorkDir: fs.WorkingDirReadOnly, WorkDir: fs.WorkingDirReadOnly,
PublishFs: publishFs, PublishFs: publishFs,
PublishFsStatic: publishFsStatic, PublishFsStatic: publishFsStatic,
buildMu: lockedfile.MutexAt(filepath.Join(p.WorkingDir, lockFileBuild)), buildMu: buildMu,
} }
for _, opt := range options { for _, opt := range options {