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

ubccpsc / classy / c3613766-7c49-4a6d-8ad5-a549be905ad5

04 Apr 2025 02:16PM UTC coverage: 87.191% (+0.09%) from 87.102%
c3613766-7c49-4a6d-8ad5-a549be905ad5

push

circleci

web-flow
Merge pull request #478 from ubccpsc310/main

Contribute 310's 24w2 changes upstream

1101 of 1340 branches covered (82.16%)

Branch coverage included in aggregate %.

3950 of 4453 relevant lines covered (88.7%)

35.93 hits per line

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

94.9
packages/portal/backend/src/controllers/RepositoryController.ts
1
import Log from "@common/Log";
1✔
2
import { RepositoryTransport } from "@common/types/PortalTypes";
3
import Util from "@common/Util";
1✔
4
import { Deliverable, GitHubStatus, Person, Repository, Team } from "../Types";
1✔
5

6
import { DatabaseController } from "./DatabaseController";
1✔
7
import { DeliverablesController } from "./DeliverablesController";
1✔
8
import { TeamController } from "./TeamController";
1✔
9

10
export class RepositoryController {
1✔
11
        private db: DatabaseController = DatabaseController.getInstance();
203✔
12

13
        public static repositoryToTransport(repository: Repository): RepositoryTransport {
14
                if (typeof repository === "undefined" || repository === null) {
12✔
15
                        throw new Error("RepositoryController::repositoryToTransport( .. ) - ERROR: repository not provided.");
2✔
16
                }
17

18
                const repo: RepositoryTransport = {
10✔
19
                        id: repository.id,
20
                        URL: repository.URL,
21
                        delivId: repository.delivId,
22
                };
23

24
                return repo;
10✔
25
        }
26

27
        public async getAllRepos(): Promise<Repository[]> {
28
                Log.trace("RepositoryController::getAllRepos() - start");
26✔
29
                const start = Date.now();
26✔
30

31
                const repos = await this.db.getRepositories();
26✔
32

33
                Log.trace("RepositoryController::getAllRepos() - done; # repos: " + repos.length + "; took: " + Util.took(start));
26✔
34
                return repos;
26✔
35
        }
36

37
        public async getRepository(name: string): Promise<Repository | null> {
38
                Log.trace("RepositoryController::getRepository( " + name + " ) - start");
92✔
39
                const start = Date.now();
92✔
40

41
                const repo = await this.db.getRepository(name);
92✔
42

43
                Log.trace("RepositoryController::getRepository( " + name + " ) - done; took: " + Util.took(start));
92✔
44
                return repo;
92✔
45
        }
46

47
        public async getReposForPerson(myPerson: Person): Promise<Repository[]> {
48
                Log.trace("RepositoryController::getReposForPerson( " + myPerson.id + " ) - start");
4✔
49
                const start = Date.now();
4✔
50

51
                // TODO: this is slow; there is a faster implementation in db.getReposForPerson now, but it is untested
52
                // db.getRepositoriesForPerson(myPerson.id)
53

54
                const myTeams = await new TeamController().getTeamsForPerson(myPerson);
4✔
55
                Log.trace("RepositoryController::getReposForPerson( " + myPerson.id + " ) - # teams: " + myTeams.length);
4✔
56

57
                const myRepos: Repository[] = [];
4✔
58
                const allRepos = await this.db.getRepositories();
4✔
59
                for (const repo of allRepos) {
4✔
60
                        for (const team of myTeams) {
9✔
61
                                if (repo.teamIds.indexOf(team.id) >= 0) {
26✔
62
                                        myRepos.push(repo);
9✔
63
                                }
64
                        }
65
                }
66

67
                Log.trace(
4✔
68
                        "RepositoryController::getReposForPerson( " +
69
                                myPerson.id +
70
                                " ) - done; # found: " +
71
                                myRepos.length +
72
                                "; took: " +
73
                                Util.took(start)
74
                );
75
                return myRepos;
4✔
76
        }
77

78
        /**
79
         * Updates an existing repository record.
80
         *
81
         * @param {Repository} repo
82
         * @returns {Promise<Repository>}
83
         */
84
        public async updateRepository(repo: Repository): Promise<Repository> {
85
                if (typeof repo === "undefined" || repo === null) {
3✔
86
                        return null;
1✔
87
                }
88

89
                Log.info("RepositoryController::updateRepository( " + repo.id + " ) - start");
2✔
90

91
                const existingRepo = await this.getRepository(repo.id);
2✔
92
                if (existingRepo === null) {
2✔
93
                        // repo not in db, create new one
94
                        const teams: Team[] = [];
1✔
95
                        const tc = new TeamController();
1✔
96
                        for (const tid of repo.teamIds) {
1✔
97
                                const team = await tc.getTeam(tid);
×
98
                                teams.push(team);
×
99
                        }
100
                        const dc = new DeliverablesController();
1✔
101
                        const deliv = await dc.getDeliverable(repo.delivId);
1✔
102
                        await this.createRepository(repo.id, deliv, teams, repo.custom);
1✔
103
                } else {
104
                        // overwrite existing repo
105
                        const customExisting = Object.assign({}, existingRepo.custom); // overwrite with new fields
1✔
106
                        const customCombined = Object.assign(customExisting, existingRepo.custom);
1✔
107
                        repo.custom = customCombined;
1✔
108
                        await this.db.writeRepository(repo);
1✔
109
                }
110

111
                Log.info("RepositoryController::updateRepository( " + repo.id + " ) - done");
2✔
112
                return await this.db.getRepository(repo.id);
2✔
113
        }
114

115
        // public async createPullRequest(repoId: string, prId: string, custom: any): Promise<Repository | null> {
116
        //     Log.error("RepositoryController::createPullRequest( " + repoId + ", " + prId + ", .. ) -  NOT IMPLEMENTED!!");
117
        //     // TODO: implement PR functionality
118
        //
119
        //     // NOTE: this impl is more complex than it needs to be but is erring on the side of caution
120
        //     const repo = await this.getRepository(repoId);
121
        //     const customA = Object.assign({}, repo.custom);
122
        //     const customB = Object.assign(customA, custom); // overwrite with new fields
123
        //     repo.custom = customB;
124
        //     await this.db.writeRepository(repo);
125
        //     return await this.getRepository(repoId);
126
        // }
127

128
        public async createRepository(name: string, deliv: Deliverable, teams: Team[], custom: any): Promise<Repository | null> {
129
                Log.info("RepositoryController::createRepository( " + name + ", .. ) - start");
54✔
130

131
                const existingRepo = await this.getRepository(name);
54✔
132
                if (existingRepo === null) {
54✔
133
                        const teamIds: string[] = teams.map((team) => team.id);
39✔
134

135
                        if (custom === null) {
38!
136
                                custom = {}; // custom must not be null
×
137
                        }
138

139
                        const repo: Repository = {
38✔
140
                                id: name,
141
                                delivId: deliv.id,
142
                                URL: null,
143
                                gitHubStatus: GitHubStatus.NOT_PROVISIONED,
144
                                cloneURL: null,
145
                                teamIds: teamIds,
146
                                custom: custom,
147
                        };
148

149
                        await this.db.writeRepository(repo);
38✔
150

151
                        Log.info("RepositoryController::createRepository( " + name + ", .. ) - done");
38✔
152
                        return await this.db.getRepository(repo.id);
38✔
153
                } else {
154
                        Log.info("RepositoryController::createRepository( " + name + ", .. ) - repository exists: " + JSON.stringify(existingRepo));
15✔
155
                        return await this.db.getRepository(name);
15✔
156
                }
157
        }
158

159
        public async getPeopleForRepo(repoId: string): Promise<string[] | null> {
160
                Log.trace("RepositoryController::getPeopleForRepo( " + repoId + ", .. ) -  start");
6✔
161
                const start = Date.now();
6✔
162

163
                const peopleIds: string[] = [];
6✔
164
                const tc = new TeamController();
6✔
165
                const repo = await this.getRepository(repoId);
6✔
166
                if (repo !== null) {
6✔
167
                        for (const teamId of repo.teamIds) {
5✔
168
                                const team = await tc.getTeam(teamId);
5✔
169
                                for (const personId of team.personIds) {
5✔
170
                                        if (peopleIds.indexOf(personId) < 0) {
10!
171
                                                peopleIds.push(personId);
10✔
172
                                        }
173
                                }
174
                        }
175
                }
176

177
                Log.trace(
6✔
178
                        "RepositoryController::getPeopleForRepo( " +
179
                                repoId +
180
                                ", .. ) -  done; # people: " +
181
                                peopleIds.length +
182
                                "; took: " +
183
                                Util.took(start)
184
                );
185
                return peopleIds;
6✔
186
        }
187
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc