Package hudson.plugins.git

Source Code of hudson.plugins.git.GitChangeSet$Path

/*
* The MIT License
*
* Copyright (c) 2004-2011, Oracle Corporation, Andrew Bayer, Anton Kozak, Nikita Levyankov, rogerhu
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package hudson.plugins.git;

import hudson.MarkupText;
import hudson.model.User;
import hudson.scm.ChangeLogAnnotator;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.AffectedFile;
import hudson.scm.EditType;
import hudson.tasks.Mailer;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;

import static hudson.Util.fixEmpty;

/**
* Represents a change set.
*
* @author Nigel Magnay
* @author Nikita Levyankov
*/
public class GitChangeSet extends ChangeLogSet.Entry {
    private static final Logger LOGGER = Logger.getLogger(GitSCM.class.getName());

    private static final Pattern FILE_LOG_ENTRY = Pattern.compile(
        "^:[0-9]{6} [0-9]{6} ([0-9a-f]{40}) ([0-9a-f]{40}) ([ACDMRTUX])(?>[0-9]+)?\t(.*)$");
    private static final Pattern AUTHOR_ENTRY = Pattern.compile("^author (.*) <(.*)> (.*) (.*)$");
    private static final Pattern COMMITTER_ENTRY = Pattern.compile("^committer (.*) <(.*)> (.*) (.*)$");
    private static final Pattern RENAME_SPLIT = Pattern.compile("^(.*?)\t(.*)$");

    private static final String NULL_HASH = "0000000000000000000000000000000000000000";
    private String committer;
    private String committerEmail;
    private String committerTime;
    private String committerTz;
    private String author;
    private String authorEmail;
    private String authorTime;
    private String authorTz;
    private String comment;
    private String title;
    private String id;
    private String parentCommit;
    private Collection<Path> paths = new HashSet<Path>();
    private boolean authorOrCommitter;

    public GitChangeSet(List<String> lines, boolean authorOrCommitter) {
        this.authorOrCommitter = authorOrCommitter;
        if (lines.size() > 0) {
            parseCommit(lines);
        }
    }

    private void parseCommit(List<String> lines) {

        String message = "";

        for (String line : lines) {
            if (line.length() > 0) {
                if (line.startsWith("commit ")) {
                    this.id = line.split(" ")[1];
                } else if (line.startsWith("parent ")) {
                    this.parentCommit = line.split(" ")[1];
                } else if (line.startsWith("committer ")) {
                    Matcher committerMatcher = COMMITTER_ENTRY.matcher(line);
                    if (committerMatcher.matches() && committerMatcher.groupCount() >= 4) {
                        this.committer = committerMatcher.group(1);
                        this.committerEmail = committerMatcher.group(2);
                        this.committerTime = committerMatcher.group(3);
                        this.committerTz = committerMatcher.group(4);
                    }
                } else if (line.startsWith("author ")) {
                    Matcher authorMatcher = AUTHOR_ENTRY.matcher(line);
                    if (authorMatcher.matches() && authorMatcher.groupCount() >= 4) {
                        this.author = authorMatcher.group(1);
                        this.authorEmail = authorMatcher.group(2);
                        this.authorTime = authorMatcher.group(3);
                        this.authorTz = authorMatcher.group(4);
                    }
                } else if (line.startsWith("    ")) {
                    message += line.substring(4) + "\n";
                } else if (':' == line.charAt(0)) {
                    Matcher fileMatcher = FILE_LOG_ENTRY.matcher(line);
                    if (fileMatcher.matches() && fileMatcher.groupCount() >= 4) {
                        String mode = fileMatcher.group(3);
                        if (mode.length() == 1) {
                            String src = null;
                            String dst = null;
                            String path = fileMatcher.group(4);
                            char editMode = mode.charAt(0);
                            if (editMode == 'M' || editMode == 'A' || editMode == 'D'
                                || editMode == 'R' || editMode == 'C') {
                                src = parseHash(fileMatcher.group(1));
                                dst = parseHash(fileMatcher.group(2));
                            }

                            // Handle rename as two operations - a delete and an add
                            if (editMode == 'R') {
                                Matcher renameSplitMatcher = RENAME_SPLIT.matcher(path);
                                if (renameSplitMatcher.matches() && renameSplitMatcher.groupCount() >= 2) {
                                    String oldPath = renameSplitMatcher.group(1);
                                    String newPath = renameSplitMatcher.group(2);
                                    this.paths.add(new Path(src, dst, 'D', oldPath, this));
                                    this.paths.add(new Path(src, dst, 'A', newPath, this));
                                }
                            }
                            // Handle copy as an add
                            else if (editMode == 'C') {
                                Matcher copySplitMatcher = RENAME_SPLIT.matcher(path);
                                if (copySplitMatcher.matches() && copySplitMatcher.groupCount() >= 2) {
                                    String newPath = copySplitMatcher.group(2);
                                    this.paths.add(new Path(src, dst, 'A', newPath, this));
                                }
                            } else {
                                this.paths.add(new Path(src, dst, editMode, path, this));
                            }
                        }
                    }
                }
            }
        }

        this.comment = message;

        int endOfFirstLine = this.comment.indexOf('\n');
        if (endOfFirstLine == -1) {
            this.title = this.comment;
        } else {
            this.title = this.comment.substring(0, endOfFirstLine);
        }
    }

    private String parseHash(String hash) {
        return NULL_HASH.equals(hash) ? null : hash;
    }

