001package org.nasdanika.models.gitlab.util; 002 003import java.util.List; 004import java.util.function.BiConsumer; 005 006import org.eclipse.emf.common.util.EMap; 007import org.gitlab4j.api.Constants.AutoDevopsDeployStrategy; 008import org.gitlab4j.api.Constants.BuildGitStrategy; 009import org.gitlab4j.api.Constants.SquashOption; 010import org.gitlab4j.api.GitLabApi; 011import org.gitlab4j.api.GitLabApiException; 012import org.gitlab4j.api.GroupApi; 013import org.gitlab4j.api.Pager; 014import org.gitlab4j.api.ProjectApi; 015import org.gitlab4j.api.ProjectLicense; 016import org.gitlab4j.api.RepositoryApi; 017import org.gitlab4j.api.RepositoryFileApi; 018import org.gitlab4j.api.models.AbstractUser; 019import org.gitlab4j.api.models.Branch; 020import org.gitlab4j.api.models.Commit; 021import org.gitlab4j.api.models.Contributor; 022import org.gitlab4j.api.models.CustomAttribute; 023import org.gitlab4j.api.models.Group.Statistics; 024import org.gitlab4j.api.models.GroupFilter; 025import org.gitlab4j.api.models.Owner; 026import org.gitlab4j.api.models.Permissions; 027import org.gitlab4j.api.models.Project; 028import org.gitlab4j.api.models.ProjectAccess; 029import org.gitlab4j.api.models.ProjectSharedGroup; 030import org.gitlab4j.api.models.ProjectStatistics; 031import org.gitlab4j.api.models.TreeItem; 032import org.gitlab4j.api.models.Visibility; 033import org.nasdanika.common.ProgressMonitor; 034import org.nasdanika.common.Status; 035import org.nasdanika.models.gitlab.GitLabFactory; 036import org.nasdanika.models.gitlab.MergeMethod; 037 038/** 039 * Loads GitLab model using {@link GitLabApi}. 040 * Provides low-level loading capabilities at a single element. 041 * 042 */ 043public class Loader { 044 045 public static final String ROOT_PATH = "/"; 046 private GitLabApi gitLabApi; 047 private GitLabFactory factory = GitLabFactory.eINSTANCE; 048 private int pageSize = 20; 049 050 public int getPageSize() { 051 return pageSize; 052 } 053 054 /** 055 * Page size for retrieving groups. 056 * @param groupsPageSize 057 */ 058 public void setPageSize(int pageSize) { 059 this.pageSize = pageSize; 060 } 061 062 /** 063 * Access to the API for configuration. 064 * @return 065 */ 066 public GitLabApi getGitLabApi() { 067 return gitLabApi; 068 } 069 070 public Loader(GitLabApi gitLabApi) { 071 this.gitLabApi = gitLabApi; 072 } 073 074 public GitLabFactory getFactory() { 075 return factory; 076 } 077 078 public void setFactory(GitLabFactory factory) { 079 this.factory = factory; 080 } 081 082 /** 083 * This implementation returns a new instance of {@link GroupFilter}. 084 * Override to customize. 085 * @return 086 */ 087 protected GroupFilter getGroupFilter() { 088 return new GroupFilter(); 089 } 090 091 // --- 092 093 /** 094 * @param groupConsumer Group bi-consumer which may trigger downstream operations such as loading sub-groups and projects. It takes a group and a progress monitor for group-related downstream operations. 095 * @param progressMonitor 096 */ 097 public void loadTopLevelGroups(BiConsumer<org.nasdanika.models.gitlab.Group, ProgressMonitor> groupConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 098 try (ProgressMonitor groupsMonitor = progressMonitor.split("Loading top-level groups", 1)) { 099 GroupApi groupApi = gitLabApi.getGroupApi(); 100 Pager<org.gitlab4j.api.models.Group> groupPager = groupApi.getGroups(getGroupFilter().withTopLevelOnly(true), getPageSize()); 101 loadGroupPager(groupApi, groupPager, groupConsumer, groupsMonitor); 102 } 103 } 104 105 /** 106 * @param groupConsumer Group bi-consumer which may trigger downstream operations such as loading sub-groups and projects. It takes a group and a progress monitor for group-related downstream operations. 107 * @param progressMonitor 108 */ 109 public void loadSubGroups(long groupId, BiConsumer<org.nasdanika.models.gitlab.Group, ProgressMonitor> groupConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 110 try (ProgressMonitor groupsMonitor = progressMonitor.split("Loading sub-groups of " + groupId, 1)) { 111 GroupApi groupApi = gitLabApi.getGroupApi(); 112 Pager<org.gitlab4j.api.models.Group> groupPager = groupApi.getDescendantGroups(groupId, getGroupFilter(), getPageSize()); 113 loadGroupPager(groupApi, groupPager, groupConsumer, groupsMonitor); 114 } 115 } 116 117 protected void loadGroupPager( 118 GroupApi groupApi, 119 Pager<org.gitlab4j.api.models.Group> groupPager, 120 BiConsumer<org.nasdanika.models.gitlab.Group, ProgressMonitor> groupConsumer, 121 ProgressMonitor groupsMonitor) throws GitLabApiException { 122 int pageNum = 0; 123 while (groupPager.hasNext()) { 124 ++pageNum; 125 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 126 try (ProgressMonitor groupPageMonitor = groupsMonitor.split("Group page " + pageNum, monitorSize)) { 127 List<org.gitlab4j.api.models.Group> groups = groupPager.next(); 128 try (ProgressMonitor scaledGroupsMonitor = groupPageMonitor.scale(groups.size()*2 + 1)) { 129 scaledGroupsMonitor.worked(Status.INFO, 1, "Retrieved " + groups.size() + " groups"); 130 for (org.gitlab4j.api.models.Group group: groups) { 131 try (ProgressMonitor groupMonitor = scaledGroupsMonitor.split("Loading group " + group.getName() + " " + group.getId(), 2, group)) { 132 org.nasdanika.models.gitlab.Group modelGroup = loadGroup(group, groupApi, groupMonitor.split("Loading group data and members", 1)); 133 groupConsumer.accept(modelGroup, groupMonitor.split("Consuming group", 1)); 134 } 135 } 136 } 137 } 138 } 139 } 140 141 protected org.nasdanika.models.gitlab.Group createGroup(org.gitlab4j.api.models.Group group, ProgressMonitor progressMonitor) { 142 return getFactory().createGroup(); 143 } 144 145 protected org.nasdanika.models.gitlab.Group loadGroup( 146 org.gitlab4j.api.models.Group group, 147 GroupApi groupApi, 148 ProgressMonitor progressMonitor) throws GitLabApiException { 149 150 org.nasdanika.models.gitlab.Group modelGroup = createGroup(group, progressMonitor); 151 modelGroup.setAvatarUrl(group.getAvatarUrl()); 152 modelGroup.setCreatedAt(group.getCreatedAt()); 153 modelGroup.setDescription(group.getDescription()); 154 modelGroup.setFullName(group.getFullName()); 155 modelGroup.setFullPath(group.getFullPath()); 156 modelGroup.setId(group.getId()); 157 Statistics stats = group.getStatistics(); 158 if (stats != null) { 159 modelGroup.setJobArtifactsSize(stats.getJobArtifactsSize()); 160 modelGroup.setLfsObjectsSize(stats.getLfsObjectsSize()); 161 modelGroup.setRepositorySize(stats.getRepositorySize()); 162 modelGroup.setStorageSize(stats.getStorageSize()); 163 } 164 modelGroup.setLfsEnabled(group.getLfsEnabled()); 165 modelGroup.setName(group.getName()); 166 modelGroup.setPath(group.getPath()); 167 modelGroup.setVisibility(org.nasdanika.models.gitlab.Visibility.get(group.getVisibility().ordinal())); 168 modelGroup.setWebUrl(group.getWebUrl()); 169 170 return modelGroup; 171 } 172 173 public void loadGroupMembers(long groupId, BiConsumer<org.nasdanika.models.gitlab.Member, ProgressMonitor> memberConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 174 try (ProgressMonitor membersMonitor = progressMonitor.split("Loading group members of " + groupId, 1)) { 175 GroupApi groupApi = gitLabApi.getGroupApi(); 176 Pager<org.gitlab4j.api.models.Member> memberPager = groupApi.getMembers(groupId, getPageSize()); 177 int pageNum = 0; 178 while (memberPager.hasNext()) { 179 ++pageNum; 180 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 181 try (ProgressMonitor memberPageMonitor = membersMonitor.split("Group members page " + pageNum, monitorSize)) { 182 List<org.gitlab4j.api.models.Member> members = memberPager.next(); 183 try (ProgressMonitor scaledMembersMonitor = memberPageMonitor.scale(members.size() * 2 + 1)) { 184 scaledMembersMonitor.worked(Status.INFO, 1, "Retrieved " + members.size() + " members"); 185 for (org.gitlab4j.api.models.Member member: members) { 186 try (ProgressMonitor memberMonitor = scaledMembersMonitor.split("Loading member " + member.getName() + " " + member.getId(), 2, member)) { 187 org.nasdanika.models.gitlab.Member modelMember = loadMember(member, memberMonitor.split("Loading member data", 1)); 188 memberConsumer.accept(modelMember, memberMonitor.split("Consuming member", 1)); 189 } 190 } 191 } 192 } 193 } 194 } 195 } 196 197 protected void populateAbstractUser(AbstractUser<?> apiUser, org.nasdanika.models.gitlab.AbstractUser user) { 198 user.setAvatarUrl(apiUser.getAvatarUrl()); 199 user.setCreatedAt(apiUser.getCreatedAt()); 200 user.setEMail(apiUser.getEmail()); 201 user.setId(apiUser.getId()); 202 user.setName(apiUser.getName()); 203 user.setState(apiUser.getState()); 204 user.setUserName(apiUser.getUsername()); 205 user.setWebUrl(apiUser.getWebUrl()); 206 } 207 208 /** 209 * 210 * @param member 211 * @param userProvider Provides a user instance to reference by the member 212 * @param progressMonitor 213 * @return 214 */ 215 protected org.nasdanika.models.gitlab.Member loadMember(org.gitlab4j.api.models.Member member, ProgressMonitor progressMonitor) { 216 org.nasdanika.models.gitlab.Member modelMember = getFactory().createMember(); 217 populateAbstractUser(member, modelMember); 218 org.gitlab4j.api.models.AccessLevel accessLevel = member.getAccessLevel(); 219 if (accessLevel != null) { 220 modelMember.setAccessLevel(org.nasdanika.models.gitlab.AccessLevel.get(accessLevel.value)); 221 } 222 modelMember.setExpiresAt(member.getExpiresAt()); 223 return modelMember; 224 } 225 226 public void loadProjects(long groupId, BiConsumer<org.nasdanika.models.gitlab.Project, ProgressMonitor> projectConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 227 try (ProgressMonitor projectsMonitor = progressMonitor.split("Loading projects of " + groupId, 1)) { 228 GroupApi groupApi = gitLabApi.getGroupApi(); 229 Pager<org.gitlab4j.api.models.Project> projectPager = groupApi.getProjects(groupId, getPageSize()); 230 int pageNum = 0; 231 while (projectPager.hasNext()) { 232 ++pageNum; 233 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 234 try (ProgressMonitor projectPageMonitor = projectsMonitor.split("Project page " + pageNum, monitorSize)) { 235 List<org.gitlab4j.api.models.Project> projects = projectPager.next(); 236 try (ProgressMonitor scaledProjectsMonitor = projectPageMonitor.scale(projects.size() * 2 + 1)) { 237 scaledProjectsMonitor.worked(Status.INFO, 1, "Retrieved " + projects.size() + " projects"); 238 for (org.gitlab4j.api.models.Project project: projects) { 239 try (ProgressMonitor projectMonitor = scaledProjectsMonitor.split("Loading project " + project.getName() + " " + project.getId(), 2, project)) { 240 org.nasdanika.models.gitlab.Project modelProject = loadProject(project, projectMonitor.split("Loading project data", 1)); 241 projectConsumer.accept(modelProject, projectMonitor.split("Consuming project", 1)); 242 } 243 } 244 } 245 } 246 } 247 } 248 } 249 250 /** 251 * Creates a new instance of model project. Called by loadProject(). 252 * This implementation calls getFactory().createProject(). Override to customize creation. 253 * E.g. create a subclass of Project, load a project from a prototypes with some information pre-filled, ... 254 * @param project 255 * @param groupProvider 256 * @param projectProvider 257 * @param progressMonitor 258 * @return 259 */ 260 protected org.nasdanika.models.gitlab.Project createProject(org.gitlab4j.api.models.Project project, ProgressMonitor progressMonitor) { 261 return getFactory().createProject(); 262 } 263 264 protected org.nasdanika.models.gitlab.Owner createOwner(Owner owner, ProgressMonitor progressMonitor) { 265 return getFactory().createOwner(); 266 } 267 268 protected org.nasdanika.models.gitlab.Branch createBranch(Branch branch, ProgressMonitor progressMonitor) { 269 return getFactory().createBranch(); 270 } 271 272 protected org.nasdanika.models.gitlab.Contributor createContributor(Contributor contributor, ProgressMonitor progressMonitor) { 273 return getFactory().createContributor(); 274 } 275 276 protected org.nasdanika.models.gitlab.ProjectLicense loadProjectLicense(ProjectLicense apiLicense, ProgressMonitor progressMonitor) { 277 org.nasdanika.models.gitlab.ProjectLicense modelLicense = getFactory().createProjectLicense(); 278 modelLicense.setHtmlUrl(apiLicense.getHtmlUrl()); 279 modelLicense.setKey(apiLicense.getKey()); 280 modelLicense.setName(apiLicense.getName()); 281 modelLicense.setNickname(apiLicense.getNickname()); 282 modelLicense.setSourceUrl(apiLicense.getSourceUrl()); 283 return modelLicense; 284 } 285 286 protected org.nasdanika.models.gitlab.Project loadProject(org.gitlab4j.api.models.Project project, ProgressMonitor progressMonitor) throws GitLabApiException { 287 288 org.nasdanika.models.gitlab.Project modelProject = createProject(project, progressMonitor); 289 290 modelProject.setId(project.getId()); 291 modelProject.setApprovalsBeforeMerge(project.getApprovalsBeforeMerge()); 292 modelProject.setArchived(project.getArchived()); 293 modelProject.setAvatarUrl(project.getAvatarUrl()); 294 modelProject.setContainerRegistryEnabled(project.getContainerRegistryEnabled()); 295 modelProject.setCreatedAt(project.getCreatedAt()); 296 modelProject.setCreatorId(project.getCreatorId()); 297 modelProject.setDefaultBranch(project.getDefaultBranch()); 298 modelProject.setDescription(project.getDescription()); 299 modelProject.setForksCount(project.getForksCount()); 300 301 Project forkedFromProject = project.getForkedFromProject(); 302 if (forkedFromProject != null) { 303 modelProject.setForkedFromId(forkedFromProject.getId()); 304 } 305 306 modelProject.setHttpUrlToRepo(project.getHttpUrlToRepo()); 307 modelProject.setIsPublic(project.getPublic()); 308 modelProject.setIssuesEnabled(project.getIssuesEnabled()); 309 modelProject.setJobsEnabled(project.getJobsEnabled()); 310 modelProject.setLastsActivityAt(project.getLastActivityAt()); 311 modelProject.setLfsEnabled(project.getLfsEnabled()); 312 modelProject.setMergeMethod(MergeMethod.get(project.getMergeMethod().ordinal())); 313 modelProject.setMergeRequestsEnabled(project.getMergeRequestsEnabled()); 314 modelProject.setName(project.getName()); 315 modelProject.setNameWithNamespace(project.getNameWithNamespace()); 316 modelProject.setOnlyAllowMergeIfAllDiscussionsAreResolved(project.getOnlyAllowMergeIfAllDiscussionsAreResolved()); 317 modelProject.setOpenIssuesCount(project.getOpenIssuesCount()); 318 319 Owner owner = project.getOwner(); 320 if (owner != null) { 321 org.nasdanika.models.gitlab.Owner modelOwner = createOwner(owner, progressMonitor); 322 populateAbstractUser(owner, modelOwner); 323 modelProject.setOwner(modelOwner); 324 } 325 326 modelProject.setPath(project.getPath()); 327 modelProject.setPathWithNamespace(project.getPathWithNamespace()); 328 329 Permissions permissions = project.getPermissions(); 330 if (permissions != null) { 331 ProjectAccess groupAccess = permissions.getGroupAccess(); 332 if (groupAccess != null) { 333 org.nasdanika.models.gitlab.ProjectAccess modelGroupAccess = getFactory().createProjectAccess(); 334 modelGroupAccess.setAccessLevel(org.nasdanika.models.gitlab.AccessLevel.get(groupAccess.getAccessLevel().value)); 335 modelProject.setGroupAccess(modelGroupAccess); 336 } 337 ProjectAccess projectAccess = permissions.getProjectAccess(); 338 if (projectAccess != null) { 339 org.nasdanika.models.gitlab.ProjectAccess modelProjectAccess = getFactory().createProjectAccess(); 340 modelProjectAccess.setAccessLevel(org.nasdanika.models.gitlab.AccessLevel.get(projectAccess.getAccessLevel().value)); 341 modelProject.setGroupAccess(modelProjectAccess); 342 } 343 } 344 345 modelProject.setPublicJobs(project.getPublicJobs()); 346 modelProject.setRepositoryStorage(project.getRepositoryStorage()); 347 modelProject.setRequestAccessEnabled(project.getRequestAccessEnabled()); 348 modelProject.setRunnersToken(project.getRunnersToken()); 349 modelProject.setSharedRunnersEnabled(project.getSharedRunnersEnabled()); 350 351 List<ProjectSharedGroup> sharedGroups = project.getSharedWithGroups(); 352 if (sharedGroups != null) { 353 for (ProjectSharedGroup sg: sharedGroups) { 354 org.nasdanika.models.gitlab.ProjectSharedGroup psg = getFactory().createProjectSharedGroup(); 355 org.gitlab4j.api.models.AccessLevel accessLevel = sg.getGroupAccessLevel(); 356 if (accessLevel != null) { 357 psg.setAccessLevel(org.nasdanika.models.gitlab.AccessLevel.get(accessLevel.value)); 358 } 359 psg.setFullPath(sg.getGroupFullPath()); 360 psg.setId(sg.getGroupId()); 361 psg.setName(sg.getGroupName()); 362 } 363 } 364 365 modelProject.setSnippetsEnabled(project.getSnippetsEnabled()); 366 modelProject.setSshUrlToRepo(project.getSshUrlToRepo()); 367 modelProject.setStarCount(project.getStarCount()); 368 369 List<String> tags = project.getTagList(); 370 if (tags != null) { 371 modelProject.getTags().addAll(tags); 372 } 373 374 modelProject.setVisibilityLevel(project.getVisibilityLevel()); 375 Visibility projectVisibility = project.getVisibility(); 376 if (projectVisibility != null) { 377 modelProject.setVisibility(org.nasdanika.models.gitlab.Visibility.get(projectVisibility.ordinal())); 378 } 379 modelProject.setWallEnabled(project.getWallEnabled()); 380 modelProject.setWebUrl(project.getWebUrl()); 381 modelProject.setWikiEnabled(project.getWikiEnabled()); 382 modelProject.setPrintingMergeRequestLinkEnabled(project.getPrintingMergeRequestLinkEnabled()); 383 modelProject.setResolveOutdatedDiffDiscussions(project.getResolveOutdatedDiffDiscussions()); 384 385 ProjectStatistics projectStatistics = project.getStatistics(); 386 if (projectStatistics != null) { 387 org.nasdanika.models.gitlab.ProjectStatistics modelProjectStatistics = getFactory().createProjectStatistics(); 388 modelProjectStatistics.setCommitCount(projectStatistics.getCommitCount()); 389 modelProjectStatistics.setJobArtifactsSize(projectStatistics.getJobArtifactsSize()); 390 modelProjectStatistics.setLfsObjectsSize(projectStatistics.getLfsObjectsSize()); 391 modelProjectStatistics.setPackagesSize(projectStatistics.getPackagesSize()); 392 modelProjectStatistics.setRepositorySize(projectStatistics.getRepositorySize()); 393 modelProjectStatistics.setStorageSize(projectStatistics.getStorageSize()); 394 modelProjectStatistics.setWikiSize(projectStatistics.getWikiSize()); 395 396 modelProject.setStatistics(modelProjectStatistics); 397 } 398 399 modelProject.setInitializeWithReadme(null); 400 modelProject.setPackagesEnabled(null); 401 modelProject.setEmptyRepo(null); 402 modelProject.setLicenseUrl(null); 403 404 ProjectLicense apiLicense = project.getLicense(); 405 if (apiLicense != null) { 406 modelProject.setLicense(loadProjectLicense(apiLicense, progressMonitor)); 407 } 408 409 List<CustomAttribute> apiCustomAttributes = project.getCustomAttributes(); 410 if (apiCustomAttributes != null) { 411 EMap<String, String> modelCustomAttributes = modelProject.getCustomAttributes(); 412 apiCustomAttributes.forEach(ca -> modelCustomAttributes.put(ca.getKey(), ca.getValue())); 413 } 414 415 modelProject.setBuildCoverageRegex(project.getBuildCoverageRegex()); 416 417 BuildGitStrategy buildGitStrategy = project.getBuildGitStrategy(); 418 if (buildGitStrategy != null) { 419 modelProject.setBuildGitStrategy(org.nasdanika.models.gitlab.BuildGitStrategy.get(buildGitStrategy.ordinal())); 420 } 421 422 modelProject.setReadmeUrl(project.getReadmeUrl()); 423 modelProject.setCanCreateMergeRequestIn(project.getCanCreateMergeRequestIn()); 424 425 org.gitlab4j.api.models.ImportStatus.Status importStatus = project.getImportStatus(); 426 if (importStatus != null) { 427 modelProject.setImportStatus(org.nasdanika.models.gitlab.Status.get(importStatus.ordinal())); 428 } 429 modelProject.setCiDefaultGitDepth(project.getCiDefaultGitDepth()); 430 modelProject.setCiForwardDeploymentEnabled(project.getCiForwardDeploymentEnabled()); 431 modelProject.setCiConfigPath(project.getCiConfigPath()); 432 modelProject.setRemoveSourceBranchAfterMerge(project.getRemoveSourceBranchAfterMerge()); 433 modelProject.setAutoDevopsEnabled(project.getAutoDevopsEnabled()); 434 435 AutoDevopsDeployStrategy autoDevopsDeployStrategy = project.getAutoDevopsDeployStrategy(); 436 if (autoDevopsDeployStrategy != null) { 437 modelProject.setAutoDevopsDeployStrategy(org.nasdanika.models.gitlab.AutoDevopsDeployStrategy.get(autoDevopsDeployStrategy.ordinal())); 438 } 439 440 modelProject.setAutocloseReferencedIssues(project.getAutocloseReferencedIssues()); 441 modelProject.setEmailsDisabled(project.getEmailsDisabled()); 442 modelProject.setSuggestionCommitMessage(project.getSuggestionCommitMessage()); 443 444 SquashOption squashOption = project.getSquashOption(); 445 if (squashOption != null) { 446 modelProject.setSquashOption(org.nasdanika.models.gitlab.SquashOption.get(squashOption.ordinal())); 447 } 448 449 return modelProject; 450 } 451 452 public void loadProjectMembers(long projectId, BiConsumer<org.nasdanika.models.gitlab.Member, ProgressMonitor> memberConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 453 try (ProgressMonitor membersMonitor = progressMonitor.split("Loading project members of " + projectId, 1)) { 454 ProjectApi projectApi = gitLabApi.getProjectApi(); 455 Pager<org.gitlab4j.api.models.Member> memberPager = projectApi.getMembers(projectId, getPageSize()); 456 int pageNum = 0; 457 while (memberPager.hasNext()) { 458 ++pageNum; 459 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 460 try (ProgressMonitor memberPageMonitor = membersMonitor.split("Project members page " + pageNum, monitorSize)) { 461 List<org.gitlab4j.api.models.Member> members = memberPager.next(); 462 try (ProgressMonitor scaledMembersMonitor = memberPageMonitor.scale(members.size() * 2 + 1)) { 463 scaledMembersMonitor.worked(Status.INFO, 1, "Retrieved " + members.size() + " members"); 464 for (org.gitlab4j.api.models.Member member: members) { 465 try (ProgressMonitor memberMonitor = scaledMembersMonitor.split("Loading member " + member.getName() + " " + member.getId(), 2, member)) { 466 org.nasdanika.models.gitlab.Member modelMember = loadMember(member, memberMonitor.split("Loading member data", 1)); 467 memberConsumer.accept(modelMember, memberMonitor.split("Consuming member", 1)); 468 } 469 } 470 } 471 } 472 } 473 } 474 } 475 476 public void loadProjectContributors(long projectId, BiConsumer<org.nasdanika.models.gitlab.Contributor, ProgressMonitor> contributorConsumer, ProgressMonitor progressMonitor) throws GitLabApiException { 477 try (ProgressMonitor contributorsMonitor = progressMonitor.split("Loading project contributors of " + projectId, 1)) { 478 RepositoryApi repoApi = gitLabApi.getRepositoryApi(); 479 Pager<org.gitlab4j.api.models.Contributor> contributorPager = repoApi.getContributors(projectId, getPageSize()); 480 int pageNum = 0; 481 while (contributorPager.hasNext()) { 482 ++pageNum; 483 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 484 try (ProgressMonitor contributorPageMonitor = contributorsMonitor.split("Project contributors page " + pageNum, monitorSize)) { 485 List<org.gitlab4j.api.models.Contributor> contributors = contributorPager.next(); 486 try (ProgressMonitor scaledContributorsMonitor = contributorPageMonitor.scale(contributors.size() + 1)) { 487 scaledContributorsMonitor.worked(Status.INFO, 1, "Retrieved " + contributors.size() + " contributors"); 488 for (org.gitlab4j.api.models.Contributor contributor: contributors) { 489 try (ProgressMonitor contributorMonitor = scaledContributorsMonitor.split("Loading contributor " + contributor.getName() + " " + contributor.getId(), 1, contributor)) { 490 org.nasdanika.models.gitlab.Contributor modelContributor = createContributor(contributor, contributorMonitor); 491 populateAbstractUser(contributor, modelContributor); 492 modelContributor.setAdditions(contributor.getAdditions()); 493 modelContributor.setCommits(contributor.getCommits()); 494 modelContributor.setDeletions(contributor.getDeletions()); 495 contributorConsumer.accept(modelContributor, contributorMonitor); 496 } 497 } 498 } 499 } 500 } 501 } 502 } 503 504// CommitsApi commitsApi = gitLabApi.getCommitsApi(); 505// for (Commit commit: commitsApi.getCommits(project.getId())) { 506// System.out.println("Commit: " + commit); 507// } 508 509 public void loadBranches( 510 long projectId, 511 BiConsumer<org.nasdanika.models.gitlab.Branch, ProgressMonitor> branchConsumer, 512 ProgressMonitor progressMonitor) throws GitLabApiException { 513 514 try (ProgressMonitor branchesMonitor = progressMonitor.split("Loading branches of " + projectId, 1)) { 515 RepositoryApi repoApi = gitLabApi.getRepositoryApi(); 516 Pager<org.gitlab4j.api.models.Branch> branchPager = repoApi.getBranches(projectId, getPageSize()); 517 int pageNum = 0; 518 while (branchPager.hasNext()) { 519 ++pageNum; 520 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 521 try (ProgressMonitor branchPageMonitor = branchesMonitor.split("Branch page " + pageNum, monitorSize)) { 522 List<org.gitlab4j.api.models.Branch> branches = branchPager.next(); 523 try (ProgressMonitor scaledBranchPageMonitor = branchPageMonitor.scale(branches.size() + 1)) { 524 scaledBranchPageMonitor.worked(Status.INFO, 1, "Retrieved " + branches.size() + " branches"); 525 for (org.gitlab4j.api.models.Branch branch: branches) { 526 try (ProgressMonitor branchMonitor = scaledBranchPageMonitor.split("Loading branch " + branch.getName(), 1, branch)) { 527 org.nasdanika.models.gitlab.Branch modelBranch = createBranch(branch, progressMonitor); 528 modelBranch.setCanPush(branch.getCanPush()); 529 530 Commit commit = branch.getCommit(); 531 if (commit != null) { 532 modelBranch.setCommitDate(commit.getCommittedDate()); 533 } 534 535 modelBranch.setDevelopersCanMerge(branch.getDevelopersCanMerge()); 536 modelBranch.setDevelopersCanPush(branch.getDevelopersCanPush()); 537 modelBranch.setIsDefault(branch.getDefault()); 538 modelBranch.setIsProtected(branch.getProtected()); 539 modelBranch.setMerged(branch.getMerged()); 540 modelBranch.setName(branch.getName()); 541 modelBranch.setWebUrl(branch.getWebUrl()); 542 543 branchConsumer.accept(modelBranch, branchMonitor); 544 } 545 } 546 } 547 } 548 } 549 } 550 } 551 552 /** 553 * Loads branch tree 554 * @param project 555 * @param groupProvider 556 * @param projectProvider 557 * @param progressMonitor 558 * @return 559 * @throws GitLabApiException 560 */ 561 public void loadTree( 562 long projectId, 563 String refName, 564 String path, 565 BiConsumer<org.nasdanika.models.gitlab.TreeItem, ProgressMonitor> treeItemConsumer, 566 ProgressMonitor progressMonitor) throws GitLabApiException { 567 568 try (ProgressMonitor treeItemsMonitor = progressMonitor.split("Loading tree items of project: " + projectId + ", refName: " + refName + ", path: " + path, 1)) { 569 RepositoryApi repoApi = gitLabApi.getRepositoryApi(); 570 Pager<org.gitlab4j.api.models.TreeItem> treeItemPager = repoApi.getTree(projectId, path, refName, getPageSize()); 571 int pageNum = 0; 572 while (treeItemPager.hasNext()) { 573 ++pageNum; 574 double monitorSize = 1.0/Math.pow(2.0, pageNum); // Unknown number of pages, dividing each next by 2. I.e. 1/2 for the first page, 1/4 for the second, ... 575 try (ProgressMonitor treeItemPagePageMonitor = treeItemsMonitor.split("Tree item page " + pageNum, monitorSize)) { 576 List<org.gitlab4j.api.models.TreeItem> treeItems = treeItemPager.next(); 577 try (ProgressMonitor scaledTreeItemPageMonitor = treeItemPagePageMonitor.scale(treeItems.size() + 1)) { 578 scaledTreeItemPageMonitor.worked(Status.INFO, 1, "Retrieved " + treeItems.size() + " tree items"); 579 for (org.gitlab4j.api.models.TreeItem treeItem: treeItems) { 580 try (ProgressMonitor treeItemMonitor = scaledTreeItemPageMonitor.split("Loading tree item " + treeItem.getName(), 1, treeItem)) { 581 switch (treeItem.getType()) { 582 case TREE: 583 org.nasdanika.models.gitlab.Tree subTree = createTree(projectId, refName, treeItem); 584 if (subTree != null) { 585 subTree.setId(treeItem.getId()); 586 subTree.setName(treeItem.getName()); 587 subTree.setPath(treeItem.getPath()); 588 treeItemConsumer.accept(subTree, treeItemMonitor); 589 } 590 break; 591 case BLOB: 592 org.nasdanika.models.gitlab.Blob blob = createBlob( 593 projectId, 594 refName, 595 treeItem, 596 progressMonitor); 597 if (blob != null) { 598 blob.setId(treeItem.getId()); 599 blob.setName(treeItem.getName()); 600 blob.setPath(treeItem.getPath()); 601 treeItemConsumer.accept(blob, treeItemMonitor); 602 } 603 break; 604 case COMMIT: 605 break; 606 default: 607 break; 608 609 } 610 } 611 } 612 } 613 } 614 } 615 } 616 } 617 618 /** 619 * Creates a model tree. Override to create specialized trees. 620 * @param modelProject 621 * @param modelBranch 622 * @param tree 623 * @return 624 */ 625 protected org.nasdanika.models.gitlab.Tree createTree(long projectId, String refName, TreeItem tree) { 626 return getFactory().createTree(); 627 } 628 629 /** 630 * Creates and populates a model blob. This implementation returns RepositoryFile. Override to create specialized blobs, e.g. TextRepositoryFile. 631 * This method may return null or an instance of org.nasdanika.models.gitlab.Blob to avoid calling to repository file API. 632 * @param modelProject 633 * @param modelBranch 634 * @param blob 635 * @return 636 * @throws GitLabApiException 637 */ 638 protected org.nasdanika.models.gitlab.Blob createBlob( 639 long projectId, 640 String refName, 641 TreeItem blob, 642 ProgressMonitor progressMonitor) throws GitLabApiException { 643 644 org.nasdanika.models.gitlab.RepositoryFile ret = createRepositoryFile( 645 projectId, 646 refName, 647 blob, 648 progressMonitor); 649 650 ret.setCommitId(ret.getCommitId()); 651 ret.setLastCommitId(ret.getLastCommitId()); 652 ret.setRef(ret.getRef()); 653 ret.setSize(ret.getSize()); 654 return ret; 655 } 656 657 /** 658 * Creates a model repository file. This implementation returns RepositoryFile. Override to create specialized blobs, e.g. TextRepositoryFile. 659 * @param modelProject 660 * @param modelBranch 661 * @param blob 662 * @param repositoryFile 663 * @return 664 */ 665 protected org.nasdanika.models.gitlab.RepositoryFile createRepositoryFile( 666 long projectId, 667 String refName, 668 TreeItem blob, 669 ProgressMonitor progressMonitor) { 670 671 return getFactory().createRepositoryFile(); 672 } 673 674 public org.gitlab4j.api.models.RepositoryFile loadRepositoryFile(long projectId, String path, String refName) throws GitLabApiException { 675 RepositoryFileApi repoFileApi = gitLabApi.getRepositoryFileApi(); 676 return repoFileApi.getFile(projectId, path, refName); 677 } 678 679}