Example usage for org.eclipse.jgit.api Git Git

List of usage examples for org.eclipse.jgit.api Git Git

Introduction

In this page you can find the example usage for org.eclipse.jgit.api Git Git.

Prototype

public Git(Repository repo) 

Source Link

Document

Construct a new org.eclipse.jgit.api.Git object which can interact with the specified git repository.

Usage

From source file:net.polydawn.mdm.commands.MdmAddCommand.java

License:Open Source License

void doGitCommit(File path) throws MdmRepositoryStateException {
    String currentAction = "commit a link to the new dependency repo into the project repo";
    try {/*w  ww . j  ava 2  s.  c o m*/
        new Git(repo).commit().setOnly(path.getPath()).setOnly(Constants.DOT_GIT_MODULES)
                .setMessage("adding dependency on " + name + " at " + version + ".").call();
    } catch (NoHeadException e) {
        throw new MdmRepositoryStateException(currentAction, repo.getWorkTree().toString(), e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (UnmergedPathsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
}

From source file:net.polydawn.mdm.commands.MdmAlterCommand.java

License:Open Source License

public MdmExitMessage call() throws ConfigInvalidException, IOException, MdmException {
    try {/*from ww  w .jav  a  2 s  .  co m*/
        assertInRepoRoot();
    } catch (MdmExitMessage e) {
        return e;
    }

    // touch up args a tad.  tab completion in the terminal tends to suggest *almost* what you want, but with a trailing slash because it's a directory, and git doesn't like that slash.  so, we'll sand down that sharp corner a bit.
    String name = args.getString("name");
    if (name.endsWith("/"))
        name = name.substring(0, name.length() - 1);

    // load current module state
    StoredConfig gitmodulesCfg = new FileBasedConfig(new File(repo.getWorkTree(), Constants.DOT_GIT_MODULES),
            repo.getFS());
    try {
        gitmodulesCfg.load();
    } catch (ConfigInvalidException e) {
        throw new MdmExitInvalidConfig(Constants.DOT_GIT_MODULES);
    }
    MdmModuleDependency module;
    try {
        module = MdmModuleDependency.load(repo, name, gitmodulesCfg);
    } catch (MdmModuleTypeException e) {
        return new MdmExitMessage(":(", "there is no mdm dependency by that name.");
    }

    // give a look at the remote path and see what versions are physically available.
    List<String> versions;
    try {
        //XXX: here the triplicate-and-then-some configuration is a tanglefuck again.  do we use the origin, or the url in the submodule config, or the url that's initialized in the parent .git/config, or the url in the .gitmodules file, or some complicated fallback pattern that covers all of them, or initialize the ones that aren't yet, or...??  Original mdm took the value from .gitmodules, which is the least likely to be uninitialized, but also not the most correct.
        if (module.getRepo() == null)
            versions = Plumbing.getVersionManifest(repo, module.getUrlHistoric());
        else
            versions = Plumbing.getVersionManifest(module.getRepo(), "origin");
    } catch (InvalidRemoteException e) {
        return new MdmExitMessage(":(",
                "the submodule remote origin url isn't initialized.  maybe run `mdm update` first so there's something in place before we alter?");
    } catch (TransportException e) {
        return new MdmExitMessage(":'(",
                "transport failed!  check that the submodule remote origin url is correct and reachable and try again?\n  (error message: "
                        + e.getMessage() + ")");
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    if (versions.size() == 0)
        return new MdmExitMessage(":(",
                "no releases could be found at the submodule remote origin url -- it doesn't look like releases that mdm understands are there.\ncheck the origin url in the submodule's config.  if this url worked in the past, maybe the project maintainers moved their releases repo?");

    // if a specific version name was given, we'll just go straight at it; otherwise we present options interactively from the manifest of versions the remote reported.
    String version;
    if (args.getString("version") != null) {
        version = args.getString("version");
        if (!versions.contains(version))
            return new MdmExitMessage(":(",
                    "no version labelled " + version + " available from the provided remote url.");
    } else {
        version = Loco.promptForVersion(os, versions);
    }

    // if you specify the version you already had, okay, we'll just put our tools down.
    if (module.getVersionName().equals(version))
        return new MdmExitMessage(":I", "that version is already specified!  no changes made.");

    // do the submodule/dependency dancing
    gitmodulesCfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, module.getHandle(),
            MdmConfigConstants.Module.DEPENDENCY_VERSION.toString(), version);
    module = MdmModuleDependency.load(repo, module.getPath(), gitmodulesCfg); // reload the MdmModule completely because it's not yet implmented intelligently enough to be able to refresh a bunch of its cached state
    Plumbing.fetch(repo, module);
    gitmodulesCfg.save(); // don't do this save until after the fetch: if the fetch blows up, it's better that we don't have this mutated, because that leaves you with slightly stranger output from your next `mdm status` query.

    // commit the changes
    try {
        new Git(repo).add().addFilepattern(module.getPath()).addFilepattern(Constants.DOT_GIT_MODULES).call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    try {
        new Git(repo).commit().setOnly(module.getPath()).setOnly(Constants.DOT_GIT_MODULES)
                .setMessage("shifting dependency on " + name + " to version " + version + ".").call();
    } catch (NoHeadException e) {
        throw new MdmException("your repository is in an invalid state!", e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (UnmergedPathsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }

    return new MdmExitMessage(":D",
            "altered dependency on " + name + " to version " + version + " successfully!");
}

From source file:net.polydawn.mdm.commands.MdmReleaseCommand.java

License:Open Source License

public MdmExitMessage call() throws IOException, MdmException, MdmExitMessage {
    MdmModuleRelease relModule = loadReleaseModule();
    Repository relRepo = relModule.getRepo();

    relModule.assertPresentsAsReleaseRepo();
    assertReleaseRepoDoesntAlreadyContain(relModule, version);
    assertReleaseRepoClean(relModule);//from  www. j a v  a2s  .c  o m

    List<String> inputFiles = selectInputFiles();

    // create a branch for the release commit.  depending on whether or not infix mode is enabled, this is either branching from the infix branch, or it's founding a new root of history.
    boolean infixMode = relRepo.getRef("refs/heads/mdm/infix") != null;
    if (infixMode)
        try {
            new Git(relRepo).checkout().setCreateBranch(true).setStartPoint("mdm/infix")
                    .setName("mdm/release/" + version).call();
        } catch (RefAlreadyExistsException e) {
            return new MdmExitMessage(":'(",
                    "the releases repo already has a release point labeled version " + version + " !");
        } catch (RefNotFoundException e) {
            throw new MdmException("aborted due to concurrent modification of repo");
        } catch (InvalidRefNameException e) {
            return new MdmExitMessage(":(", "you can't use version names that git rejects as branch names.");
        } catch (CheckoutConflictException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        } catch (GitAPIException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        }
    else {
        Plumbing.createOrphanBranch(relRepo, "mdm/release/" + version);
        try {
            new Git(relRepo).checkout().setName("mdm/release/" + version).call();
        } catch (GitAPIException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        }
    }

    // enumerate and copy in artifact files.
    File inputBase = new File(inputPath).getCanonicalFile();
    if (inputBase.isFile())
        inputBase = inputBase.getParentFile();
    File relRepoFile = new File(relRepoPath).getCanonicalFile();
    for (String input : inputFiles) {
        File inputFull = new File(inputBase, input);
        File dest = new File(relRepoFile, input);
        if (inputFull.isDirectory())
            FileUtils.copyDirectory(inputFull, dest, new FileFilter() {
                public boolean accept(File file) {
                    return !(file.isDirectory() && file.listFiles().length == 0);
                }
            }, true, false);
        else
            FileUtils.copyFile(inputFull, dest, true, false);
    }

    // commit the changes
    try {
        new Git(relRepo).add().addFilepattern(".").call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    try {
        CommitCommand commit = new Git(relRepo).commit().setMessage("release version " + version);
        if (!infixMode) {
            commit.setAmend(true); // because our mechanism for creating an orphan branch starts us with an empty commit.
            PersonIdent convergenceIdent = new PersonIdent("mdm", "", new Date(0), TimeZone.getTimeZone("GMT"));
            commit.setAuthor(convergenceIdent);
            commit.setCommitter(convergenceIdent);
        }
        commit.call();

        // this tag will be removed in a future release, as it's no longer required for any structural purpose
        // (long long ago in a galaxy far away, this was used as an easy way for `mdm status` to report version names... but execing `git describe --tags` hasn't been the way we do this anymore for a long time now)
        new Git(relRepo).tag().setName("release/" + version).setAnnotated(false).call();
    } catch (NoHeadException e) {
        throw new MdmException("your repository is in an invalid state!", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MdmException("aborted due to concurrent modification of repo");
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (UnmergedPathsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }

    // generate an accumulation commit.  do this from the master branch, but don't submit it yet, because when we roll in the artifacts we want them in a subdirectory so that when master is checked out all the versions are splayed out in the working tree at once.
    try {
        new Git(relRepo).checkout().setName("master").call();
    } catch (RefAlreadyExistsException e) {
        throw new MajorBug(e); // not even valid unless we're creating a new branch, which we aren't.
    } catch (RefNotFoundException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (InvalidRefNameException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (CheckoutConflictException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    try {
        new Git(relRepo).merge().include(relRepo.getRef("mdm/release/" + version))
                .setFastForward(FastForwardMode.NO_FF).setCommit(false).call();
    } catch (NoHeadException e) {
        throw new MdmException("your repository is in an invalid state!", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MdmException("aborted due to concurrent modification of repo");
    } catch (CheckoutConflictException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (InvalidMergeHeadsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?  also, we're not even making a commit here.
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }

    // move the artifact files into a version-named directory
    File artifactDestFile = new File(relRepoFile, version);
    if (!artifactDestFile.mkdir())
        return new MdmExitMessage(":'(", "couldn't make the directory named \"" + version
                + "\" to put the releases into because there was already something there.");

    for (String input : inputFiles)
        new File(relRepoFile, input).renameTo(new File(artifactDestFile, input));

    // now fire off the accumulation commit, and that commit now becomes head of the master branch.
    try {
        RmCommand rmc = new Git(relRepo).rm();
        for (String input : inputFiles)
            rmc.addFilepattern(input);
        rmc.call();
        new Git(relRepo).add().addFilepattern(version).call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    try {
        new Git(relRepo).commit().setMessage("merge release version " + version + " to master").call();
        new Git(relRepo).tag().setName("mdm/master/" + version).setAnnotated(false).call();
    } catch (NoHeadException e) {
        throw new MdmException("your repository is in an invalid state!", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MdmException("aborted due to concurrent modification of repo");
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (UnmergedPathsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }

    // commit the new hash of the releases-repo into the project main repo (if we are operating in a canonically placed releases submodule)
    if (isInRepoRoot() && relRepoPath.equals("releases") && Plumbing.isCommitedGitlink(repo, "releases")) {
        try {
            new Git(repo).commit().setOnly("releases").setMessage("release version " + version).call();
            new Git(repo).tag().setName("release/" + version).setAnnotated(false).call();
        } catch (NoHeadException e) {
            throw new MdmException("your repository is in an invalid state!", e);
        } catch (ConcurrentRefUpdateException e) {
            throw new MdmException("aborted due to concurrent modification of repo");
        } catch (NoMessageException e) {
            throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
        } catch (UnmergedPathsException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        } catch (WrongRepositoryStateException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        } catch (GitAPIException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        }
    }

    return new MdmExitMessage(":D", "release version " + version + " complete");
}

From source file:net.polydawn.mdm.commands.MdmReleaseInitCommand.java

License:Open Source License

/**
 * Create a text file stating the repository name and commit it. This creates a
 * root commit for history so that we can actually wield the repo.
 *
 * @param releaserepo/*ww  w  . jav a 2 s  .  c o m*/
 */
void makeReleaseRepoFoundingCommit(Repository releaserepo) {
    // write readme file
    try {
        IOForge.saveFile("This is the releases repo for " + name + ".\n",
                new File(path, "README").getCanonicalFile());
    } catch (IOException e) {
        throw new MdmRepositoryIOException("create a release repo", true, path, e);
    }

    // add and commit
    String currentAction = "commit into the new releases repo";
    try {
        new Git(releaserepo).add().addFilepattern("README").call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MdmUnrecognizedError(e);
    }
    try {
        new Git(releaserepo).commit().setOnly("README").setMessage("initialize releases repo for " + name + ".")
                .call();
    } catch (NoHeadException e) {
        throw new MdmConcurrentException(
                new MdmRepositoryStateException(currentAction, releaserepo.getWorkTree().toString(), e));
    } catch (WrongRepositoryStateException e) {
        throw new MdmConcurrentException(
                new MdmRepositoryStateException(currentAction, releaserepo.getWorkTree().toString(), e));
    } catch (UnmergedPathsException e) {
        throw new MdmConcurrentException(
                new MdmRepositoryStateException(currentAction, releaserepo.getWorkTree().toString(), e));
    } catch (ConcurrentRefUpdateException e) {
        throw new MdmConcurrentException(e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MdmUnrecognizedError(e);
    }
}

From source file:net.polydawn.mdm.commands.MdmReleaseInitCommand.java

License:Open Source License

/**
 * Label the current commit (which in context is the root commit) with the
 * 'mdm/init' branch./*from ww  w .  ja v a  2 s .  c  o m*/
 *
 * This branch has two roles; firstly, it is the metadata that is considered the
 * official declaration of this repo as a valid mdm releases repo; secondly, when
 * mdm is fetching a dependency, this essentially empty branch is used as a safe
 * default for the remote.origin.fetch configuration of the submodule.
 *
 * @param releaserepo
 */
void makeReleaseRepoInitBranch(Repository releaserepo) {
    String currentAction = "create branches in the new releases repo";
    try {
        new Git(releaserepo).branchCreate().setName("mdm/init").call();
    } catch (RefAlreadyExistsException e) {
        throw new MdmConcurrentException(
                new MdmRepositoryStateException(currentAction, releaserepo.getWorkTree().toString(), e));
    } catch (RefNotFoundException e) {
        throw new MdmConcurrentException(
                new MdmRepositoryStateException(currentAction, releaserepo.getWorkTree().toString(), e));
    } catch (InvalidRefNameException e) {
        throw new MajorBug(e); // branch name is fixed at compile time here and is quite valid, thanks
    } catch (GitAPIException e) {
        throw new MdmUnrecognizedError(e);
    }
}

From source file:net.polydawn.mdm.commands.MdmReleaseInitCommand.java

License:Open Source License

/**
 * Commits the release repo path and the gitmodules file.
 *
 * @param repo/*from ww w. ja  va 2  s  . c o m*/
 * @throws MdmRepositoryStateException
 * @throws NoWorkTreeException
 */
void makeParentRepoLinkCommit(Repository repo) throws MdmRepositoryStateException {
    String currentAction = "commit a link to the new releases repo into the parent repo";
    try {
        new Git(repo).add().addFilepattern(path).addFilepattern(Constants.DOT_GIT_MODULES).call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MdmUnrecognizedError(e);
    }
    try {
        new Git(repo).commit().setOnly(path).setOnly(Constants.DOT_GIT_MODULES)
                .setMessage("initialize releases repo for " + name + ".").call();
    } catch (NoHeadException e) {
        throw new MdmRepositoryStateException(currentAction, repo.getWorkTree().toString(), e);
    } catch (UnmergedPathsException e) {
        throw new MdmRepositoryStateException(currentAction, repo.getWorkTree().toString(), e);
    } catch (WrongRepositoryStateException e) {
        throw new MdmRepositoryStateException(currentAction, repo.getWorkTree().toString(), e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MdmConcurrentException(e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MdmUnrecognizedError(e);
    }
}

From source file:net.polydawn.mdm.commands.MdmRemoveCommand.java

License:Open Source License

public MdmExitMessage call() throws IOException, MdmException {
    try {//from   www. j  av a 2 s  .co m
        assertInRepoRoot();
    } catch (MdmExitMessage e) {
        return e;
    }

    // touch up args a tad.  tab completion in the terminal tends to suggest *almost* what you want, but with a trailing slash because it's a directory, and git doesn't like that slash.  so, we'll sand down that sharp corner a bit.
    String name = args.getString("name");
    if (name.endsWith("/"))
        name = name.substring(0, name.length() - 1);

    // load up config
    StoredConfig gitmodulesCfg = new FileBasedConfig(new File(repo.getWorkTree(), Constants.DOT_GIT_MODULES),
            repo.getFS());
    try {
        gitmodulesCfg.load();
    } catch (ConfigInvalidException e) {
        throw new MdmExitInvalidConfig(Constants.DOT_GIT_MODULES);
    }

    // if there's no module there, we haven't got much to do
    try {
        MdmModuleDependency.load(repo, name, gitmodulesCfg);
    } catch (MdmModuleTypeException _) {
        return new MdmExitMessage(":I", "there is no mdm dependency by that name.");
    }

    // stage the remove and blow away the repo dirs
    try {
        new Git(repo).rm().setCached(true).addFilepattern(name).call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    IOForge.delete(new File(repo.getWorkTree(), name));
    IOForge.delete(new File(repo.getDirectory(), "modules/" + name)); // if this is one of the newer version of git (specifically, 1.7.8 or newer) that stores the submodule's data in the parent projects .git dir, clear that out forcefully as well.

    // blow away gitmodule config section
    gitmodulesCfg.unsetSection(ConfigConstants.CONFIG_SUBMODULE_SECTION, name);
    gitmodulesCfg.save();

    // commit the changes
    try {
        new Git(repo).add().addFilepattern(name).addFilepattern(Constants.DOT_GIT_MODULES).call();
    } catch (NoFilepatternException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }
    try {
        new Git(repo).commit().setOnly(name).setOnly(Constants.DOT_GIT_MODULES)
                .setMessage("removing dependency on " + name + ".").call();
    } catch (NoHeadException e) {
        throw new MdmException("your repository is in an invalid state!", e);
    } catch (NoMessageException e) {
        throw new MajorBug(e); // why would an api throw exceptions like this *checked*?
    } catch (UnmergedPathsException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (ConcurrentRefUpdateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (WrongRepositoryStateException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    } catch (GitAPIException e) {
        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
    }

    // clear out local git config
    StoredConfig localConfig = repo.getConfig();
    localConfig.unsetSection(ConfigConstants.CONFIG_SUBMODULE_SECTION, name);
    localConfig.save();

    return new MdmExitMessage(":D", "removed dependency on " + name + "!");
}

From source file:net.polydawn.mdm.MdmModule.java

License:Open Source License

/**
 * @param repo/*from   ww  w .  j a  va  2 s .c  o  m*/
 *                required.
 *
 *                well, unless you're about to create one, in which case not even.
 * @param handle
 *                required.
 * @param parent
 *                null if repository stands alone, otherwise if we are a submodule
 *                required.
 * @param gitmodulesCfg
 *                ignored if parent null, otherwise required.
 * @param indexId
 *                ignored if parent null, otherwise will be automatically loaded
 *                if not provided.
 *
 *                the commit hash known to the parent repo index for this
 *                submodule (or null if it's not handy; we'll load it in that
 *                case).
 *
 * @throws MdmModuleTypeException
 *                 if the {@code gitmodulesCfg} entries for {@code handle} don't
 *                 concur with the {@code type} expected.
 * @throws MdmRepositoryIOException
 *                 if disks reject our advances
 */
protected MdmModule(Repository repo, String handle, Repository parent, Config gitmodulesCfg, ObjectId indexId)
        throws MdmRepositoryIOException, MdmModuleTypeException {
    handle = (File.separatorChar != '/') ? handle.replace(File.separatorChar, '/') : handle;
    this.handle = handle;
    this.repo = repo;

    if (repo == null) {
        this.headId = null;
        this.dirtyFiles = false;
    } else {
        try {
            this.headId = repo.resolve(Constants.HEAD);
        } catch (IOException e) {
            throw new MdmRepositoryIOException(false, handle, e);
        }

        boolean dirtyFiles;
        try {
            dirtyFiles = !new Git(repo).status().call().isClean();
        } catch (NoWorkTreeException e) {
            throw new RuntimeException("wat", e);
        } catch (GitAPIException e) {
            dirtyFiles = false;
        }
        this.dirtyFiles = dirtyFiles;
    }

    if (parent != null) {
        // sanity check the expected module type if we're a submodule (if we're not a submodule, we can't make any such check since there's no gitmodules file to refer to).
        MdmModuleType type = getType();
        MdmModuleType type_configured = MdmModuleType
                .fromString(gitmodulesCfg.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, handle,
                        MdmConfigConstants.Module.MODULE_TYPE.toString()));
        if (type == null)
            throw new MdmModuleTypeException("expected module of type " + type + " for repository " + handle
                    + ", but gitmodules file has no known type for this module.");
        if (type != type_configured)
            throw new MdmModuleTypeException("expected module of type " + type + " for repository " + handle
                    + ", but gitmodules file states this is a " + type_configured + " module.");

        // load real path from gitmodule config (probably same as handle, but theoretically allowed to be different)
        String path = gitmodulesCfg.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, handle,
                ConfigConstants.CONFIG_KEY_PATH);
        this.path = (File.separatorChar != '/') ? path.replace(File.separatorChar, '/') : path;

        // load remote urls
        this.urlHistoric = gitmodulesCfg.getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, handle,
                ConfigConstants.CONFIG_KEY_URL);
        this.urlLocal = parent.getConfig().getString(ConfigConstants.CONFIG_SUBMODULE_SECTION, handle,
                ConfigConstants.CONFIG_KEY_URL);

        // load indexId the parent expects the submodule to be at (if not already provided)
        if (indexId != null)
            this.indexId = indexId;
        else
            try {
                SubmoduleWalk generator = SubmoduleWalk.forIndex(parent).setFilter(PathFilter.create(path));
                this.indexId = generator.next() ? generator.getObjectId() : null;
            } catch (IOException e) {
                throw new MdmRepositoryIOException(false, parent.getWorkTree().getPath(), e);
            }

        // review the submodule and summarize a status.
        SubmoduleStatusType statusType;
        if (path == null)
            // jgit report SubmoduleStatusType.MISSING if no path in .gitmodules file, but I don't even want to deal with that.
            throw new MdmModuleTypeException("no path for module " + handle + " listed in gitmodules file.");
        else if (urlLocal == null)
            // Report uninitialized if no URL in config file
            statusType = SubmoduleStatusType.UNINITIALIZED;
        else if (repo == null)
            // Report uninitialized if no submodule repository
            statusType = SubmoduleStatusType.UNINITIALIZED;
        else if (headId == null)
            // Report uninitialized if no HEAD commit in submodule repository
            statusType = SubmoduleStatusType.UNINITIALIZED;
        else if (!headId.equals(indexId))
            // Report checked out if HEAD commit is different than index commit
            statusType = SubmoduleStatusType.REV_CHECKED_OUT;
        else
            // Report initialized if HEAD commit is the same as the index commit
            statusType = SubmoduleStatusType.INITIALIZED;
        this.status = new SubmoduleStatus(statusType, path, indexId, headId);
    } else {
        this.path = handle;
        this.indexId = null;
        this.urlHistoric = null;
        this.urlLocal = null;
        this.status = null;
    }
}

From source file:net.polydawn.mdm.Plumbing.java

License:Open Source License

public static boolean fetch(Repository repo, MdmModuleDependency module) throws ConfigInvalidException,
        MdmRepositoryIOException, MdmRepositoryStateException, MdmException, IOException {
    switch (module.getStatus().getType()) {
    case MISSING:
        throw new MajorBug();
    case UNINITIALIZED:
        if (module.getRepo() == null)
            try {
                RepositoryBuilder builder = new RepositoryBuilder();
                builder.setWorkTree(new File(repo.getWorkTree() + "/" + module.getPath()));
                builder.setGitDir(new File(repo.getDirectory() + "/modules/" + module.getPath()));
                module.repo = builder.build();

                // we actually *might* not have to make the repo from zero.
                // this getRepo gets its effective data from SubmoduleWalk.getSubmoduleRepository...
                // which does its job by looking in the working tree of the parent repo.
                // meaning if it finds nothing, it certainly won't find any gitdir indirections.
                // so, even if this is null, we might well have a gitdir cached that we still have to go find.
                final FileBasedConfig cfg = (FileBasedConfig) module.repo.getConfig();
                if (!cfg.getFile().exists()) { // though seemly messy, this is the same question the jgit create() function asks, and it's not exposed to us, so.
                    module.repo.create(false);
                } else {
                    // do something crazy, because... i think the user's expectation after blowing away their submodule working tree is likely wanting a clean state of index and such here
                    try {
                        new Git(module.getRepo()).reset().setMode(ResetType.HARD).call();
                    } catch (CheckoutConflictException e) {
                        /* Can a hard reset even have a conflict? */
                        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
                    } catch (GitAPIException e) {
                        throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
                    }/*from  w w  w .j a  v a  2  s.c  o m*/
                }

                // set up a working tree which points to the gitdir in the parent repo:

                // handling paths in java, god forbid relative paths, is such an unbelievable backwater.  someday please make a whole library that actually disambiguates pathnames from filedescriptors properly
                int ups = StringUtils.countMatches(module.getPath(), "/");
                // look up the path between the `repo` and its possible git dir location.  if the gitdir is relocated, we have adjust our own relocations to compensate.
                String parentGitPointerStr = ".git/";
                String parentWorktreePointerStr = "../";
                // load it ourselves because we explicitly want the unresolved path, not what jgit would give us back from `repo.getDirectory().toString()`.
                File parentGitPointer = new File(repo.getWorkTree(), ".git");
                if (parentGitPointer.isFile()) {
                    // this shouldn't have to be recursive fortunately (that recursion is done implicitly by the chaining of each guy at each stage).
                    // this does however feel fairly fragile.  it's considerable that perhaps we should try to heuristically determine when paths are just to crazy to deal with.  but, on the off chance that check was overzealous, it would be very irritating, so let's not.
                    // frankly, if you're doing deeply nested submodules, or other advanced gitdir relocations, at some point you're taking it upon yourself to deal with the inevitably complex outcomes and edge case limitations.
                    parentGitPointerStr = IOForge.readFileAsString(parentGitPointer);
                    if (!"gitdir:".equals(parentGitPointerStr.substring(0, 7)))
                        throw new ConfigInvalidException(
                                "cannot understand location of parent project git directory");
                    parentGitPointerStr = parentGitPointerStr.substring(7).trim() + "/";
                    parentWorktreePointerStr = repo.getConfig().getString("core", null, "worktree") + "/";
                }
                // jgit does not appear to create the .git file correctly here :/
                // nor even consider it to be jgit's job to create the worktree yet, apparently, so do that
                module.repo.getWorkTree().mkdirs();
                // need modules/[module]/config to contain 'core.worktree' = appropriate
                String submoduleWorkTreeRelativeToGitDir = StringUtils.repeat("../", ups + 2)
                        + parentWorktreePointerStr + module.getPath();
                StoredConfig cnf = module.repo.getConfig();
                cnf.setString("core", null, "worktree", submoduleWorkTreeRelativeToGitDir);
                cnf.save();
                // need [module]/.git to contain 'gitdir: appropriate' (which appears to not be normal gitconfig)
                String submoduleGitDirRelativeToWorkTree = StringUtils.repeat("../", ups + 1)
                        + parentGitPointerStr + "modules/" + module.getPath();
                IOForge.saveFile("gitdir: " + submoduleGitDirRelativeToWorkTree + "\n",
                        new File(module.repo.getWorkTree(), ".git"));
            } catch (IOException e) {
                throw new MdmRepositoryIOException("create a new submodule", true, module.getHandle(), e);
            }

        try {
            if (initLocalConfig(repo, module))
                repo.getConfig().save();
        } catch (IOException e) {
            throw new MdmRepositoryIOException("save changes", true, "the local git configuration file", e);
        }
        try {
            setMdmRemote(module);
            module.getRepo().getConfig().save();
        } catch (IOException e) {
            throw new MdmRepositoryIOException("save changes", true,
                    "the git configuration file for submodule " + module.getHandle(), e);
        }
    case INITIALIZED:
        if (module.getVersionName() == null || module.getVersionName().equals(module.getVersionActual()))
            return false;
    case REV_CHECKED_OUT:
        try {
            if (initModuleConfig(repo, module))
                module.getRepo().getConfig().save();
        } catch (IOException e) {
            throw new MdmRepositoryIOException("save changes", true,
                    "the git configuration file for submodule " + module.getHandle(), e);
        }

        final String versionBranchName = "refs/heads/mdm/release/" + module.getVersionName();
        final String versionTagName = "refs/tags/release/" + module.getVersionName();

        /* Fetch only the branch labelled with the version requested. */
        if (module.getRepo().getRef(versionBranchName) == null)
            try {
                RefSpec releaseBranchRef = new RefSpec().setForceUpdate(true).setSource(versionBranchName)
                        .setDestination(versionBranchName);
                RefSpec releaseTagRef = new RefSpec().setForceUpdate(true).setSource(versionTagName)
                        .setDestination(versionTagName);
                new Git(module.getRepo()).fetch().setRemote("origin")
                        .setRefSpecs(releaseBranchRef, releaseTagRef).setTagOpt(TagOpt.NO_TAGS).call();
            } catch (InvalidRemoteException e) {
                throw new MdmRepositoryStateException(
                        "find a valid remote origin in the config for the submodule", module.getHandle(), e);
            } catch (TransportException e) {
                URIish remote = null;
                try { //XXX: if we went through all the work to resolve the remote like the fetch command does, we could just as well do it and hand the resolved uri to fetch for better consistency.
                    remote = new RemoteConfig(module.getRepo().getConfig(), "origin").getURIs().get(0);
                } catch (URISyntaxException e1) {
                }
                throw new MdmRepositoryIOException("fetch from a remote", false, remote.toASCIIString(), e)
                        .setAdditionalMessage("check your connectivity and try again?");
            } catch (GitAPIException e) {
                throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
            }

        /* Drop the files into the working tree. */
        try {
            new Git(module.getRepo()).checkout().setName(versionBranchName).setForce(true).call();
        } catch (RefAlreadyExistsException e) {
            /* I'm not creating a new branch, so this exception wouldn't even make sense. */
            throw new MajorBug(e);
        } catch (RefNotFoundException e) {
            /* I just got this branch, so we shouldn't have a problem here. */
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        } catch (InvalidRefNameException e) {
            /* I just got this branch, so we shouldn't have a problem here. */
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        } catch (CheckoutConflictException e) {
            // this one is just a perfectly reasonable message with a list of files in conflict; we'll take it.
            throw new MdmRepositoryStateException(module.getHandle(), e); // this currently gets translated to a :'( exception and it's probably more like a :(
        } catch (GitAPIException e) {
            throw new MajorBug("an unrecognized problem occurred.  please file a bug report.", e);
        }
        return true;
    default:
        throw new MajorBug();
    }
}

From source file:net.polydawn.mdm.Plumbing.java

License:Open Source License

/**
 * wield `git ls-remote` to get a list of branches matching the labelling pattern
 * mdm releases use. works locally or remote over any transport git itself
 * supports./*from w w  w  . ja  va  2 s  .c o m*/
 *
 * @param repo
 *                this argument is completely stupid and should not be required.
 *                The jgit api for ls-remote is wrong. Go ahead and use the parent
 *                repo.
 * @throws GitAPIException
 * @throws TransportException
 * @throws InvalidRemoteException
 */
public static List<String> getVersionManifest(Repository repo, String releasesUrl)
        throws InvalidRemoteException, TransportException, GitAPIException {
    Collection<Ref> refs = new Git(repo).lsRemote().setRemote(releasesUrl).call();
    final String mdmReleaseRefPrefix = "refs/heads/mdm/release/";
    List<String> v = new ArrayList<String>();
    for (Ref ref : refs) {
        if (ref.getName().startsWith(mdmReleaseRefPrefix))
            v.add(ref.getName().substring(mdmReleaseRefPrefix.length()));
    }
    Collections.sort(v, new VersionComparator());
    return v;
}