net.oneandone.maven.plugins.prerelease.core.WorkingCopy.java Source code

Java tutorial

Introduction

Here is the source code for net.oneandone.maven.plugins.prerelease.core.WorkingCopy.java

Source

/**
 * Copyright 1&1 Internet AG, https://github.com/1and1/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.oneandone.maven.plugins.prerelease.core;

import net.oneandone.maven.plugins.prerelease.util.Subversion;
import net.oneandone.sushi.fs.World;
import net.oneandone.sushi.fs.file.FileNode;
import net.oneandone.sushi.launcher.Failure;
import net.oneandone.sushi.util.Strings;
import net.oneandone.sushi.xml.Selector;
import net.oneandone.sushi.xml.XmlException;
import org.apache.maven.plugin.logging.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

public class WorkingCopy {
    /** TODO: memory consumption */
    public static WorkingCopy load(FileNode workingCopy) throws IOException, SAXException, XmlException {
        World world;
        String output;
        Document doc;
        String path;
        Selector selector;
        Element wcStatus;
        List<FileNode> modifications;
        SortedSet<Long> revisions;
        SortedSet<Long> changes;
        // maps paths to the change revision
        Map<String, Long> maybePendings;
        List<String> pendings;
        long revision;
        long change;
        String props;

        output = Subversion.launcher(workingCopy, "--xml", "-v", "--show-updates", "status").exec();
        world = workingCopy.getWorld();
        doc = world.getXml().getBuilder().parseString(output);
        selector = world.getXml().getSelector();
        modifications = new ArrayList<>();
        revisions = new TreeSet<>();
        changes = new TreeSet<>();
        maybePendings = new HashMap<>();
        for (Element entry : selector.elements(doc, "status/target/entry")) {
            path = entry.getAttribute("path");
            wcStatus = selector.element(entry, "wc-status");
            props = wcStatus.getAttribute("props");
            if ("normal".equals(wcStatus.getAttribute("item"))
                    && ("none".equals(props) || "normal".equals(props))) {
                revision = Long.parseLong(wcStatus.getAttribute("revision"));
                revisions.add(revision);
                change = Long.parseLong(selector.element(wcStatus, "commit").getAttribute("revision"));
                changes.add(change);
                if (selector.elementOpt(entry, "repos-status") != null) {
                    maybePendings.put(entry.getAttribute("path"), change);
                }
            } else {
                modifications.add(workingCopy.join(path));
            }
        }
        if (changes.size() == 0) {
            throw new IOException("Cannot determine svn status - is this directory under svn?");
        }
        if (revisions.size() == 0) {
            throw new IllegalStateException();
        }
        if (changes.last() > revisions.last()) {
            throw new IllegalStateException(changes.last() + " vs " + revisions.last());
        }
        pendings = new ArrayList<>();
        for (Map.Entry<String, Long> entry : maybePendings.entrySet()) {
            if (entry.getValue() < revisions.last()) {
                output = Subversion.launcher(workingCopy, "log", "--xml", "-q",
                        "-r" + (entry.getValue() + 1) + ":" + revisions.last(), entry.getKey()).exec();
                doc = world.getXml().getBuilder().parseString(output);
                if (selector.elements(doc, "log/logentry").size() > 0) {
                    pendings.add(entry.getKey());
                }
            }
        }
        return new WorkingCopy(workingCopy, modifications, revisions, changes, pendings);
    }

    //--

    public final FileNode directory;
    public final List<FileNode> modifications;
    public final SortedSet<Long> revisions;
    public final SortedSet<Long> changes;
    public final List<String> pendingUpdates;

    public WorkingCopy(FileNode directory, List<FileNode> modifications, SortedSet<Long> revisions,
            SortedSet<Long> changes, List<String> pendingUpdates) {
        this.directory = directory;
        this.modifications = modifications;
        this.revisions = revisions;
        this.changes = changes;
        this.pendingUpdates = pendingUpdates;
    }

    public long revision() {
        return changes.last();
    }

    public void check() throws UncommitedChanges, PendingUpdates {
        if (!modifications.isEmpty()) {
            throw new UncommitedChanges(modifications);
        }
        if (!pendingUpdates.isEmpty()) {
            throw new PendingUpdates(revisions.last(), pendingUpdates);
        }
    }

    public Descriptor checkCompatibility(Descriptor descriptor) throws Exception {
        String svnurlWorkspace;

        svnurlWorkspace = Subversion.workspaceUrl(directory);
        svnurlWorkspace = Strings.removeRightOpt(svnurlWorkspace, "/");
        if (!svnurlWorkspace.equals(descriptor.svnOrig)) {
            throw new SvnUrlMismatch(svnurlWorkspace, descriptor.svnOrig);
        }
        if (revision() != descriptor.revision) {
            throw new RevisionMismatch(revision(), descriptor.revision);
        }
        return descriptor;
    }

    public void update(Log log) throws Failure {
        log.info(Subversion.launcher(directory, "update").exec());
    }
}