GitlabRepositoryManager::getPackageFromBranch()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 12
ccs 9
cts 9
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace CompoLab\Application;
4
5
use CompoLab\Domain\Dist;
6
use CompoLab\Domain\Package;
7
use CompoLab\Domain\PackageConfiguration;
8
use CompoLab\Domain\RepositoryCache;
9
use CompoLab\Domain\Source;
10
use CompoLab\Domain\Type\Git;
11
use CompoLab\Domain\Type\Tar;
12
use CompoLab\Domain\ValueObject\Reference;
13
use CompoLab\Domain\ValueObject\Url;
14
use CompoLab\Domain\ValueObject\Version;
15
use Gitlab\Model\Branch;
16
use Gitlab\Model\Commit;
17
use Gitlab\Model\Project;
18
use Gitlab\Model\Tag;
19
use Gitlab\ResultPager;
20
21
final class GitlabRepositoryManager
22
{
23
    /** @var RepositoryCache */
24
    private $repositoryCache;
25
26
    public function __construct(RepositoryCache $repositoryCache)
27
    {
28
        $this->repositoryCache = $repositoryCache;
29
    }
30
31
    public function registerProject(Project $project)
32
    {
33
        // Catch exceptions as a branch or tag
34
        // may contain a version without any
35
        // composer.json file
36
37
        foreach ($project->branches() as $branch) {
38
            try {
39
                $this->registerBranch($branch);
40
41
            } catch (\Exception $e) {
42
                continue;
43
            }
44
        }
45
46
        $gitlab = $project->getClient();
47
        $pager = new ResultPager($gitlab);
48
        foreach ($pager->fetchall($gitlab->tags, 'all', [ $project->id ]) as $tagData) {
49
            try {
50
                $this->registerTag(Tag::fromArray($gitlab, $project, $tagData));
51
52
            } catch (\Exception $e) {
53
                continue;
54
            }
55
        }
56
    }
57
58 1
    public function registerBranch(Branch $branch)
59
    {
60 1
        $this->repositoryCache->addPackage(
61 1
            $this->getPackageFromBranch($branch)
62
        );
63 1
    }
64
65 1
    public function registerTag(Tag $tag)
66
    {
67 1
        $this->repositoryCache->addPackage(
68 1
            $this->getPackageFromTag($tag)
69
        );
70 1
    }
71
72
    public function deleteProject(Project $project)
73
    {
74
        foreach ($project->branches() as $branch) {
75
            $this->deleteBranch($branch);
76
        }
77
78
        foreach ($project->tags() as $tag) {
79
            $this->deleteTag($tag);
80
        }
81
    }
82
83
    public function deleteBranch(Branch $branch)
84
    {
85
        $this->repositoryCache->removePackage(
86
            $this->getPackageFromBranch($branch)
87
        );
88
    }
89
90 1
    public function deleteTag(Tag $tag)
91
    {
92 1
        $this->repositoryCache->removePackage(
93 1
            $this->getPackageFromTag($tag)
94
        );
95 1
    }
96
97 1
    public function save()
98
    {
99 1
        $this->repositoryCache->refresh();
100 1
    }
101
102 1
    private function getPackageFromBranch(Branch $branch): Package
103
    {
104 1
        $composerJson = $this->getComposerJson($branch->commit);
105
106 1
        $version = Version::buildFromString($branch->name);
107
108 1
        return new Package(
109 1
            $composerJson['name'],
110 1
            $version,
111 1
            new PackageConfiguration($composerJson),
112 1
            $this->getSource($branch->project, $branch->commit),
113 1
            $this->getDist($composerJson['name'], $version, $branch->commit)
114
        );
115
    }
116
117 1
    private function getPackageFromTag(Tag $tag): Package
118
    {
119 1
        $composerJson = $this->getComposerJson($tag->commit);
120
121 1
        $version = Version::buildFromString($tag->name);
122
123 1
        return new Package(
124 1
            $composerJson['name'],
125 1
            $version,
126 1
            new PackageConfiguration($composerJson),
127 1
            $this->getSource($tag->project, $tag->commit),
128 1
            $this->getDist($composerJson['name'], $version, $tag->commit)
129
        );
130
    }
131
132 1
    private function getSource(Project $project, Commit $commit): Source
133
    {
134 1
        return new Source(
135 1
            new Git,
136 1
            new Url($project->ssh_url_to_repo),
137 1
            new Reference($commit->id)
138
        );
139
    }
140
141 1
    private function getDist(string $name, Version $version, Commit $commit): Dist
142
    {
143 1
        $archivePath = $this->getArchivePath($name, $version, $commit);
144
145 1
        return new Dist(
146 1
            new Tar,
147 1
            $this->repositoryCache->getRepository()->getUrl($archivePath),
148 1
            new Reference($commit->id),
149 1
            $this->repositoryCache->getRepository()->getFile($archivePath)
150
        );
151
    }
152
153 1
    private function getComposerJson(Commit $commit): array
154
    {
155
        $jsonString = (string) $commit
156 1
            ->getClient()
157 1
            ->repositoryFiles()
158 1
            ->getRawFile($commit->project->id, 'composer.json', $commit->id)
159
        ;
160
161 1
        if (!$jsonArray = json_decode($jsonString, true)) {
162
            throw new \RuntimeException(sprintf('Impossible to get composer.json from project %d (ref: %s)',
163
                $commit->project->id,
164
                $commit->id));
165
        }
166
167 1
        if (!in_array('name', array_keys($jsonArray))) {
168
            throw new \RuntimeException(sprintf('Malformed composer.json from project %d (ref: %s)',
169
                $commit->project->id,
170
                $commit->id));
171
        }
172
173 1
        return $jsonArray;
174
    }
175
176 1
    private function getArchivePath(string $name, Version $version, Commit $commit): string
177
    {
178 1
        $archivePath = Dist::buildArchivePath($name, $version, new Reference($commit->id));
179
180
        try {
181
            // This will check if the archive path exists and is a file
182 1
            $this->repositoryCache->getRepository()->getFile($archivePath);
183
184
        } catch (\Exception $e) {
185
            $this->createArchive($archivePath, $commit);
186
        }
187
188 1
        return $archivePath;
189
    }
190
191
    private function createArchive(string $path, Commit $commit)
192
    {
193
        $path = sprintf('%s/%s',
194
            $this->repositoryCache->getRepository()->getCachePath(),
195
            ltrim($path, '/'));
196
197
        try {
198
            if (!is_dir($dir = pathinfo($path, PATHINFO_DIRNAME))) {
199
                mkdir($dir, 0755, true);
200
            }
201
202
            file_put_contents(
203
                $path,
204
                $commit->getClient()->repositories()->archive(
205
                    $commit->project->id,
206
                    ['sha' => $commit->id]
207
                )
208
            );
209
210
        } catch (\Exception $e) {
211
            throw new \RuntimeException(sprintf('Impossible to put content to %s (%s)', $path, $e->getMessage()));
212
        }
213
    }
214
}
215