Java tutorial
/* * Copyright 2013 Andrew Romanenco. * * This file is part of Gitt. * * Gitt is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Gitt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Gitt. If not, see <http://www.gnu.org/licenses/>. */ package com.romanenco.gitt.git; import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.io.FileUtils; import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.PullCommand; import org.eclipse.jgit.api.errors.DetachedHeadException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.errors.NoHeadException; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import android.util.Log; import com.romanenco.gitt.GittApp; /** * Common GIT operations based on jgit. * * @author Andrew Romanenco * */ public class GitHelper { private static final String TAG = "GitHelper"; /** * Clone remote HTTP/S repo to local file system. * * @param url * @param localPath * @param user * @param password * @throws GitError */ public static void clone(String url, String localPath, String user, String password, ProgressMonitor monitor) throws GitError { Log.d(TAG, "Cloning: " + url); CloneCommand clone = Git.cloneRepository(); clone.setTimeout(30); // set time out for bad servers clone.setURI(url); clone.setDirectory(new File(localPath)); if ((user != null) && (password != null)) { UsernamePasswordCredentialsProvider access = new UsernamePasswordCredentialsProvider(user, password); clone.setCredentialsProvider(access); } if (monitor != null) { clone.setProgressMonitor(monitor); } try { FileUtils.deleteDirectory(new File(localPath)); clone.call(); return; } catch (InvalidRemoteException e) { Log.e(TAG, "InvalidRemote", e); GittApp.saveErrorTrace(e); throw new NotGitRepoError(); } catch (TransportException e) { String trace = GittApp.saveErrorTrace(e); if (trace.indexOf("not authorized") != -1) { Log.e(TAG, "Auth", e); throw new AuthFailError(); } Log.e(TAG, "Transport", e); throw new ConnectionError(); } catch (GitAPIException e) { Log.e(TAG, "GitApi", e); GittApp.saveErrorTrace(e); } catch (IOException e) { Log.e(TAG, "IO", e); GittApp.saveErrorTrace(e); } catch (JGitInternalException e) { Log.e(TAG, "GitInternal", e); GittApp.saveErrorTrace(e); if (e.getCause() instanceof NotSupportedException) { throw new ConnectionError(); } else { throw new GitError(); } } throw new GitError(); } /** * Folder size in bytes. * * @param localPath * @return */ public static long getRepoSize(String localPath) { return FileUtils.sizeOfDirectory(new File(localPath)); } /** * Current branch/tag name. * * @param path * @return */ public static String currentBranchName(String localPath) { try { Git git = Git.open(new File(localPath)); String name = git.getRepository().getBranch(); if (name.length() == 40) { //detached head processing Map<String, Ref> refs = git.add().getRepository().getAllRefs(); Iterator<Entry<String, Ref>> iter = refs.entrySet().iterator(); while (iter.hasNext()) { Entry<String, Ref> entry = iter.next(); if (entry.getValue().getObjectId().getName().equals(name)) { if (!entry.getKey().equals("HEAD")) { // so bad, will change later... name = entry.getKey(); break; } } } } return nameReFormat(name); } catch (IOException e) { GittApp.saveErrorTrace(e); } return null; } /** * List all branches and tags in a repo. * * @param branches * @param tags * @param path */ public static void readBranchesAndTags(List<String> refs, String localPath) { if (refs == null) return; try { Git git = Git.open(new File(localPath)); Map<String, Ref> mm = git.getRepository().getAllRefs(); for (String name : mm.keySet()) { if (name.equals("HEAD") || name.startsWith("refs/heads/")) continue; refs.add(name); } } catch (Exception e) { GittApp.saveErrorTrace(e); } } /** * Format name by taking last part of a ref. * * @param name * @return */ private static String nameReFormat(String name) { int index = name.lastIndexOf("/"); if (index > -1) { return name.substring(++index); } else { return name; } } /** * Delete local repo. * * @param localPath * @throws IOException */ public static void deleteRepo(String localPath) throws IOException { FileUtils.deleteDirectory(new File(localPath)); } /** * Checkout specific branch or tag. * * @param localPath * @param name * @throws GitError */ public static void checkout(String localPath, String name) throws GitError { try { Git git = Git.open(new File(localPath)); CheckoutCommand co = git.checkout(); co.setName(name); co.call(); } catch (Exception e) { GittApp.saveErrorTrace(e); throw new GitError(); } } /** * Pull repo. * * @param localPath * @param user * @param password * @param pm * @throws GitError */ public static void pull(String localPath, String user, String password, ProgressMonitor pm) throws GitError { try { Git git = Git.open(new File(localPath)); PullCommand pull = git.pull(); pull.setProgressMonitor(pm); if ((user != null) && (password != null)) { UsernamePasswordCredentialsProvider access = new UsernamePasswordCredentialsProvider(user, password); pull.setCredentialsProvider(access); } pull.call(); return; } catch (DetachedHeadException e) { Log.e(TAG, "Detached head", e); GittApp.saveErrorTrace(e); throw new NoHeadError(); } catch (InvalidRemoteException e) { Log.e(TAG, "InvalidRemote", e); GittApp.saveErrorTrace(e); throw new NotGitRepoError(); } catch (TransportException e) { String trace = GittApp.saveErrorTrace(e); if (trace.indexOf("not authorized") != -1) { Log.e(TAG, "Auth", e); throw new AuthFailError(); } Log.e(TAG, "Transport", e); throw new ConnectionError(); } catch (GitAPIException e) { Log.e(TAG, "GitApi", e); GittApp.saveErrorTrace(e); } catch (IOException e) { Log.e(TAG, "IO", e); GittApp.saveErrorTrace(e); } catch (JGitInternalException e) { Log.e(TAG, "GitInternal", e); GittApp.saveErrorTrace(e); if (e.getCause() instanceof NotSupportedException) { throw new ConnectionError(); } } throw new GitError(); } /** * Read log messages, up to maxRecords * * @param repoPath * @param maxRecords * @return */ public static List<LogEntry> readRepoHistory(String repoPath, int maxRecords) { ArrayList<LogEntry> result = new ArrayList<GitHelper.LogEntry>(maxRecords); try { Git git = Git.open(new File(repoPath)); Iterable<RevCommit> logs = git.log().call(); for (RevCommit commit : logs) { result.add(new LogEntry(commit)); if (--maxRecords == 0) break; } } catch (IOException e) { Log.e(TAG, "IO", e); } catch (NoHeadException e) { Log.e(TAG, "NoHead", e); } catch (GitAPIException e) { Log.e(TAG, "GitApi", e); } if (maxRecords > 0) { result.trimToSize(); } return result; } /** * Log entry. * * To be updated for more features. * * @author Andrew Romanenco * */ public static class LogEntry { private RevCommit commit; private LogEntry(RevCommit commit) { this.commit = commit; } private static DateFormat format = new SimpleDateFormat("MMM dd, yyyy"); public String getText() { StringBuilder sb = new StringBuilder(); sb.append(commit.getAuthorIdent() != null ? commit.getAuthorIdent().getName() : ""); sb.append("\n"); Date date = new Date((long) commit.getCommitTime() * 1000); sb.append(format.format(date)); sb.append("\n"); sb.append(commit.getId().getName()); sb.append("\n"); sb.append("\n"); sb.append(commit.getFullMessage()); return sb.toString(); } } }