Skip to content

Instantly share code, notes, and snippets.

@pvlasov
Last active September 16, 2019 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pvlasov/48dc0178feca6e74fa1d99d489f4400c to your computer and use it in GitHub Desktop.
Save pvlasov/48dc0178feca6e74fa1d99d489f4400c to your computer and use it in GitHub Desktop.
Working with jGit

Maven dependency

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

Resources

Cloning

System.out.println(System.getenv().get("GIT_USER"));
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI(REMOTE);
cloneCommand.setCredentialsProvider(CREDENTIALS_PROVIDER);
//		cloneCommand.setGitDir(REPO_DIRECTORY);
cloneCommand.setDirectory(REPO_DIRECTORY);
cloneCommand.setProgressMonitor(new TextProgressMonitor());
cloneCommand.call();

Note - for auth tokens put them to user name, leave password blank.

Add, commit, push

FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();
Repository repo = repositoryBuilder
//				.setWorkTree(REPO_DIRECTORY)
		.setGitDir(GIT_DIR)
//		        .readEnvironment() // scan environment GIT_* variables
        .findGitDir() // scan up the file system tree
        .setMustExist(true)
        .build();
		
File testsDir = new File(REPO_DIRECTORY, "jgit-tests");
testsDir.mkdirs();
File newFile = new File(testsDir, "jgit-test-"+System.currentTimeMillis()+".txt");
try (Writer wr = new FileWriter(newFile)) {
	wr.write("Hello "+new Date());
}
try (Git git = new Git(repo)) {
	git.add().addFilepattern("jgit-tests/").call();
	git.commit()
		.setMessage("Added a test file")
		.setAuthor("AWS DX Gateway", "Pavel.Vlasov@citi.com")
		.call();
	git.push().setCredentialsProvider(CREDENTIALS_PROVIDER).call();
}

Using in-memory repository

public void testInMemoryLoadFromGit() throws Exception {
      ObjectLoader loader = loadRemote(REMOTE, "master", "readme.md");
      loader.copyTo(System.out);
}

private ObjectLoader loadRemote(String uri, String branch, String filename) throws Exception {
    DfsRepositoryDescription repoDesc = new DfsRepositoryDescription();
    InMemoryRepository repo = new InMemoryRepository(repoDesc);
     try (Git git = new Git(repo)) {
     git.fetch()
             .setRemote(uri)
             .setRefSpecs(new RefSpec("+refs/heads/*:refs/heads/*"))
             .setCredentialsProvider(CREDENTIALS_PROVIDER)
             .setProgressMonitor(new TextProgressMonitor())
             .call();
     //repo.getObjectDatabase();
     ObjectId lastCommitId = repo.resolve("refs/heads/"+ branch);
     try (RevWalk revWalk = new RevWalk(repo)) {
      RevCommit commit = revWalk.parseCommit(lastCommitId);
      RevTree tree = commit.getTree();
      try (TreeWalk treeWalk = new TreeWalk(repo)) {
       treeWalk.addTree(tree);
       treeWalk.setRecursive(true);
       treeWalk.setFilter(PathFilter.create(filename));
       if (!treeWalk.next()) {
           return null;
       }
       ObjectId objectId = treeWalk.getObjectId(0);
       ObjectLoader loader = repo.open(objectId);
       return loader;
      }
     }
    }
}

Clone-modify-add-commit-push helper

public static final String GIT_TEMP_DIR_PREFIX = "git-helper-";

protected String getTempDirPrefix() {
	return GIT_TEMP_DIR_PREFIX; 
}
	
protected File createWorkingDirectory() throws Exception {
	return Files.createTempDirectory(GIT_TEMP_DIR_PREFIX).toFile();		
}

/**
 * Performs clone, calls execute(), then if execute() returns non-null adds changes, commits and pushes. Returns report.
 * @param remote
 * @param commitMessage
 * @return Report.
 * @throws Exception
 */
public String call(
		String remote, 
		CredentialsProvider credentialsProvider, 
		String commitMessage,
		PersonIdent author
		) throws Exception {		
	File repoDir = createWorkingDirectory();
	File gitDir = new File(repoDir, ".git");
	StringWriter writer = new StringWriter();
	TextProgressMonitor progressMonitor = new TextProgressMonitor(writer);
	try {
		// Cloning - reuse existing in the future?
		progressMonitor.beginTask("Cloning repository "+remote+" to "+repoDir.getAbsolutePath(), 1);
		CloneCommand cloneCommand = Git.cloneRepository();
		cloneCommand.setURI(remote);
		cloneCommand.setCredentialsProvider(credentialsProvider);
		cloneCommand.setDirectory(repoDir);
		cloneCommand.setProgressMonitor(progressMonitor);
		cloneCommand.call();
		progressMonitor.endTask();

		String filePattern = execute(repoDir, progressMonitor);
		if (filePattern == null) {
			progressMonitor.beginTask("No changes", 1);
			progressMonitor.endTask();
		} else {
			progressMonitor.beginTask("Adding payload to the repository, committing and pushing to remote", 1);
			FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();
			Repository repo = repositoryBuilder
					.setGitDir(gitDir)
//			        .findGitDir() // scan up the file system tree
			        .setMustExist(true)
			        .build();
			
			try (Git git = new Git(repo)) {
				git.add().addFilepattern(filePattern).call();
				git.commit()
					.setMessage(commitMessage)
					.setAuthor(author)
					.call();
				git.push().setCredentialsProvider(credentialsProvider).call();
			}
			progressMonitor.endTask();
		}
		writer.close();
		return writer.toString();
	} finally {
		delete(repoDir);
	}		
}

/**
 * Performs file manipulation, returns add pattern.
 * @param workingDir Working directory.
 * @param progressMonitor Progress monitor
 * @return Add pattern or null if no modifications shall be added to the repository.
 * @throws Exception
 */
protected abstract String execute(File repoDir, ProgressMonitor progressMonitor) throws Exception; 
	
public static void delete(File file) throws IOException {
	if (file.exists()) {
		if (file.isDirectory()) {
			for (File child: file.listFiles()) {
				delete(child);
			}
		}
		Files.delete(file.toPath());
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment