• 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

43.14
/opengrok-indexer/src/main/java/org/opengrok/indexer/history/RCSRepository.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) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
22
 * Portions Copyright (c) 2018, Chris Fraire <cfraire@me.com>.
23
 */
24
package org.opengrok.indexer.history;
25

26
import java.io.File;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.OutputStream;
30
import java.util.ArrayList;
31
import java.util.List;
32
import java.util.function.Supplier;
33
import java.util.logging.Level;
34
import java.util.logging.Logger;
35

36
import org.opengrok.indexer.configuration.CommandTimeoutType;
37
import org.opengrok.indexer.configuration.RuntimeEnvironment;
38
import org.opengrok.indexer.util.Executor;
39
import org.opengrok.indexer.logger.LoggerFactory;
40
import org.opengrok.indexer.util.LazilyInstantiate;
41

42
/**
43
 * Access to an RCS repository.
44
 */
45
public class RCSRepository extends Repository {
46

47
    private static final Logger LOGGER = LoggerFactory.getLogger(RCSRepository.class);
1✔
48

49
    private static final long serialVersionUID = 1L;
50

51
    /**
52
     * This property name is used to obtain the command to get annotation for this repository.
53
     */
54
    private static final String CMD_BLAME_PROPERTY_KEY = "org.opengrok.indexer.history.RCS.blame";
55
    /**
56
     * The command to use to get annotation if none was given explicitly.
57
     */
58
    private static final String CMD_BLAME_FALLBACK = "blame";
59

60
    /**
61
     * This is a static replacement for 'working' field. Effectively, check if hg is working once in a JVM
62
     * instead of calling it for every MercurialRepository instance.
63
     */
64
    private static final Supplier<Boolean> BLAME_IS_WORKING = LazilyInstantiate.using(RCSRepository::isBlameWorking);
1✔
65

66
    public RCSRepository() {
1✔
67
        type = "RCS";
1✔
68

69
        ignoredDirs.add("RCS");
1✔
70
    }
1✔
71

72
    private static boolean isBlameWorking() {
73
        String repoCommand = getCommand(MercurialRepository.class, CMD_BLAME_PROPERTY_KEY, CMD_BLAME_FALLBACK);
1✔
74
        return checkCmd(repoCommand);
1✔
75
    }
76

77
    @Override
78
    public boolean isWorking() {
79
        if (working == null) {
1✔
80
            working = BLAME_IS_WORKING.get();
1✔
81
            ensureCommand(CMD_BLAME_PROPERTY_KEY, CMD_BLAME_FALLBACK);
1✔
82
        }
83
        return working;
1✔
84
    }
85

86
    @Override
87
    boolean fileHasHistory(File file) {
UNCOV
88
        return getRCSFile(file) != null;
×
89
    }
90

91
    @Override
92
    boolean getHistoryGet(OutputStream out, String parent, String basename, String rev) {
93
        try {
94
            File file = new File(parent, basename);
×
95
            File rcsFile = getRCSFile(file);
×
96
            try (InputStream in = new RCSget(rcsFile.getPath(), rev)) {
×
97
                copyBytes(out::write, in);
×
98
            }
99
            return true;
×
100
        } catch (IOException ioe) {
×
101
            LOGGER.log(Level.SEVERE, ioe, () ->
×
102
                    "Failed to retrieve revision " + rev + " of " + basename);
×
103
            return false;
×
104
        }
105
    }
106

107
    @Override
108
    boolean fileHasAnnotation(File file) {
UNCOV
109
        return fileHasHistory(file);
×
110
    }
111

112
    @Override
113
    Annotation annotate(File file, String revision) throws IOException {
UNCOV
114
        List<String> argv = new ArrayList<>();
×
UNCOV
115
        ensureCommand(CMD_BLAME_PROPERTY_KEY, CMD_BLAME_FALLBACK);
×
116

UNCOV
117
        argv.add(RepoCommand);
×
UNCOV
118
        if (revision != null) {
×
119
            argv.add("-r");
×
120
            argv.add(revision);
×
121
        }
UNCOV
122
        argv.add(file.getName());
×
123

UNCOV
124
        Executor executor = new Executor(argv, file.getParentFile(),
×
UNCOV
125
                RuntimeEnvironment.getInstance().getInteractiveCommandTimeout());
×
126

UNCOV
127
        RCSAnnotationParser annotator = new RCSAnnotationParser(file);
×
UNCOV
128
        executor.exec(true, annotator);
×
129

UNCOV
130
        return annotator.getAnnotation();
×
131
    }
132

133
    /**
134
     * Wrap a {@code Throwable} in an {@code IOException} and return it.
135
     */
136
    static IOException wrapInIOException(String message, Throwable t) {
137
        return new IOException(message + ": " + t.getMessage(), t);
×
138
    }
139

140
    @Override
141
    boolean isRepositoryFor(File file, CommandTimeoutType cmdType) {
142
        File rcsDir = new File(file, "RCS");
1✔
143
        if (!rcsDir.isDirectory()) {
1✔
144
            return false;
1✔
145
        }
146

147
        // If there is at least one entry with the ',v' suffix,
148
        // consider this a RCS repository.
149
        String[] list = rcsDir.list((dir, name) ->
1✔
150
            // Technically we should check whether the entry is a file
151
            // however this would incur additional I/O. The pattern
152
            // should be enough.
153
            name.matches(".*,v")
1✔
154
        );
155

156
        return (list.length > 0);
1✔
157
    }
158

159
    /**
160
     * Get a {@code File} object that points to the file that contains
161
     * RCS history for the specified file.
162
     *
163
     * @param file the file whose corresponding RCS file should be found
164
     * @return the file which contains the RCS history, or {@code null} if it
165
     * cannot be found
166
     */
167
    File getRCSFile(File file) {
UNCOV
168
        File dir = new File(file.getParentFile(), "RCS");
×
UNCOV
169
        String baseName = file.getName();
×
UNCOV
170
        File rcsFile = new File(dir, baseName + ",v");
×
UNCOV
171
        return rcsFile.exists() ? rcsFile : null;
×
172
    }
173

174
    @Override
175
    boolean hasHistoryForDirectories() {
176
        return false;
1✔
177
    }
178

179
    @Override
180
    History getHistory(File file) throws HistoryException {
UNCOV
181
        return new RCSHistoryParser().parse(file, this);
×
182
    }
183

184
    @Override
185
    String determineParent(CommandTimeoutType cmdType) throws IOException {
186
        return null;
1✔
187
    }
188

189
    @Override
190
    String determineBranch(CommandTimeoutType cmdType) throws IOException {
191
        return null;
1✔
192
    }
193

194
    @Override
195
    String determineCurrentVersion(CommandTimeoutType cmdType) throws IOException {
196
        return null;
1✔
197
    }
198
}
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