svnserver.repository.git.prop.GitIgnore.java Source code

Java tutorial

Introduction

Here is the source code for svnserver.repository.git.prop.GitIgnore.java

Source

/**
 * This file is part of git-as-svn. It is subject to the license terms
 * in the LICENSE file found in the top-level directory of this distribution
 * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn,
 * including this file, may be copied, modified, propagated, or distributed
 * except according to the terms contained in the LICENSE file.
 */
package svnserver.repository.git.prop;

import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tmatesoft.svn.core.SVNProperty;
import svnserver.repository.git.path.PathMatcher;
import svnserver.repository.git.path.Wildcard;

import java.util.*;
import java.util.regex.PatternSyntaxException;

/**
 * Parse and processing .gitignore.
 *
 * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com>
 */
final class GitIgnore implements GitProperty {

    @NotNull
    private static final Logger log = LoggerFactory.getLogger(GitIgnore.class);

    @NotNull
    private final List<PathMatcher> matchers;
    // svn:global-ignores
    @NotNull
    private final String[] global;
    // svn:ignore
    @NotNull
    private final String[] local;

    /**
     * Parse and store .gitignore data (http://git-scm.com/docs/gitignore).
     * <p>
     * Important:
     * * An optional prefix "!" which negates the pattern is not supported.
     * * Mask trailing slash is not supported (/foo/bar/ works like /foo/bar).
     *
     * @param content Original file content.
     */
    public GitIgnore(@NotNull String content) {
        final List<String> localList = new ArrayList<>();
        final List<String> globalList = new ArrayList<>();
        matchers = new ArrayList<>();
        for (String rawLine : content.split("\n")) {
            final String line = trimLine(rawLine);
            if (line.isEmpty())
                continue;
            try {
                final Wildcard wildcard = new Wildcard(line);
                if (wildcard.isSvnCompatible()) {
                    processMatcher(localList, globalList, matchers, wildcard.getMatcher());
                }
            } catch (InvalidPatternException | PatternSyntaxException e) {
                log.warn("Found invalid git pattern: {}", line);
            }
        }
        local = localList.toArray(new String[localList.size()]);
        global = globalList.toArray(new String[globalList.size()]);
    }

    private GitIgnore(@NotNull List<String> local, @NotNull List<String> global,
            @NotNull List<PathMatcher> matchers) {
        this.local = local.toArray(new String[local.size()]);
        this.global = global.toArray(new String[global.size()]);
        this.matchers = matchers;
    }

    private static void processMatcher(@NotNull List<String> local, @NotNull List<String> global,
            @NotNull List<PathMatcher> matchers, @Nullable PathMatcher matcher) {
        if (matcher == null) {
            return;
        }
        final String maskGlobal = matcher.getSvnMaskGlobal();
        if (maskGlobal != null) {
            global.add(maskGlobal);
            return;
        }
        final String maskLocal = matcher.getSvnMaskLocal();
        if (maskLocal != null) {
            local.add(maskLocal);
        }
        matchers.add(matcher);
    }

    private String trimLine(@NotNull String line) {
        if (line.isEmpty() || line.startsWith("#") || line.startsWith("!") || line.startsWith("\\!"))
            return "";
        // Remove trailing spaces end escapes.
        int end = line.length();
        while (end > 0) {
            final char c = line.charAt(end - 1);
            if (c != ' ') {
                if ((end < line.length()) && (line.charAt(end - 1) == '\\')) {
                    end++;
                }
                break;
            }
            end--;
        }
        return line.substring(0, end);
    }

    @Override
    public void apply(@NotNull Map<String, String> props) {
        if (global.length > 0) {
            props.compute(SVNProperty.INHERITABLE_IGNORES, (key, value) -> addIgnore(value, global));
        }
        if (local.length > 0) {
            props.compute(SVNProperty.IGNORE, (key, value) -> addIgnore(value, local));
        }
    }

    @Nullable
    @Override
    public String getFilterName() {
        return null;
    }

    private static String addIgnore(@Nullable String oldValue, @NotNull String[] ignores) {
        final Set<String> contains = new HashSet<>();
        final StringBuilder result = new StringBuilder();
        if (oldValue != null) {
            result.append(oldValue);
            contains.addAll(Arrays.asList(oldValue.split("\n")));
        }
        for (String ignore : ignores) {
            if (contains.add(ignore)) {
                result.append(ignore).append('\n');
            }
        }
        return result.toString();
    }

    @Nullable
    @Override
    public GitProperty createForChild(@NotNull String name, @NotNull FileMode fileMode) {
        if (matchers.isEmpty() || (fileMode.getObjectType() == Constants.OBJ_BLOB)) {
            return null;
        }
        final List<String> localList = new ArrayList<>();
        final List<String> globalList = new ArrayList<>();
        final List<PathMatcher> childMatchers = new ArrayList<>();
        for (PathMatcher matcher : matchers) {
            processMatcher(localList, globalList, childMatchers, matcher.createChild(name, true));
        }
        if (localList.isEmpty() && globalList.isEmpty() && childMatchers.isEmpty()) {
            return null;
        }
        return new GitIgnore(localList, globalList, childMatchers);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        GitIgnore gitIgnore = (GitIgnore) o;

        return Arrays.equals(global, gitIgnore.global) && Arrays.equals(local, gitIgnore.local)
                && matchers.equals(gitIgnore.matchers);
    }

    @Override
    public int hashCode() {
        int result = matchers.hashCode();
        result = 31 * result + Arrays.hashCode(global);
        result = 31 * result + Arrays.hashCode(local);
        return result;
    }
}