Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clone a git repository into an InMemoryRepository with JGit

Tags:

git

jgit

I need to clone an existing git repository into an InMemoryRepository, using JGit, change a file's content and push the changes back to the remote repository.

I couldn't find any examples of cloning a repository into an in-memory repository.

I tried this:

InMemoryRepository.Builder builder = new InMemoryRepository.Builder();  
InMemoryRepository inm = builder.build(); 
Git.cloneRepository().setURI("git@[github_url].git").setDirectory(inm.getDirectory()).call();  

Which resulted in an error:

'Destination path ".git" already exists and is not an empty directory'.

I checked the configuration options for InMemoryRepository.Builder and Repository classes, but haven't found anything useful.

How can it be done? And after that, is there any problem with changing a file's content and pushing it to github, all from the in-memory repository?

like image 962
arikabc Avatar asked Jul 07 '15 14:07

arikabc


People also ask

How do I clone a repository with Tortoise?

Download and install the TortoiseGit client. Configure an HTTPS password. On the CodeHub homepage, click the name of a repository in the repository list. On the repository details page displayed, click Clone/Download, click Clone with HTTPS, and copy the repository address.


2 Answers

There is a proper solution without any files on disk, even temporary:

    // sample usage
    private void loadFromGit() throws Exception {
        ObjectLoader loader = loadRemote("https://github.com/msangel/promisified-resource-loader", "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);
        Git git = new Git(repo);
        git.fetch()
                .setRemote(uri)
                .setRefSpecs(new RefSpec("+refs/heads/*:refs/heads/*"))
                .call();
        repo.getObjectDatabase();
        ObjectId lastCommitId = repo.resolve("refs/heads/"+ branch);
        RevWalk revWalk = new RevWalk(repo);
        RevCommit commit = revWalk.parseCommit(lastCommitId);
        RevTree tree = commit.getTree();
        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;
    }

So, actually you have TreeWalk here (which is default to recursive), but you can change this and manually iterate all from repo.

like image 61
msangel Avatar answered Oct 11 '22 01:10

msangel


The CloneCommand will always create a file-based repository. The lines from your post that create an InMemoryRepository have no effect on the clone command.

I suggest to clone into a temporary location if you only need the repository to make a change and push the result.

For example:

Git.cloneRepository().setURI( ... ).setDirectory( new File("/path/to/empty/dir" ) ).call();  

An InMemoryRepository in JGit still requires a work directory for operations like checkout, etc. Only the object database which is usually found in the .git directory is stored in memory

like image 26
Rüdiger Herrmann Avatar answered Oct 11 '22 01:10

Rüdiger Herrmann