JGit使用

pom依赖

<dependency>
    <groupId>org.eclipse.jgit</groupId>
    <artifactId>org.eclipse.jgit</artifactId>
    <version>3.5.0.201409260305-r</version>
</dependency>

jgit客户端常用功能实现

import com.jcraft.jsch.Session;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.TransportCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.SshTransport;

/**
 * 功能描述:
 * 1. 将远程仓库pre分支拉取至本地,如果pre不存在则使用master分支
 * 2. 如果本地存在temp4deleteSwitches分支则删除分支,从本地pre分支check出temp4deleteSwitches分支
 * 3. 如果远程存在temp4deleteSwitches分支则删除分支,将本地temp4deleteSwitches分支推送至远程temp4deleteSwitches分支
 * @author 会灰翔的灰机
 * @date 2019/11/1
 */
@Slf4j
public class GitService {

    /**
     * 本地操作使用分支名称
     */
    public static final String GIT_TEMP = "temp4deleteSwitches";
    public static final String PRE = "pre";
    public static final String MASTER = "master";
    public static final String SEPARATOR = "/";
    /**
     * 与git服务使用ssh认证
     */
    private static final SshSessionFactory SSH_SESSION_FACTORY = new JschConfigSessionFactory() {
        @Override
        protected void configure(Host host, Session session) {

        }
    };

    private String gitDir = "/tmp";

    public void autoCommit() throws IOException, GitAPIException {
        Git git;
        String gitPath = getGitPath(gitlabProjectDTO.getName());
        // 1. 如果本地git仓库已存在则打开,否则clone至本地
        if (new File(gitPath).exists()) {
            git = open(gitPath);
        } else {
            git = clone(gitlabProjectDTO.getSshUrlToRepo(), gitPath);
        }
        Ref ref = null;
        if (git != null) {
            ref = getRemotePreOrMasterRef(git);
            if (ref == null) {
                log.error("不存在pre或master分支,操作失败。gitlabProjectDTOJsonDTO={}",
                        gitlabProjectDTO);
            }
            ref = checkout2Temp(git, ref);
        }
        List<String> modifiedFiles = new LinkedList<>();
        add(git, modifiedFiles);
        commit(git);
        push(git, ref);
    }

    /**
     * 打开本地git仓库
     * @param uri : 
     * @return org.eclipse.jgit.api.Git :
     */
    public Git open(String uri) throws IOException {
        Git git = null;
        File file = new File(uri);
        if (file.exists()) {
            git = Git.open(file);
        }
        return git;
    }

    /**
     * 克隆pre分支,如果不存在pre分支则克隆master分支
     * @param uri : 
     * @param gitDir :
     * @return org.eclipse.jgit.api.Git :
     */
    public Git clone(String uri, String gitDir) throws GitAPIException {
        Git git;
        boolean useMaster = false;
        try {
            git = clone(uri, gitDir, PRE);
        } catch (GitAPIException e) {
            e.printStackTrace();
            useMaster = true;
            git = clone(uri, gitDir, MASTER);
        }
        if (findRemoteRef(git, PRE) != null && useMaster) {
            throw new RuntimeException("clone pre分支失败");
        }
        return git;
    }

    /**
     * git clone,如果本地目录存在则先删除后再clone
     * @param uri : 
     * @param gitDir : 
     * @param branchName : 
     * @return org.eclipse.jgit.api.Git :
     */
    public Git clone(String uri, String gitDir, String branchName) throws GitAPIException {
        CloneCommand cloneCommand = Git.cloneRepository();
        File file = new File(gitDir);
        if (file.exists()) {
            if (!file.delete()) {
                return null;
            }
        }
        configTransport(cloneCommand);
        cloneCommand.setURI(uri);
        cloneCommand.setDirectory(file);
        cloneCommand.setBranch(branchName);
        cloneCommand.setNoCheckout(true);
        return cloneCommand.call();
    }

    /**
     * Git pull
     * @param git : 
     * @param ref :
     * @return org.eclipse.jgit.api.PullResult :
     */
    public PullResult pull(Git git, Ref ref) throws GitAPIException {
        PullCommand pull = git.pull();
        configTransport(pull);
        pull.setRemoteBranchName(ref.getName());
        return pull.call();
    }

    /**
     * git push 命令
     * @param git : 
     * @param ref :
     * @return java.lang.Iterable<org.eclipse.jgit.transport.PushResult> :
     */
    public Iterable<PushResult> push(Git git, Ref ref) throws GitAPIException {
        PushCommand push = git.push();
        configTransport(push);
        push.add(ref);
        push.setForce(true);
        return push.call();
    }

    /**
     * git add 命令
     * @param git : 
     * @param modifiedFiles :
     * @return org.eclipse.jgit.dircache.DirCache :
     */
    public DirCache add(Git git, List<String> modifiedFiles) throws GitAPIException {
        AddCommand add = git.add();
        Status status = git.status().call();
        Set<String> modified = status.getModified();
        modified.forEach(modifiedFile -> {
            if (!modifiedFiles.contains(modifiedFile.substring(modifiedFile.lastIndexOf(SEPARATOR)))) {
                log.warn("has added unwanted file:{}", modifiedFile);
            }
            add.addFilepattern(modifiedFile);
        });
        return add.call();
    }

