mirror of
				https://github.com/go-task/task.git
				synced 2025-10-30 23:58:01 +02:00 
			
		
		
		
	Merge branch 'issue-37-cyclic-dep'
This commit is contained in:
		
							
								
								
									
										27
									
								
								cyclic.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								cyclic.go
									
									
									
									
									
								
							| @@ -1,29 +1,34 @@ | ||||
| package task | ||||
|  | ||||
| // HasCyclicDep checks if a task tree has any cyclic dependency | ||||
| func (e *Executor) HasCyclicDep() bool { | ||||
| // CheckCyclicDep checks if a task tree has any cyclic dependency | ||||
| func (e *Executor) CheckCyclicDep() error { | ||||
| 	visits := make(map[string]struct{}, len(e.Tasks)) | ||||
|  | ||||
| 	var checkCyclicDep func(string, *Task) bool | ||||
| 	checkCyclicDep = func(name string, t *Task) bool { | ||||
| 	var checkCyclicDep func(string, *Task) error | ||||
| 	checkCyclicDep = func(name string, t *Task) error { | ||||
| 		if _, ok := visits[name]; ok { | ||||
| 			return false | ||||
| 			return ErrCyclicDepDetected | ||||
| 		} | ||||
| 		visits[name] = struct{}{} | ||||
| 		defer delete(visits, name) | ||||
|  | ||||
| 		for _, d := range t.Deps { | ||||
| 			if !checkCyclicDep(d.Task, e.Tasks[d.Task]) { | ||||
| 				return false | ||||
| 			// FIXME: ignoring by now. should return an error instead? | ||||
| 			task, ok := e.Tasks[d.Task] | ||||
| 			if !ok { | ||||
| 				continue | ||||
| 			} | ||||
| 			if err := checkCyclicDep(d.Task, task); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	for k, v := range e.Tasks { | ||||
| 		if !checkCyclicDep(k, v) { | ||||
| 			return true | ||||
| 		if err := checkCyclicDep(k, v); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-task/task" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestCyclicDepCheck(t *testing.T) { | ||||
| @@ -18,9 +20,7 @@ func TestCyclicDepCheck(t *testing.T) { | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	if !isCyclic.HasCyclicDep() { | ||||
| 		t.Error("Task should be cyclic") | ||||
| 	} | ||||
| 	assert.Equal(t, task.ErrCyclicDepDetected, isCyclic.CheckCyclicDep(), "task should be cyclic") | ||||
|  | ||||
| 	isNotCyclic := &task.Executor{ | ||||
| 		Tasks: task.Tasks{ | ||||
| @@ -34,7 +34,23 @@ func TestCyclicDepCheck(t *testing.T) { | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	if isNotCyclic.HasCyclicDep() { | ||||
| 		t.Error("Task should not be cyclic") | ||||
| 	assert.NoError(t, isNotCyclic.CheckCyclicDep()) | ||||
|  | ||||
| 	inexixtentTask := &task.Executor{ | ||||
| 		Tasks: task.Tasks{ | ||||
| 			"task-a": &task.Task{ | ||||
| 				Deps: []*task.Dep{&task.Dep{Task: "invalid-task"}}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	// FIXME: by now Task should ignore non existent tasks | ||||
| 	// in the future we should improve the detection of | ||||
| 	// tasks called with interpolation? | ||||
| 	//     task: | ||||
| 	//       deps: | ||||
| 	//         - task: "task{{.VARIABLE}}" | ||||
| 	//       vars: | ||||
| 	//         VARIABLE: something | ||||
| 	assert.NoError(t, inexixtentTask.CheckCyclicDep()) | ||||
| } | ||||
|   | ||||
| @@ -6,8 +6,8 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrCyclicDependencyDetected is returned when a cyclic dependency was found in the Taskfile | ||||
| 	ErrCyclicDependencyDetected = errors.New("task: cyclic dependency detected") | ||||
| 	// ErrCyclicDepDetected is returned when a cyclic dependency was found in the Taskfile | ||||
| 	ErrCyclicDepDetected = errors.New("task: cyclic dependency detected") | ||||
| 	// ErrTaskfileAlreadyExists is returned on creating a Taskfile if one already exists | ||||
| 	ErrTaskfileAlreadyExists = errors.New("task: A Taskfile already exists") | ||||
| ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user