1

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

MrWayne
  • 309
  • 1
  • 9
  • 20
  • Please show the complete/relevant parts of the stacktrace. And please minimize the code snippet, i.e. remove dead code, useless comments, format properly, etc. – Rüdiger Herrmann Feb 09 '18 at 11:24
  • Error is gone but functionality is not working.Calling Git.init().setDirectory(repository.getDirectory().getAbsoluteFile()).call() some how does not detect files which I added in commit – MrWayne Feb 09 '18 at 13:31
  • Git::init. creates a new repository, that‘s probably not what you want. – Rüdiger Herrmann Feb 09 '18 at 20:14
  • It is not an issue.it seems to be working fine .Problem is renamed .sql files are getting as part of Untracked files in git.My Expectation was that if I rename a given.sql file in code and then add it to git repo,it should be considered as added before git is commited with rest of files.But after running git commit, I am getting file renamed but some how not getting added to git .git.add().addFilepattern(path).call() does not seems to add the renamed file to git index – MrWayne Feb 13 '18 at 07:15
  • According to this post (https://stackoverflow.com/questions/16831536/can-you-change-a-file-content-during-git-commit), adding and removing to/from the index should work in a pre-commit hook. If you have trouble, please post a self-contained example to reproduce your problem. – Rüdiger Herrmann Feb 13 '18 at 08:36
  • I have edited the question and added more details – MrWayne Feb 13 '18 at 10:35
  • Git add does not work through jgit.May be I am missing something very basic thing.For now I am launching git add through java run time and it is working – MrWayne Feb 14 '18 at 04:09
  • 1
    The argument given to `addFIlePattern` is wrong. The line `git.add().addFilePattern()` should specify a path relative to the root of the repository. In your case, simply `"isgitaddworkingsure"`. Besides that, use `repository.getWorkTree()` to obtain the root of the Git work directory. – Rüdiger Herrmann Feb 14 '18 at 09:01

0 Answers0