    /**
     * 提交代码
     * @param git : 
     * @return org.eclipse.jgit.revwalk.RevCommit :
     */
    public RevCommit commit(Git git) throws GitAPIException {
        CommitCommand commit = git.commit();
        commit.setMessage("auto commit");
        return commit.call();
    }

    public String getGitPath(String projectName) {
        return gitDir + "/" + projectName;
    }

    /**
     * 配置ssh会话
     * @param transportCommand :
     */
    public void configTransport(TransportCommand transportCommand){
        transportCommand.setTransportConfigCallback((transport) -> {
            SshTransport sshTransport = (SshTransport)transport;
            sshTransport.setSshSessionFactory(SSH_SESSION_FACTORY);
        });
    }

    /**
     * 1. checkout至pre或master分支
     * 2. git pull拉取最新代码
     * 3. 从本地pre或master分支checkout至临时分支
     * @param git : git客户端实例
     * @param ref : 当前分支引用
     * @return org.eclipse.jgit.lib.Ref : checkout分支后的分支引用
     */
    public Ref checkout2Temp(Git git, Ref ref) throws GitAPIException, IOException {
        // 1. 将远程分支check至本地,分支名称与远程同名,如果本地分支不存在则创建
        CheckoutCommand checkout = git.checkout();
        // 设置远程分支
        checkout.setStartPoint(ref.getName());
        // 设置本地分支名称
        checkout.setName(getBranchName(ref));
        // 如果本地不存在同名分支则创建
        if (!refExist(git, getBranchName(ref))) {
            checkout.setCreateBranch(true);
        }
        Ref preOrMasterRef = checkout.call();
        if (preOrMasterRef == null) {
            log.error("checkout 操作失败,结果为空");
            return null;
        }
        // pull最新代码
        PullResult pullResult = pull(git, preOrMasterRef);
        if (!pullResult.isSuccessful()) {
            log.error("pull 操作失败:{}", pullResult);
            return null;
        }
        // 如果本地存在临时分支则删除
        if (refExist(git, GIT_TEMP)) {
            git.branchDelete().setBranchNames(GIT_TEMP).setForce(true).call();
        }
        // 如果远程存在临时分支则删除
        Ref remoteTemp = findRemoteRef(git, GIT_TEMP);
        if (remoteTemp != null) {
            RefSpec refSpec = new RefSpec().setSource(null).setDestination(getDestination(GIT_TEMP));
            git.push().setRefSpecs(refSpec).setRemote(Constants.DEFAULT_REMOTE_NAME).call();
        }
        // 创建本地临时分支
        checkout = git.checkout();
        checkout.setStartPoint(ref.getName());
        checkout.setName(GIT_TEMP);
        checkout.setCreateBranch(true);
        return checkout.call();
    }

    /**
     * 查找远程分支
     * @param git : git客户端实例
     * @param branchName : 分支名称
     * @return org.eclipse.jgit.lib.Ref : 返回远程分支引用
     */
    public Ref findRemoteRef(Git git, String branchName) throws GitAPIException {
        Ref existRef = null;
        if (git != null) {
            List<Ref> refs = git.branchList().setListMode(ListMode.REMOTE).call();
            for (Ref ref : refs) {
                if (getBranchName(ref).equals(branchName)) {
                    existRef = ref;
                    break;
                }
            }
        }
        return existRef;
    }

    /**
     * 判断本地分支是否存在
     * @param git : 
     * @param branchName : 分支名称
     * @return boolean : 是否存在
     */
    public boolean refExist(Git git, String branchName) throws IOException {
        return git.getRepository().resolve(branchName) != null;
    }

    public Ref getRemotePreOrMasterRef(Git git) throws GitAPIException {
        Ref ref = findRemoteRef(git, PRE);
        if (ref == null) {
            ref = findRemoteRef(git, MASTER);
        }
        return ref;
    }

    public String getBranchName(Ref ref) {
        return ref.getName().substring(ref.getName().lastIndexOf(SEPARATOR) + 1);
    }

    public String getDestination(String branchName) {
        return Constants.R_HEADS + branchName;
    }
}

用户名密码方式连接Git

@Value("${username:none}")
private String username;
@Value("${password:none}")
private String password;
private static CredentialsProvider credentialsProvider;

public void configTransport(TransportCommand<?,?> transportCommand, boolean useSsh){
    if (useSsh) {
        transportCommand.setTransportConfigCallback((transport) -> {
            SshTransport sshTransport = (SshTransport) transport;
            sshTransport.setSshSessionFactory(SSH_SESSION_FACTORY);
        });
    } else {
        transportCommand.setCredentialsProvider(credentialsProvider);
    }
}
@Override
public void afterPropertiesSet() {
    if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
        credentialsProvider = new UsernamePasswordCredentialsProvider(username, password);
    }
}

版权声明:本文为u010597819原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。