github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/model/context.go (about) 1 package model 2 3 import ( 4 "github.com/evergreen-ci/evergreen/model/build" 5 "github.com/evergreen-ci/evergreen/model/patch" 6 "github.com/evergreen-ci/evergreen/model/task" 7 "github.com/evergreen-ci/evergreen/model/version" 8 "github.com/pkg/errors" 9 ) 10 11 // Context is the set of all the related entities in a 12 // task/build/version/project hierarchy. Using the LoadContext 13 // function, all the other applicable fields in the Context can 14 // inferred and populated from the id of any one of the fields. 15 type Context struct { 16 Task *task.Task 17 Build *build.Build 18 Version *version.Version 19 Patch *patch.Patch 20 Project *Project 21 ProjectRef *ProjectRef 22 } 23 24 // LoadContext builds a Context from the set of given resource ID's 25 // by inferring all the relationships between them - for example, e.g. loading a project based on 26 // the the task, or the version based on the patch, etc. 27 func LoadContext(taskId, buildId, versionId, patchId, projectId string) (Context, error) { 28 ctx := &Context{} 29 30 pId, err := ctx.populateTaskBuildVersion(taskId, buildId, versionId) 31 if err != nil { 32 return *ctx, err 33 } 34 if len(projectId) == 0 || (len(pId) > 0 && pId != projectId) { 35 projectId = pId 36 } 37 38 err = ctx.populatePatch(patchId) 39 if err != nil { 40 return *ctx, err 41 } 42 if ctx.Patch != nil && len(projectId) == 0 { 43 projectId = ctx.Patch.Project 44 } 45 46 // Try to load project for the ID we found, and set cookie with it for subsequent requests 47 if len(projectId) > 0 { 48 // Also lookup the ProjectRef itself and add it to context. 49 ctx.ProjectRef, err = FindOneProjectRef(projectId) 50 if err != nil { 51 return *ctx, err 52 } 53 54 if ctx.ProjectRef != nil { 55 ctx.Project, err = FindProject("", ctx.ProjectRef) 56 if err != nil { 57 return *ctx, err 58 } 59 } 60 } 61 return *ctx, nil 62 } 63 64 // populateTaskBuildVersion takes a task, build, and version ID and populates a Context 65 // with as many of the task, build, and version documents as possible. 66 // If any of the provided IDs is blank, they will be inferred from the more selective ones. 67 // Returns the project ID of the data found, which may be blank if the IDs are empty. 68 func (ctx *Context) populateTaskBuildVersion(taskId, buildId, versionId string) (string, error) { 69 projectId := "" 70 var err error 71 // Fetch task if there's a task ID present; if we find one, populate build/version IDs from it 72 if len(taskId) > 0 { 73 ctx.Task, err = task.FindOne(task.ById(taskId)) 74 if err != nil { 75 return "", err 76 } 77 78 if ctx.Task != nil { 79 // override build and version ID with the ones this task belongs to 80 buildId = ctx.Task.BuildId 81 versionId = ctx.Task.Version 82 projectId = ctx.Task.Project 83 } 84 } 85 86 // Fetch build if there's a build ID present; if we find one, populate version ID from it 87 if len(buildId) > 0 { 88 ctx.Build, err = build.FindOne(build.ById(buildId)) 89 if err != nil { 90 return "", err 91 } 92 if ctx.Build != nil { 93 versionId = ctx.Build.Version 94 projectId = ctx.Build.Project 95 } 96 } 97 if len(versionId) > 0 { 98 ctx.Version, err = version.FindOne(version.ById(versionId)) 99 if err != nil { 100 return "", err 101 } 102 if ctx.Version != nil { 103 projectId = ctx.Version.Identifier 104 } 105 } 106 return projectId, nil 107 } 108 109 // populatePatch loads a patch into the project context, using patchId if provided. 110 // If patchId is blank, will try to infer the patch ID from the version already loaded 111 // into context, if available. 112 func (ctx *Context) populatePatch(patchId string) error { 113 var err error 114 if len(patchId) > 0 { 115 // The patch is explicitly identified in the URL, so fetch it 116 if !patch.IsValidId(patchId) { 117 return errors.Errorf("patch id '%s' is not an object id", patchId) 118 } 119 ctx.Patch, err = patch.FindOne(patch.ById(patch.NewId(patchId)).Project(patch.ExcludePatchDiff)) 120 } else if ctx.Version != nil { 121 // patch isn't in URL but the version in context has one, get it 122 ctx.Patch, err = patch.FindOne(patch.ByVersion(ctx.Version.Id).Project(patch.ExcludePatchDiff)) 123 } 124 if err != nil { 125 return err 126 } 127 128 // If there's a finalized patch loaded into context but not a version, load the version 129 // associated with the patch as the context's version. 130 if ctx.Version == nil && ctx.Patch != nil && ctx.Patch.Version != "" { 131 ctx.Version, err = version.FindOne(version.ById(ctx.Patch.Version)) 132 if err != nil { 133 return errors.WithStack(err) 134 } 135 } 136 return nil 137 }