Problem Statement:Manage versioning of bunch of .sql files which will be part of git project structure spread across different developers workspaces.
Pre-commit git hook basically runs before files are commited.In this hook I am launching a 'gradle run' task which will trigger java process,which in turn looks in to git modified,added or changed .sql files in git repo and renamed them accordingly.
I am able to accomplish it through direct run of gradle run task.But when I trigger gradle run through precommit hook I get this cryptic error.
same piece of code executes without any issue when I directly launch gradle run task or through Eclipse java programme.precommit hook as below.
echo "Running gradle command"
echo `pwd`
gradle run
this triggers when I type
git commit -m "somemessages"
gradle file:
apply plugin: 'java-library'
apply plugin: 'application'
mainClassName = "com.git.status.GitStatusFileAndRename"
repositories {
jcenter()
}
dependencies {
compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
compile group: 'org.flywaydb', name: 'flyway-core', version: '4.2.0'
compile group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '4.10.0.201712302008-r'
implementation 'com.google.guava:guava:21.0'
testImplementation 'junit:junit:4.12'
}
task installGitHooks(type: Copy) {
from new File(rootProject.rootDir, 'pre-commit')
into { new File(rootProject.rootDir, '.git/hooks') }
}
finally Git Programme:there is popular java library for doing git operations and I must say it is pretty cool to have git commands runs through java api without having to do Process API.
/** * */
package com.git.status;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoFilepatternException;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
public class GitStatusFileAndRename {
private static int versionStarter = 8000;
public static void main(String[] args) throws IOException, NoWorkTreeException, GitAPIException {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.readEnvironment() .findGitDir() .build();
System.out.println("Printing repo is" + repository.getDirectory().getAbsolutePath());
//Git git = Git.init().setDirectory(repository.getDirectory().getAbsoluteFile()).call()
try (Git git = new Git(repository)) {
Status status = git.status().call();
List<String> files = createListOfSqlFilesModifiedAddedOrChanged(status);
String regex = "^V[0-9]{1,4}__(.)*";
for (String path : files) {
String[] pathtokesn = path.split(File.separator);
if (Pattern.matches(regex, pathtokesn[pathtokesn.length - 1])) {
} else {
File file = new File(path);
String renamedPath = renameSqlFiles(path);
file.renameTo(new File(renamedPath));
System.out.println("Renamed file is" + "{}" + renamedPath);
addRenamedFileToIndex(renamedPath, git);
removeOldFileFromIndex(path, git);
System.out.println("printing path of files" + file.getAbsolutePath());
}
}
}
}
private static void addRenamedFileToIndex(String path, Git git) throws NoFilepatternException, GitAPIException {
System.out.println("Adding renamed file to index" + path);
git.add().addFilepattern(path).call();
}
private static void removeOldFileFromIndex(String filePath, Git git)
throws CheckoutConflictException, GitAPIException {
System.out.println("Removing file" + "{}" + filePath + "{}" + "from index");
ResetCommand reset = git.reset();
reset.setRef(Constants.HEAD);
reset.addPath(filePath);
reset.call();
}
private static List<String> createListOfSqlFilesModifiedAddedOrChanged(Status status) {
List<String> files = new ArrayList<String>();
files.addAll(status.getAdded().stream().filter(name -> name.endsWith(".sql")).collect(Collectors.toList()));
files.addAll(status.getChanged().stream().filter(name -> name.endsWith(".sql")).collect(Collectors.toList()));
files.addAll(status.getModified().stream().filter(name -> name.endsWith(".sql")).collect(Collectors.toList()));
return files;
}
private static String renameSqlFiles(String path) {
int lastIndex = path.lastIndexOf(File.separator);
String fileName = path.substring(lastIndex + 1, path.length());
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(path.substring(0, lastIndex + 1)).append("V").append(++versionStarter).append("__")
.append(fileName);
return pathBuilder.toString();
}
}
Question:What could be the reason for this behaviour.precommit hook is just launching gradle run task and nothing else.Same gradle task when run through command line runs fine and I don't get any kind of error. Below Error I get when I launch it through git pre commit hook
Exception in thread "main" org.eclipse.jgit.errors.NoWorkTreeException: Bare Repository has neither a working tree, nor an index
at org.eclipse.jgit.lib.Repository.getWorkTree(Repository.java:1573)
at org.eclipse.jgit.treewalk.FileTreeIterator.<init>(FileTreeIterator.java:115)
at org.eclipse.jgit.treewalk.FileTreeIterator.<init>(FileTreeIterator.java:98)
at org.eclipse.jgit.api.StatusCommand.call(StatusCommand.java:146)
at com.git.status.GitStatusFileAndRename.main(GitStatusFileAndRename.java:39)
.
Repository repository= builder
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
System.out.println("Printing repo is"+repository.getDirectory().getAbsolutePath());
Above code prints same path when launched through either gradle run or through pre-commit hook
Initialising Git through this API has seemed to solve the problem.
//Git git = Git.init().setDirectory(repository.getDirectory().getAbsoluteFile()).call()
StandAlone Mode:I am creating a new file and adding the newly created index.Infact there is no git pre-commit hook involved.Just right click and run the code.Git add still shows newly created files under untracked path.
package com.git.status;
import java.io.File;
import java.io.IOException;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.StatusCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
public class SelfContainedExample {
public static void main(String[] args)
throws IllegalStateException, GitAPIException, IOException, InterruptedException {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.readEnvironment().findGitDir().build();
try (Git git = Git.init().setDirectory(repository.getDirectory().getAbsoluteFile()).call()) {
File myfile = new File(repository.getDirectory().getParent(), "isgitaddworkingsure");
if (!myfile.createNewFile()) {
throw new IOException("Could not create file " + myfile);
}
System.out.println("printing absolute path" + "{}" + myfile.getAbsolutePath());
git.add().addFilepattern(myfile.getAbsolutePath()).call();
System.out.println("Added file " + myfile + " to repository at " + repository.getDirectory());
StatusCommand status = git.status();
// Thread.sleep(2000);
System.out.println("Printing added file" + status.call().getAdded());
System.out.println("Printing untracked file" + " " + status.call().getUntracked());
System.out.println("Printing uncommited" + " " + status.call().getUncommittedChanges());
System.out.println("reinitaling new git instance");
Git gitnew = Git.init().setDirectory(repository.getDirectory().getAbsoluteFile()).call();
gitnew.add().addFilepattern(myfile.getAbsolutePath()).call();
StatusCommand newstatus = git.status();
Thread.sleep(2000);
System.out.println("after reinitializing Printing added file" + newstatus.call().getAdded());
System.out.println("after reinitializing Printing untracked file" + " " + newstatus.call().getUntracked());
System.out.println(
"after reinitializing Printing uncommited" + " " + newstatus.call().getUncommittedChanges());
}
}
}
outPut:
printing absolute path{}/home/bmarwaha/workspace/eclipse/unipaynext/DbManagement/isgitaddworkingsure
Added file /home/bmarwaha/workspace/eclipse/unipaynext/DbManagement/isgitaddworkingsure to repository at /home/bmarwaha/workspace/eclipse/unipaynext/DbManagement/.git
Printing added file[]
Printing untracked file []
Printing uncommited []
reinitaling new git instance
after reinitializing Printing added file[]
after reinitializing Printing untracked file []
after reinitializing Printing uncommited []
git version:git version 2.7.4