Skip to content

Commit ab18f5e

Browse files
committed
refactor: re-organize node loading code to make it easier to follow
Readability is subjective, but while working in this part of the code I found it difficult to follow the different code paths when loading a node's content. In this change I am attempting to make the branches of the decision tree return early as much as possible. This way we discard each possibility as we work our way down, in this order: 1. Non-remote nodes 2. In offline mode, use cached remote nodes 3. On network timeout, use cached remote nodes 4a. Use fetched remote node 4b. On checksum change, handle writing to cache Tests are added to ensure this functionality does not break.
1 parent f704a06 commit ab18f5e

File tree

1 file changed

+67
-69
lines changed

1 file changed

+67
-69
lines changed

taskfile/reader.go

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -221,91 +221,89 @@ func (r *Reader) readNode(node Node) (*ast.Taskfile, error) {
221221
}
222222

223223
func (r *Reader) loadNodeContent(node Node) ([]byte, error) {
224-
var b []byte
225-
var err error
226-
var cache *Cache
224+
if !node.Remote() {
225+
ctx, cf := context.WithTimeout(context.Background(), r.timeout)
226+
defer cf()
227+
return node.Read(ctx)
228+
}
227229

228-
if node.Remote() {
229-
cache, err = NewCache(r.tempDir)
230-
if err != nil {
231-
return nil, err
232-
}
230+
cache, err := NewCache(r.tempDir)
231+
if err != nil {
232+
return nil, err
233233
}
234234

235-
// If the file is remote and we're in offline mode, check if we have a cached copy
236-
if node.Remote() && r.offline {
237-
if b, err = cache.read(node); errors.Is(err, os.ErrNotExist) {
235+
if r.offline {
236+
// In offline mode try to use cached copy
237+
cached, err := cache.read(node)
238+
if errors.Is(err, os.ErrNotExist) {
238239
return nil, &errors.TaskfileCacheNotFoundError{URI: node.Location()}
239240
} else if err != nil {
240241
return nil, err
241242
}
242243
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Fetched cached copy\n", node.Location())
243-
} else {
244244

245-
downloaded := false
246-
ctx, cf := context.WithTimeout(context.Background(), r.timeout)
247-
defer cf()
245+
return cached, nil
246+
}
248247

249-
// Read the file
250-
b, err = node.Read(ctx)
251-
var taskfileNetworkTimeoutError *errors.TaskfileNetworkTimeoutError
248+
ctx, cf := context.WithTimeout(context.Background(), r.timeout)
249+
defer cf()
250+
251+
b, err := node.Read(ctx)
252+
if errors.Is(err, &errors.TaskfileNetworkTimeoutError{}) {
252253
// If we timed out then we likely have a network issue
253-
if node.Remote() && errors.As(err, &taskfileNetworkTimeoutError) {
254-
// If a download was requested, then we can't use a cached copy
255-
if r.download {
256-
return nil, &errors.TaskfileNetworkTimeoutError{URI: node.Location(), Timeout: r.timeout}
257-
}
258-
// Search for any cached copies
259-
if b, err = cache.read(node); errors.Is(err, os.ErrNotExist) {
260-
return nil, &errors.TaskfileNetworkTimeoutError{URI: node.Location(), Timeout: r.timeout, CheckedCache: true}
261-
} else if err != nil {
262-
return nil, err
263-
}
264-
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Network timeout. Fetched cached copy\n", node.Location())
254+
255+
// If a download was requested, then we can't use a cached copy
256+
if r.download {
257+
return nil, &errors.TaskfileNetworkTimeoutError{URI: node.Location(), Timeout: r.timeout}
258+
}
259+
260+
// Search for any cached copies
261+
cached, err := cache.read(node)
262+
if errors.Is(err, os.ErrNotExist) {
263+
return nil, &errors.TaskfileNetworkTimeoutError{URI: node.Location(), Timeout: r.timeout, CheckedCache: true}
265264
} else if err != nil {
266265
return nil, err
267-
} else {
268-
downloaded = true
269266
}
267+
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Network timeout. Fetched cached copy\n", node.Location())
270268

271-
// If the node was remote, we need to check the checksum
272-
if node.Remote() && downloaded {
273-
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Fetched remote copy\n", node.Location())
274-
275-
// Get the checksums
276-
checksum := checksum(b)
277-
cachedChecksum := cache.readChecksum(node)
278-
279-
var prompt string
280-
if cachedChecksum == "" {
281-
// If the checksum doesn't exist, prompt the user to continue
282-
prompt = fmt.Sprintf(taskfileUntrustedPrompt, node.Location())
283-
} else if checksum != cachedChecksum {
284-
// If there is a cached hash, but it doesn't match the expected hash, prompt the user to continue
285-
prompt = fmt.Sprintf(taskfileChangedPrompt, node.Location())
286-
}
269+
return cached, nil
287270

288-
if prompt != "" {
289-
if err := func() error {
290-
r.promptMutex.Lock()
291-
defer r.promptMutex.Unlock()
292-
return r.logger.Prompt(logger.Yellow, prompt, "n", "y", "yes")
293-
}(); err != nil {
294-
return nil, &errors.TaskfileNotTrustedError{URI: node.Location()}
295-
}
296-
}
297-
// If the hash has changed (or is new)
298-
if checksum != cachedChecksum {
299-
// Store the checksum
300-
if err := cache.writeChecksum(node, checksum); err != nil {
301-
return nil, err
302-
}
303-
// Cache the file
304-
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Caching downloaded file\n", node.Location())
305-
if err = cache.write(node, b); err != nil {
306-
return nil, err
307-
}
308-
}
271+
} else if err != nil {
272+
return nil, err
273+
}
274+
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Fetched remote copy\n", node.Location())
275+
276+
// Get the checksums
277+
checksum := checksum(b)
278+
cachedChecksum := cache.readChecksum(node)
279+
280+
var prompt string
281+
if cachedChecksum == "" {
282+
// If the checksum doesn't exist, prompt the user to continue
283+
prompt = fmt.Sprintf(taskfileUntrustedPrompt, node.Location())
284+
} else if checksum != cachedChecksum {
285+
// If there is a cached hash, but it doesn't match the expected hash, prompt the user to continue
286+
prompt = fmt.Sprintf(taskfileChangedPrompt, node.Location())
287+
}
288+
289+
if prompt != "" {
290+
if err := func() error {
291+
r.promptMutex.Lock()
292+
defer r.promptMutex.Unlock()
293+
return r.logger.Prompt(logger.Yellow, prompt, "n", "y", "yes")
294+
}(); err != nil {
295+
return nil, &errors.TaskfileNotTrustedError{URI: node.Location()}
296+
}
297+
298+
// Store the checksum
299+
if err := cache.writeChecksum(node, checksum); err != nil {
300+
return nil, err
301+
}
302+
303+
// Cache the file
304+
r.logger.VerboseOutf(logger.Magenta, "task: [%s] Caching downloaded file\n", node.Location())
305+
if err = cache.write(node, b); err != nil {
306+
return nil, err
309307
}
310308
}
311309

0 commit comments

Comments
 (0)