    @Exported
    public String getDate() {
        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String dateStr;
        String csTime;
        String csTz;
        Date csDate;

        if (authorOrCommitter) {
            csTime = this.authorTime;
            csTz = this.authorTz;
        } else {
            csTime = this.committerTime;
            csTz = this.committerTz;
        }

        try {
            csDate = new Date(Long.parseLong(csTime) * 1000L);
        } catch (NumberFormatException e) {
            csDate = new Date();
        }

        dateStr = fmt.format(csDate) + " " + csTz;

        return dateStr;
    }

    @Override
    public void setParent(ChangeLogSet parent) {
        LOGGER.log(Level.FINEST, "Set parent " + parent);
        super.setParent(parent);
    }

    public String getParentCommit() {
        return parentCommit;
    }

    /**
     * {@inheritDoc}
     */
    public Collection<String> getAffectedPaths() {
        Collection<String> affectedPaths = new HashSet<String>(this.paths.size());
        for (Path file : this.paths) {
            affectedPaths.add(file.getPath());
        }
        return affectedPaths;
    }

    /**
     * Gets the files that are changed in this commit.
     *
     * @return can be empty but never null.
     */
    @Exported
    public Collection<Path> getPaths() {
        return paths;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Path> getAffectedFiles() {
        return this.paths;
    }

    @Exported
    public User getAuthor() {
        String csAuthor;
        String csAuthorEmail;

        // If true, use the author field from git log rather than the committer.
        if (authorOrCommitter) {
            csAuthor = this.author;
            csAuthorEmail = this.authorEmail;
        } else {
            csAuthor = this.committer;
            csAuthorEmail = this.committerEmail;
        }

        if (csAuthor == null) {
            throw new RuntimeException("No author in this changeset!");
        }

        return findOrCreateUser(csAuthor, csAuthorEmail, isCreateAccountBaseOnCommitterEmail());
    }

    /**
     * Returns user of the change set.
     *
     * @param csAuthor user name.
     * @param csAuthorEmail user email.
     * @param createAccountBaseOnCommitterEmail true if create new user based on committer's email.
     * @return {@link User}
     */
    User findOrCreateUser(String csAuthor, String csAuthorEmail, boolean createAccountBaseOnCommitterEmail) {
        User user;
        if (createAccountBaseOnCommitterEmail) {
            user = User.get(csAuthorEmail, true);
            try {
                user.setFullName(csAuthor);
                user.save();
            } catch (IOException e) {
                LOGGER.log(Level.FINEST, "Could not set author name to user properties.", e);
            }
        } else {
            user = User.get(csAuthor, true);
        }

        // set email address for user if needed
        if (fixEmpty(csAuthorEmail) != null) {
            try {
                user.addProperty(new Mailer.UserProperty(csAuthorEmail));
            } catch (IOException e) {
                LOGGER.log(Level.FINEST, "Failed to add email to user properties.", e);
            }
        }
        return user;
    }

    private boolean isCreateAccountBaseOnCommitterEmail() {
        ChangeLogSet parent = getParent();
        boolean createAccountBaseOnCommitterEmail = false;
        if (parent != null) {
            createAccountBaseOnCommitterEmail = ((GitSCM) parent.getBuild().getProject().getScm()).
                isCreateAccountBaseOnCommitterEmail();
        }
        return createAccountBaseOnCommitterEmail;
    }

    /**
     * Gets the author name for this changeset - note that this is mainly here
     * so that we can test authorOrCommitter without needing a fully instantiated
     * Hudson (which is needed for User.get in getAuthor()).
     *
     * @return author name.
     */
    public String getAuthorName() {
        String csAuthor;

        // If true, use the author field from git log rather than the committer.
        if (authorOrCommitter) {
            csAuthor = this.author;
        } else {
            csAuthor = this.committer;
        }

        if (csAuthor == null) {
            throw new RuntimeException("No author in this changeset!");
        }

        return csAuthor;
    }

    /**
     * {@inheritDoc}
     */
    public String getUser() {
        return getAuthorName();
    }

    @Exported
    public String getMsg() {
        return this.title;
    }

    @Exported
    public String getId() {
        return this.id;
    }

    /**
     * @return revision id
     * @deprecated
     * @since 2.0.1
     * @see #getCurrentRevision()
     */
    public String getRevision() {
        return this.id;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getCurrentRevision() {
        return getRevision();
    }

    @Exported
    public String getComment() {
        return this.comment;
    }

    /**
     * Gets {@linkplain #getComment() the comment} fully marked up by {@link ChangeLogAnnotator}.
     */
    public String getCommentAnnotated() {
        MarkupText markup = new MarkupText(getComment());
        for (ChangeLogAnnotator a : ChangeLogAnnotator.all()) {
            a.annotate(getParent().build, this, markup);
        }

        return markup.toString(false);
    }

    @ExportedBean(defaultVisibility = 999)
    public static class Path implements AffectedFile {

        private String src;
        private String dst;
        private char action;
        private String path;
        private GitChangeSet changeSet;

        private Path(String source, String destination, char action, String filePath, GitChangeSet changeSet) {
            this.src = source;
            this.dst = destination;
            this.action = action;
            this.path = filePath;
            this.changeSet = changeSet;
        }

        public String getSrc() {
            return src;
        }

        public String getDst() {
            return dst;
        }

        @Exported(name = "file")
        public String getPath() {
            return path;
        }

        public GitChangeSet getChangeSet() {
            return changeSet;
        }

        @Exported
        public EditType getEditType() {
            switch (action) {
                case 'A':
                    return EditType.ADD;
                case 'D':
                    return EditType.DELETE;
                default:
                    return EditType.EDIT;
            }
        }
    }
}
TOP

Related Classes of hudson.plugins.git.GitChangeSet$Path

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.