python.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package buildpacks
  2. import (
  3. "strings"
  4. "sync"
  5. "github.com/google/go-github/v41/github"
  6. "github.com/xanzy/go-gitlab"
  7. )
  8. type pythonRuntime struct {
  9. wg sync.WaitGroup
  10. }
  11. func NewPythonRuntime() Runtime {
  12. return &pythonRuntime{}
  13. }
  14. func (runtime *pythonRuntime) detectPipenvGithub(results chan struct {
  15. string
  16. bool
  17. }, directoryContent []*github.RepositoryContent,
  18. ) {
  19. pipfileFound := false
  20. pipfileLockFound := false
  21. for i := 0; i < len(directoryContent); i++ {
  22. name := directoryContent[i].GetName()
  23. if name == "Pipfile" {
  24. pipfileFound = true
  25. } else if name == "Pipfile.lock" {
  26. pipfileLockFound = true
  27. }
  28. if pipfileFound && pipfileLockFound {
  29. break
  30. }
  31. }
  32. if pipfileFound && pipfileLockFound {
  33. results <- struct {
  34. string
  35. bool
  36. }{pipenv, true}
  37. }
  38. runtime.wg.Done()
  39. }
  40. func (runtime *pythonRuntime) detectPipenvGitlab(results chan struct {
  41. string
  42. bool
  43. }, tree []*gitlab.TreeNode,
  44. ) {
  45. pipfileFound := false
  46. pipfileLockFound := false
  47. for i := 0; i < len(tree); i++ {
  48. name := tree[i].Name
  49. if name == "Pipfile" {
  50. pipfileFound = true
  51. } else if name == "Pipfile.lock" {
  52. pipfileLockFound = true
  53. }
  54. if pipfileFound && pipfileLockFound {
  55. break
  56. }
  57. }
  58. if pipfileFound && pipfileLockFound {
  59. results <- struct {
  60. string
  61. bool
  62. }{pipenv, true}
  63. }
  64. runtime.wg.Done()
  65. }
  66. func (runtime *pythonRuntime) detectPipGithub(results chan struct {
  67. string
  68. bool
  69. }, directoryContent []*github.RepositoryContent,
  70. ) {
  71. requirementsTxtFound := false
  72. for i := 0; i < len(directoryContent); i++ {
  73. name := directoryContent[i].GetName()
  74. if name == "requirements.txt" {
  75. requirementsTxtFound = true
  76. }
  77. }
  78. if requirementsTxtFound {
  79. results <- struct {
  80. string
  81. bool
  82. }{pip, true}
  83. }
  84. runtime.wg.Done()
  85. }
  86. func (runtime *pythonRuntime) detectPipGitlab(results chan struct {
  87. string
  88. bool
  89. }, tree []*gitlab.TreeNode,
  90. ) {
  91. requirementsTxtFound := false
  92. for i := 0; i < len(tree); i++ {
  93. name := tree[i].Name
  94. if name == "requirements.txt" {
  95. requirementsTxtFound = true
  96. }
  97. }
  98. if requirementsTxtFound {
  99. results <- struct {
  100. string
  101. bool
  102. }{pip, true}
  103. }
  104. runtime.wg.Done()
  105. }
  106. func (runtime *pythonRuntime) detectCondaGithub(results chan struct {
  107. string
  108. bool
  109. }, directoryContent []*github.RepositoryContent,
  110. ) {
  111. environmentFound := false
  112. packageListFound := false
  113. for i := 0; i < len(directoryContent); i++ {
  114. name := directoryContent[i].GetName()
  115. if name == "environment.yml" {
  116. environmentFound = true
  117. break
  118. } else if name == "package-list.txt" {
  119. packageListFound = true
  120. break
  121. }
  122. }
  123. if environmentFound || packageListFound {
  124. results <- struct {
  125. string
  126. bool
  127. }{conda, true}
  128. }
  129. runtime.wg.Done()
  130. }
  131. func (runtime *pythonRuntime) detectCondaGitlab(results chan struct {
  132. string
  133. bool
  134. }, tree []*gitlab.TreeNode,
  135. ) {
  136. environmentFound := false
  137. packageListFound := false
  138. for i := 0; i < len(tree); i++ {
  139. name := tree[i].Name
  140. if name == "environment.yml" {
  141. environmentFound = true
  142. break
  143. } else if name == "package-list.txt" {
  144. packageListFound = true
  145. break
  146. }
  147. }
  148. if environmentFound || packageListFound {
  149. results <- struct {
  150. string
  151. bool
  152. }{conda, true}
  153. }
  154. runtime.wg.Done()
  155. }
  156. func (runtime *pythonRuntime) detectStandaloneGithub(results chan struct {
  157. string
  158. bool
  159. }, directoryContent []*github.RepositoryContent,
  160. ) {
  161. pyFound := false
  162. for i := 0; i < len(directoryContent); i++ {
  163. name := directoryContent[i].GetName()
  164. if strings.HasSuffix(name, ".py") {
  165. pyFound = true
  166. break
  167. }
  168. }
  169. if pyFound {
  170. results <- struct {
  171. string
  172. bool
  173. }{standalone, true}
  174. }
  175. runtime.wg.Done()
  176. }
  177. func (runtime *pythonRuntime) detectStandaloneGitlab(results chan struct {
  178. string
  179. bool
  180. }, tree []*gitlab.TreeNode,
  181. ) {
  182. pyFound := false
  183. for i := 0; i < len(tree); i++ {
  184. name := tree[i].Name
  185. if strings.HasSuffix(name, ".py") {
  186. pyFound = true
  187. break
  188. }
  189. }
  190. if pyFound {
  191. results <- struct {
  192. string
  193. bool
  194. }{standalone, true}
  195. }
  196. runtime.wg.Done()
  197. }
  198. func (runtime *pythonRuntime) DetectGithub(
  199. client *github.Client,
  200. directoryContent []*github.RepositoryContent,
  201. owner, name, path string,
  202. repoContentOptions github.RepositoryContentGetOptions,
  203. paketo, heroku *BuilderInfo,
  204. ) error {
  205. results := make(chan struct {
  206. string
  207. bool
  208. }, 4)
  209. runtime.wg.Add(4)
  210. go runtime.detectPipenvGithub(results, directoryContent)
  211. go runtime.detectPipGithub(results, directoryContent)
  212. go runtime.detectCondaGithub(results, directoryContent)
  213. go runtime.detectStandaloneGithub(results, directoryContent)
  214. runtime.wg.Wait()
  215. close(results)
  216. paketoBuildpackInfo := BuildpackInfo{
  217. Name: "Python",
  218. Buildpack: "gcr.io/paketo-buildpacks/python",
  219. }
  220. herokuBuildpackInfo := BuildpackInfo{
  221. Name: "Python",
  222. Buildpack: "heroku/python",
  223. }
  224. if len(results) == 0 {
  225. paketo.Others = append(paketo.Others, paketoBuildpackInfo)
  226. heroku.Others = append(heroku.Others, herokuBuildpackInfo)
  227. return nil
  228. }
  229. paketo.Detected = append(paketo.Detected, paketoBuildpackInfo)
  230. heroku.Detected = append(heroku.Detected, herokuBuildpackInfo)
  231. return nil
  232. }
  233. func (runtime *pythonRuntime) DetectGitlab(
  234. client *gitlab.Client,
  235. tree []*gitlab.TreeNode,
  236. owner, name, path, ref string,
  237. paketo, heroku *BuilderInfo,
  238. ) error {
  239. results := make(chan struct {
  240. string
  241. bool
  242. }, 4)
  243. runtime.wg.Add(4)
  244. go runtime.detectPipenvGitlab(results, tree)
  245. go runtime.detectPipGitlab(results, tree)
  246. go runtime.detectCondaGitlab(results, tree)
  247. go runtime.detectStandaloneGitlab(results, tree)
  248. runtime.wg.Wait()
  249. close(results)
  250. paketoBuildpackInfo := BuildpackInfo{
  251. Name: "Python",
  252. Buildpack: "gcr.io/paketo-buildpacks/python",
  253. }
  254. herokuBuildpackInfo := BuildpackInfo{
  255. Name: "Python",
  256. Buildpack: "heroku/python",
  257. }
  258. if len(results) == 0 {
  259. paketo.Others = append(paketo.Others, paketoBuildpackInfo)
  260. heroku.Others = append(heroku.Others, herokuBuildpackInfo)
  261. return nil
  262. }
  263. paketo.Detected = append(paketo.Detected, paketoBuildpackInfo)
  264. heroku.Detected = append(heroku.Detected, herokuBuildpackInfo)
  265. return nil
  266. }