33namespace CodedMonkey \Dirigent \Package ;
44
55use CodedMonkey \Dirigent \Composer \ComposerClient ;
6+ use CodedMonkey \Dirigent \Composer \ConfigFactory ;
67use CodedMonkey \Dirigent \Doctrine \Entity \Version ;
8+ use Composer \IO \NullIO ;
9+ use Composer \Pcre \Preg ;
10+ use Composer \Util \Filesystem as ComposerFilesystem ;
11+ use Composer \Util \Git as GitUtility ;
12+ use Composer \Util \ProcessExecutor ;
13+ use Composer \Util \Url ;
714use Symfony \Component \DependencyInjection \Attribute \Autowire ;
815use Symfony \Component \Filesystem \Filesystem ;
916
1017readonly class PackageDistributionResolver
1118{
1219 private Filesystem $ filesystem ;
13- private string $ storagePath ;
20+ private string $ distributionStoragePath ;
1421
1522 public function __construct (
1623 private ComposerClient $ composer ,
1724 #[Autowire(param: 'dirigent.storage.path ' )]
1825 string $ storagePath ,
26+ #[Autowire(param: 'dirigent.dist_builder.enabled ' )]
27+ private bool $ buildDistributions ,
28+ #[Autowire(param: 'dirigent.dist_builder.dev_packages ' )]
29+ private bool $ buildDevDistributions ,
1930 ) {
2031 $ this ->filesystem = new Filesystem ();
21- $ this ->storagePath = "$ storagePath/distribution " ;
32+ $ this ->distributionStoragePath = "$ storagePath/distribution " ;
2233 }
2334
2435 public function exists (string $ packageName , string $ packageVersion , string $ reference , string $ type ): bool
@@ -28,7 +39,7 @@ public function exists(string $packageName, string $packageVersion, string $refe
2839
2940 public function path (string $ packageName , string $ packageVersion , string $ reference , string $ type ): string
3041 {
31- return "{ $ this ->storagePath } / { $ packageName} / { $ packageVersion} - { $ reference} . { $ type} " ;
42+ return "$ this ->distributionStoragePath / $ packageName/ $ packageVersion- $ reference. $ type " ;
3243 }
3344
3445 public function resolve (Version $ version , string $ reference , string $ type ): bool
@@ -41,17 +52,77 @@ public function resolve(Version $version, string $reference, string $type): bool
4152 return true ;
4253 }
4354
44- if ($ reference !== $ version ->getDistReference () || $ type !== $ version ->getDistType ()) {
55+ if (
56+ null === $ version ->getDist ()
57+ && $ this ->buildDistributions
58+ && (!$ version ->isDevelopment () || $ this ->buildDevDistributions )
59+ ) {
60+ return $ this ->build ($ version , $ reference , $ type );
61+ } elseif (null !== $ version ->getDist ()) {
62+ return $ this ->mirror ($ version , $ reference , $ type );
63+ }
64+
65+ return false ;
66+ }
67+
68+ private function build (Version $ version , string $ reference , string $ type ): bool
69+ {
70+ // Skip building of outdated references for now
71+ if ($ reference !== $ version ->getSourceReference ()) {
72+ return false ;
73+ }
74+
75+ // Only provide .zip support for now
76+ if ('zip ' !== $ type ) {
77+ return false ;
78+ }
79+
80+ $ package = $ version ->getPackage ();
81+ $ repositoryUrl = $ package ->getRepositoryUrl ();
82+ $ distributionPath = $ this ->path ($ package ->getName (), $ version ->getNormalizedVersion (), $ reference , $ type );
83+
84+ $ io = new NullIO ();
85+ $ config = ConfigFactory::createForVcsRepository ($ repositoryUrl , $ package ->getRepositoryCredentials ());
86+
87+ $ gitUtility = new GitUtility (
88+ $ io ,
89+ $ config ,
90+ $ process = new ProcessExecutor ($ io ),
91+ new ComposerFilesystem ($ process ),
92+ );
93+
94+ $ cacheRepositoryName = Preg::replace ('{[^a-z0-9.]}i ' , '- ' , Url::sanitize ($ repositoryUrl ));
95+ $ cachePath = $ config ->get ('cache-vcs-dir ' ) . '/ ' . $ cacheRepositoryName . '/ ' ;
96+
97+ $ this ->filesystem ->mkdir (dirname ($ distributionPath ));
98+
99+ $ gitUtility ->runCommands ([
100+ ['git ' , 'archive ' , '--format=zip ' , "--output= $ distributionPath " , $ reference ],
101+ ], $ repositoryUrl , $ cachePath );
102+
103+ return true ;
104+ }
105+
106+ private function mirror (Version $ version , string $ reference , string $ type ): bool
107+ {
108+ // Skip mirroring of outdated references for now
109+ if ($ reference !== $ version ->getDistReference ()) {
110+ return false ;
111+ }
112+
113+ // The distribution type must match the origin format
114+ if ($ type !== $ version ->getDistType ()) {
45115 return false ;
46116 }
47117
48- $ distUrl = $ version ->getDistUrl ();
49- $ path = $ this ->path ($ packageName , $ packageVersion , $ reference , $ type );
118+ $ package = $ version ->getPackage ();
119+ $ distributionUrl = $ version ->getDistUrl ();
120+ $ distributionPath = $ this ->path ($ package ->getName (), $ version ->getNormalizedVersion (), $ reference , $ type );
50121
51- $ this ->filesystem ->mkdir (dirname ($ path ));
122+ $ this ->filesystem ->mkdir (dirname ($ distributionPath ));
52123
53124 $ httpDownloader = $ this ->composer ->createHttpDownloader ();
54- $ httpDownloader ->copy ($ distUrl , $ path );
125+ $ httpDownloader ->copy ($ distributionUrl , $ distributionPath );
55126
56127 return true ;
57128 }
0 commit comments