Passed
Push — master ( dad002...2c29d5 )
by Brice
05:13
created

GitlabRepositoryManager::deleteProject()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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