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

common-workflow-language / cwlviewer / #1694

30 Sep 2024 10:51AM UTC coverage: 70.306% (-0.5%) from 70.811%
#1694

push

github

mr-c
detect non-Workflow CWL documents and give a better error message

2 of 19 new or added lines in 4 files covered. (10.53%)

106 existing lines in 4 files now uncovered.

1700 of 2418 relevant lines covered (70.31%)

0.7 hits per line

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

45.95
/src/main/java/org/commonwl/view/git/GitService.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.commonwl.view.git;
21

22
import java.io.File;
23
import java.io.IOException;
24
import java.net.URI;
25
import java.net.URISyntaxException;
26
import java.nio.file.Files;
27
import java.nio.file.Path;
28
import java.util.HashSet;
29
import java.util.Set;
30
import java.util.UUID;
31
import org.apache.commons.codec.digest.DigestUtils;
32
import org.commonwl.view.researchobject.HashableAgent;
33
import org.eclipse.jgit.api.Git;
34
import org.eclipse.jgit.api.errors.CheckoutConflictException;
35
import org.eclipse.jgit.api.errors.GitAPIException;
36
import org.eclipse.jgit.api.errors.RefNotFoundException;
37
import org.eclipse.jgit.errors.RepositoryNotFoundException;
38
import org.eclipse.jgit.lib.ObjectId;
39
import org.eclipse.jgit.lib.PersonIdent;
40
import org.eclipse.jgit.revwalk.RevCommit;
41
import org.springframework.beans.factory.annotation.Autowired;
42
import org.springframework.beans.factory.annotation.Value;
43
import org.springframework.stereotype.Service;
44

45
/** Handles Git related functionality */
46
@Service
47
public class GitService {
48

49
  // Location to check out git repositories into
50
  private final Path gitStorage;
51

52
  // Whether submodules are also cloned
53
  private final boolean cloneSubmodules;
54

55
  @Autowired
56
  public GitService(
57
      @Value("${gitStorage}") Path gitStorage,
58
      @Value("${gitAPI.cloneSubmodules}") boolean cloneSubmodules) {
1✔
59
    this.gitStorage = gitStorage;
1✔
60
    this.cloneSubmodules = cloneSubmodules;
1✔
61
  }
1✔
62

63
  /**
64
   * Gets a repository, cloning into a local directory or
65
   *
66
   * @param gitDetails The details of the Git repository
67
   * @param reuseDir Whether the cached repository can be used
68
   * @return The git object for the repository
69
   */
70
  public Git getRepository(GitDetails gitDetails, boolean reuseDir)
71
      throws GitAPIException, IOException {
72
    Git repo;
73
    if (reuseDir) {
1✔
74
      // Base dir from configuration, name from hash of repository URL
UNCOV
75
      String baseName = DigestUtils.sha1Hex(GitDetails.normaliseUrl(gitDetails.getRepoUrl()));
×
76

77
      // Check if folder already exists
UNCOV
78
      Path repoDir = gitStorage.resolve(baseName);
×
79
      if (Files.isReadable(repoDir) && Files.isDirectory(repoDir)) {
×
80
        try {
UNCOV
81
          repo = Git.open(repoDir.toFile());
×
82
          repo.fetch().call();
×
83
        } catch (RepositoryNotFoundException ex) {
×
UNCOV
84
          repo = cloneRepo(gitDetails.getRepoUrl(), repoDir.toFile());
×
85
        }
×
86
      } else {
87
        // Create a folder and clone repository into it
88
        Files.createDirectory(repoDir);
×
89
        try {
UNCOV
90
          repo = cloneRepo(gitDetails.getRepoUrl(), repoDir.toFile());
×
UNCOV
91
        } catch (CheckoutConflictException ex) {
×
92
          repo = cloneRepo(gitDetails.getRepoUrl(), createTempDir());
×
UNCOV
93
        }
×
94
      }
95
    } else {
×
96
      // Another thread is already using the existing folder
97
      // Must create another temporary one
98
      repo = cloneRepo(gitDetails.getRepoUrl(), createTempDir());
1✔
99
    }
100

101
    // Checkout the specific branch or commit ID
102
    if (repo != null) {
1✔
103
      // Create a new local branch if it does not exist and not a commit ID
104
      String branchOrCommitId = gitDetails.getBranch();
1✔
105
      final boolean isId = ObjectId.isId(branchOrCommitId);
1✔
106
      if (!isId) {
1✔
107
        branchOrCommitId = "refs/remotes/origin/" + branchOrCommitId;
1✔
108
      }
109
      try {
110
        repo.checkout().setName(branchOrCommitId).call();
1✔
111
      } catch (Exception ex) {
1✔
112
        // Maybe it was a tag
113
        if (!isId && ex instanceof RefNotFoundException) {
1✔
114
          final String tag = gitDetails.getBranch();
1✔
115
          try {
116
            repo.checkout().setName(tag).call();
1✔
117
          } catch (Exception ex2) {
1✔
118
            // Throw the first exception, to keep the same behavior as before.
119
            throw ex;
1✔
120
          }
1✔
121
        } else {
1✔
UNCOV
122
          throw ex;
×
123
        }
124
      }
1✔
125
    }
126

127
    return repo;
1✔
128
  }
129

130
  /**
131
   * Gets the commit ID of the HEAD for the given repository
132
   *
133
   * @param repo The Git repository
134
   * @return The commit ID of the HEAD for the repository
135
   * @throws IOException If the HEAD is detached
136
   */
137
  public String getCurrentCommitID(Git repo) throws IOException {
UNCOV
138
    return repo.getRepository().findRef("HEAD").getObjectId().getName();
×
139
  }
140

141
  /**
142
   * Gets a set of authors for a path in a given repository
143
   *
144
   * @param repo The git repository
145
   * @param path The path to get commits for
146
   * @return An iterable of commits
147
   * @throws GitAPIException Any API errors which may occur
148
   * @throws URISyntaxException Error constructing mailto link
149
   */
150
  public Set<HashableAgent> getAuthors(Git repo, String path)
151
      throws GitAPIException, URISyntaxException {
UNCOV
152
    Iterable<RevCommit> logs = repo.log().addPath(path).call();
×
UNCOV
153
    Set<HashableAgent> fileAuthors = new HashSet<>();
×
UNCOV
154
    for (RevCommit rev : logs) {
×
155
      // Use author first with backup of committer
156
      PersonIdent author = rev.getAuthorIdent();
×
157
      if (author == null) {
×
158
        author = rev.getCommitterIdent();
×
159
      }
160
      // Create a new agent and add as much detail as possible
161
      if (author != null) {
×
162
        HashableAgent newAgent = new HashableAgent();
×
UNCOV
163
        String name = author.getName();
×
UNCOV
164
        if (name != null && name.length() > 0) {
×
165
          newAgent.setName(author.getName());
×
166
        }
167
        String email = author.getEmailAddress();
×
168
        if (email != null && email.length() > 0) {
×
169
          newAgent.setUri(new URI("mailto:" + author.getEmailAddress()));
×
170
        }
171
        fileAuthors.add(newAgent);
×
172
      }
173
    }
×
UNCOV
174
    return fileAuthors;
×
175
  }
176

177
  /**
178
   * Transfers part of the path to the branch to fix / in branch names
179
   *
180
   * @param githubInfo The current Github info possibly with part of the branch name in the path
181
   * @return A potentially corrected set of Github details, or null if there are no slashes in the
182
   *     path
183
   */
184
  public GitDetails transferPathToBranch(GitDetails githubInfo) {
185
    String path = githubInfo.getPath();
1✔
186
    String branch = githubInfo.getBranch();
1✔
187

188
    int firstSlash = path.indexOf("/");
1✔
189
    if (firstSlash > 0) {
1✔
190
      branch += "/" + path.substring(0, firstSlash);
1✔
191
      path = path.substring(firstSlash + 1);
1✔
192
      GitDetails newDetails = new GitDetails(githubInfo.getRepoUrl(), branch, path);
1✔
193
      newDetails.setPackedId(githubInfo.getPackedId());
1✔
194
      return newDetails;
1✔
195
    } else {
UNCOV
196
      return null;
×
197
    }
198
  }
199

200
  /**
201
   * Clones a Git repository
202
   *
203
   * @param repoUrl the url of the Git repository
204
   * @param directory the directory to clone the repo into
205
   * @return a Git instance
206
   * @throws GitAPIException if any error occurs cloning the repo
207
   */
208
  protected Git cloneRepo(String repoUrl, File directory) throws GitAPIException {
UNCOV
209
    return Git.cloneRepository()
×
UNCOV
210
        .setCloneSubmodules(cloneSubmodules)
×
UNCOV
211
        .setURI(repoUrl)
×
UNCOV
212
        .setDirectory(directory)
×
213
        .setCloneAllBranches(true)
×
214
        .call();
×
215
  }
216

217
  protected File createTempDir() throws IOException {
218
    Path repoDir = gitStorage.resolve(String.valueOf(UUID.randomUUID()));
1✔
219
    Files.createDirectory(repoDir);
1✔
220
    return repoDir.toFile();
1✔
221
  }
222
}
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