• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mborne / git-manager / 31580031941

12 Aug 2026 08:48AM UTC coverage: 88.153% (-0.06%) from 88.213%
31580031941

push

github

web-flow
Merge pull request #53 from mborne/51-git-purge

Add git:purge command to remove repository and related data

63 of 72 new or added lines in 3 files covered. (87.5%)

759 of 861 relevant lines covered (88.15%)

8.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.43
/src/Storage/GitRepositoryStore.php
1
<?php
2

3
namespace MBO\GitManager\Storage;
4

5
use Gitonomy\Git\Repository as GitRepository;
6
use League\Flysystem\Filesystem;
7
use League\Flysystem\FilesystemException;
8
use League\Flysystem\FilesystemOperator;
9
use League\Flysystem\Local\LocalFilesystemAdapter;
10
use Psr\Log\LoggerInterface;
11

12
/**
13
 * Store the git repositories cloned from the remote git hosting services in
14
 * the data directory, one directory per project ("{dataDir}/{fullname}").
15
 *
16
 * Note that the storage is local as the git repositories are read by git
17
 * itself and by the analysis tools (gitleaks, trivy,...).
18
 */
19
final readonly class GitRepositoryStore
20
{
21
    /**
22
     * The fullnames are composed of at least two parts ("{host}/{name}"), the
23
     * name itself containing the namespaces of the project.
24
     */
25
    private const FULLNAME_REGEXP = '#^[^/]+(/[^/]+)+$#';
26

27
    private FilesystemOperator $filesystem;
28

29
    public function __construct(
30
        private string $dataDir,
31
        LoggerInterface $logger,
32
    ) {
33
        $logger->info(sprintf('[GitRepositoryStore] %s ', $dataDir));
41✔
34
        /* the data directory is created by the clones, not by this constructor */
35
        $this->filesystem = new Filesystem(new LocalFilesystemAdapter($dataDir, lazyRootCreation: true));
41✔
36
    }
37

38
    /**
39
     * Get the path of the git repository of a project given by its fullname.
40
     */
41
    public function getPath(string $fullname): string
42
    {
43
        return $this->dataDir.DIRECTORY_SEPARATOR.$fullname;
31✔
44
    }
45

46
    /**
47
     * Get the git repository of a project given by its fullname.
48
     */
49
    public function getGitRepository(string $fullname): GitRepository
50
    {
51
        return new GitRepository($this->getPath($fullname));
1✔
52
    }
53

54
    /**
55
     * Test if the git repository of a project is available in the data directory.
56
     */
57
    public function exists(string $fullname): bool
58
    {
59
        try {
60
            return $this->filesystem->directoryExists($fullname);
3✔
NEW
61
        } catch (FilesystemException) {
×
NEW
62
            return false;
×
63
        }
64
    }
65

66
    /**
67
     * Remove the git repository of a project given by its fullname, ignoring a
68
     * missing repository.
69
     *
70
     * @throws GitRepositoryStoreException if the fullname is invalid or if the
71
     *                                     repository can't be removed
72
     */
73
    public function remove(string $fullname): void
74
    {
75
        $this->ensureIsFullname($fullname);
11✔
76
        try {
77
            $this->filesystem->deleteDirectory($fullname);
3✔
NEW
78
        } catch (FilesystemException $e) {
×
NEW
79
            throw new GitRepositoryStoreException(sprintf('fail to remove the git repository %s : %s', $fullname, $e->getMessage()), previous: $e);
×
80
        }
81
    }
82

83
    /**
84
     * Ensure that a fullname designates a single project so that a removal
85
     * can't reach the data directory itself or one of its parents.
86
     *
87
     * @throws GitRepositoryStoreException if the fullname is invalid
88
     */
89
    private function ensureIsFullname(string $fullname): void
90
    {
91
        $parts = explode('/', $fullname);
11✔
92
        if (1 !== preg_match(self::FULLNAME_REGEXP, $fullname) || [] !== array_intersect(['.', '..'], $parts)) {
11✔
93
            throw new GitRepositoryStoreException(sprintf('"%s" is not a valid project fullname (ex : "github.com/mborne/git-manager")', $fullname));
8✔
94
        }
95
    }
96
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc