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

oracle / opengrok / #3691

09 Nov 2023 04:15PM UTC coverage: 74.721% (+8.6%) from 66.08%
#3691

push

web-flow
avoid annotations for binary files (#4476)

fixes #4473

6 of 13 new or added lines in 4 files covered. (46.15%)

258 existing lines in 28 files now uncovered.

43797 of 58614 relevant lines covered (74.72%)

0.75 hits per line

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

96.67
/opengrok-indexer/src/main/java/org/opengrok/indexer/history/RepositoryWithHistoryTraversal.java
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * See LICENSE.txt included in this distribution for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing Covered Code, include this CDDL HEADER in each
12
 * file and include the License file at LICENSE.txt.
13
 * If applicable, add the following below this CDDL HEADER, with the
14
 * fields enclosed by brackets "[]" replaced with your own identifying
15
 * information: Portions Copyright [yyyy] [name of copyright owner]
16
 *
17
 * CDDL HEADER END
18
 */
19

20
/*
21
 * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
22
 */
23
package org.opengrok.indexer.history;
24

25
import org.jetbrains.annotations.Nullable;
26
import org.opengrok.indexer.configuration.Project;
27
import org.opengrok.indexer.configuration.RuntimeEnvironment;
28
import org.opengrok.indexer.logger.LoggerFactory;
29
import org.opengrok.indexer.util.Progress;
30
import org.opengrok.indexer.util.Statistics;
31

32
import java.io.File;
33
import java.util.ArrayList;
34
import java.util.Date;
35
import java.util.HashSet;
36
import java.util.List;
37
import java.util.Set;
38
import java.util.SortedSet;
39
import java.util.TreeSet;
40
import java.util.logging.Level;
41
import java.util.logging.Logger;
42

43
public abstract class RepositoryWithHistoryTraversal extends RepositoryWithPerPartesHistory {
1✔
44

45
    private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryWithHistoryTraversal.class);
1✔
46

47
    private static final long serialVersionUID = -1L;
48

49
    public static class CommitInfo {
50
        String revision;
51
        String displayRevision;
52
        Date date;
53
        String authorName;
54
        String authorEmail;
55
        String message;
56

57
        CommitInfo() {
1✔
58
        }
1✔
59

60
        CommitInfo(String revision, String displayRevision, Date date, String authorName, String authorEmail, String message) {
1✔
61
            this.revision = revision;
1✔
62
            this.displayRevision = displayRevision;
1✔
63
            this.date = date;
1✔
64
            this.authorName = authorName;
1✔
65
            this.authorEmail = authorEmail;
1✔
66
            this.message = message;
1✔
67
        }
1✔
68
    }
69

70
    public static class ChangesetInfo {
71
        CommitInfo commit;
72
        public SortedSet<String> files;
73
        public Set<String> renamedFiles;
74
        public Set<String> deletedFiles;
75
        public Boolean isMerge;
76

77
        ChangesetInfo(CommitInfo commit) {
1✔
78
            this.commit = commit;
1✔
79
            this.files = new TreeSet<>();
1✔
80
            this.renamedFiles = new HashSet<>();
1✔
81
            this.deletedFiles = new HashSet<>();
1✔
82
        }
1✔
83

84
        ChangesetInfo(CommitInfo commit, SortedSet<String> files, Set<String> renamedFiles, Set<String> deletedFiles,
85
                      Boolean isMerge) {
1✔
86
            this.commit = commit;
1✔
87
            this.files = files;
1✔
88
            this.renamedFiles = renamedFiles;
1✔
89
            this.deletedFiles = deletedFiles;
1✔
90
            this.isMerge = isMerge;
1✔
91
        }
1✔
92
    }
93

94
    /**
95
     * Traverse history of given file/directory.
96
     * @param file File object
97
     * @param sinceRevision start revision (non-inclusive)
98
     * @param tillRevision end revision (inclusive)
99
     * @param numCommits maximum number of commits to traverse (use {@code null} as unlimited)
100
     * @param visitors list of {@link ChangesetVisitor} objects
101
     * @throws HistoryException on error
102
     */
103
    public abstract void traverseHistory(File file, String sinceRevision, @Nullable String tillRevision,
104
                         Integer numCommits, List<ChangesetVisitor> visitors) throws HistoryException;
105

106
    public History getHistory(File file, String sinceRevision, String tillRevision,
107
                              Integer numCommits) throws HistoryException {
108

109
        if (numCommits != null && numCommits <= 0) {
1✔
110
            return null;
×
111
        }
112

113
        HistoryCollector historyCollector = new HistoryCollector(isMergeCommitsEnabled());
1✔
114
        traverseHistory(file, sinceRevision, tillRevision, numCommits, List.of(historyCollector));
1✔
115
        History history = new History(historyCollector.entries, historyCollector.renamedFiles,
1✔
116
                historyCollector.latestRev);
117

118
        // Assign tags to changesets they represent.
119
        if (RuntimeEnvironment.getInstance().isTagsEnabled() && hasFileBasedTags()) {
1✔
120
            assignTagsInHistory(history);
1✔
121
        }
122

123
        return history;
1✔
124
    }
125

126
    @Override
127
    protected void doCreateCache(HistoryCache cache, String sinceRevision, File directory) throws HistoryException, CacheException {
128
        RuntimeEnvironment env = RuntimeEnvironment.getInstance();
1✔
129

130
        FileCollector fileCollector = null;
1✔
131
        Project project = Project.getProject(directory);
1✔
132
        if (project != null && isHistoryBasedReindex() && isHistoryEnabled()) {
1✔
133
            // The fileCollector has to go through merge changesets no matter what the configuration says
134
            // in order to detect the files that need to be indexed.
135
            fileCollector = new FileCollector(true);
1✔
136
        }
137

138
        if (!env.isHistoryCachePerPartesEnabled()) {
1✔
139
            LOGGER.log(Level.INFO, "repository {0} supports per partes history cache creation however " +
1✔
140
                    "it is disabled in the configuration. Generating history cache as whole.", this);
141

142
            HistoryCollector historyCollector = new HistoryCollector(isMergeCommitsEnabled());
1✔
143
            List<ChangesetVisitor> visitors = new ArrayList<>();
1✔
144
            visitors.add(historyCollector);
1✔
145
            if (fileCollector != null) {
1✔
146
                visitors.add(fileCollector);
1✔
147
            }
148
            try (Progress progress = new Progress(LOGGER, String.format("changesets traversed of %s", this),
1✔
149
                    Level.FINER)) {
150
                ProgressVisitor progressVisitor = new ProgressVisitor(progress);
1✔
151
                visitors.add(progressVisitor);
1✔
152
                traverseHistory(directory, sinceRevision, null, null, visitors);
1✔
153
            }
154
            History history = new History(historyCollector.entries, historyCollector.renamedFiles,
1✔
155
                    historyCollector.latestRev);
156

157
            // Assign tags to changesets they represent.
158
            if (env.isTagsEnabled() && hasFileBasedTags()) {
1✔
159
                assignTagsInHistory(history);
×
160
            }
161

162
            finishCreateCache(cache, history, null);
1✔
163

164
            updateFileCollector(fileCollector, project);
1✔
165

166
            return;
1✔
167
        }
168

169
        // For repositories that supports this, avoid storing complete History in memory
170
        // (which can be sizeable, at least for the initial indexing, esp. if merge changeset support is enabled),
171
        // by splitting the work into multiple chunks.
172
        BoundaryChangesets boundaryChangesets = new BoundaryChangesets(this);
1✔
173
        List<String> boundaryChangesetList = new ArrayList<>(boundaryChangesets.getBoundaryChangesetIDs(sinceRevision));
1✔
174
        boundaryChangesetList.add(null);    // to finish the last step in the cycle below
1✔
175
        LOGGER.log(Level.FINE, "boundary changesets: {0}", boundaryChangesetList);
1✔
176
        int cnt = 0;
1✔
177
        for (String tillRevision: boundaryChangesetList) {
1✔
178
            Statistics stat = new Statistics();
1✔
179
            LOGGER.log(Level.FINEST, "storing history cache for revision range ({0}, {1})",
1✔
180
                    new Object[]{sinceRevision, tillRevision});
181

182
            HistoryCollector historyCollector = new HistoryCollector(isMergeCommitsEnabled());
1✔
183
            List<ChangesetVisitor> visitors = new ArrayList<>();
1✔
184
            visitors.add(historyCollector);
1✔
185
            if (fileCollector != null) {
1✔
186
                visitors.add(fileCollector);
1✔
187
            }
188

189
            try (Progress progress = new Progress(LOGGER,
1✔
190
                    String.format("changesets traversed of %s (range %s %s)", this, sinceRevision, tillRevision),
1✔
191
                    Level.FINER)) {
192
                ProgressVisitor progressVisitor = new ProgressVisitor(progress);
1✔
193
                visitors.add(progressVisitor);
1✔
194
                traverseHistory(directory, sinceRevision, tillRevision, null, visitors);
1✔
195
            }
196
            History history = new History(historyCollector.entries, historyCollector.renamedFiles,
1✔
197
                    historyCollector.latestRev);
198

199
            // Assign tags to changesets they represent.
200
            if (env.isTagsEnabled() && hasFileBasedTags()) {
1✔
UNCOV
201
                assignTagsInHistory(history);
×
202
            }
203

204
            finishCreateCache(cache, history, tillRevision);
1✔
205
            sinceRevision = tillRevision;
1✔
206
            stat.report(LOGGER, Level.FINE, String.format("Finished chunk %d/%d of history cache for repository '%s'",
1✔
207
                    ++cnt, boundaryChangesetList.size(), this.getDirectoryName()));
1✔
208
        }
1✔
209

210
        updateFileCollector(fileCollector, project);
1✔
211
    }
1✔
212

213
    private void updateFileCollector(FileCollector fileCollector, Project project) {
214
        RuntimeEnvironment env = RuntimeEnvironment.getInstance();
1✔
215

216
        if (project != null && fileCollector != null) {
1✔
217
            FileCollector fileCollectorEnv = env.getFileCollector(project.getName());
1✔
218
            if (fileCollectorEnv == null) {
1✔
219
                env.setFileCollector(project.getName(), fileCollector);
1✔
220
            } else {
221
                fileCollectorEnv.addFiles(fileCollector.getFiles());
1✔
222
            }
223
        }
224
    }
1✔
225
}
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

© 2025 Coveralls, Inc