public FormValidation doCheckUrl( @AncestorInPath Item project, @QueryParameter String credentialsId, @QueryParameter String value) throws IOException, InterruptedException { if (project == null || !project.hasPermission(Item.CONFIGURE)) { return FormValidation.ok(); } String url = Util.fixEmptyAndTrim(value); if (url == null) return FormValidation.error("Please enter repository url."); // get git executable on master final EnvVars environment = new EnvVars(EnvVars.masterEnvVars); GitClient git = Git.with(TaskListener.NULL, environment) .using(GitTool.getDefaultInstallation().getGitExe()) .getClient(); if (credentialsId != null) { StandardCredentials credentials = lookupCredentials(project, credentialsId, url); if (credentials != null) git.addDefaultCredentials(credentials); } // attempt to connect the provided URL try { git.getHeadRev(url, "HEAD"); } catch (GitException e) { return FormValidation.error(Messages.UserRemoteConfig_FailedToConnect(e.getMessage())); } return FormValidation.ok(); }
@Override public Revision decorateRevisionToBuild( GitSCM scm, AbstractBuild<?, ?> build, GitClient git, BuildListener listener, Revision rev) throws IOException, InterruptedException { String remoteBranchRef = GitSCM.getParameterString(options.getRef(), build.getEnvironment(listener)); // if the branch we are merging is already at the commit being built, the entire merge becomes // no-op // so there's nothing to do if (rev.containsBranchName(remoteBranchRef)) return rev; // Only merge if there's a branch to merge that isn't us.. listener .getLogger() .println( "Merging " + rev + " onto " + remoteBranchRef + " using " + scm.getUserMergeOptions().getMergeStrategy().toString() + " strategy"); // checkout origin/blah ObjectId target = git.revParse(remoteBranchRef); String paramLocalBranch = scm.getParamLocalBranch(build); git.checkoutBranch(paramLocalBranch, remoteBranchRef); try { MergeCommand cmd = git.merge().setRevisionToMerge(rev.getSha1()); for (GitSCMExtension ext : scm.getExtensions()) ext.decorateMergeCommand(scm, build, git, listener, cmd); cmd.execute(); } catch (GitException ex) { // merge conflict. First, avoid leaving any conflict markers in the working tree // by checking out some known clean state. We don't really mind what commit this is, // since the next build is going to pick its own commit to build, but 'rev' is as good any. git.checkoutBranch(paramLocalBranch, rev.getSha1String()); // record the fact that we've tried building 'rev' and it failed, or else // BuildChooser in future builds will pick up this same 'rev' again and we'll see the exact // same merge failure // all over again. scm.getBuildData(build).saveBuild(new Build(rev, build.getNumber(), FAILURE)); throw new AbortException("Branch not suitable for integration as it does not merge cleanly"); } build.addAction(new MergeRecord(remoteBranchRef, target.getName())); return new GitUtils(listener, git).getRevisionForSHA1(git.revParse(HEAD)); }
public String prettyRevisionInfo(GitClient newgit, Revision r) { List<String> test3 = null; try { test3 = newgit.showRevision(r.getSha1()); } catch (GitException e1) { return ""; } catch (InterruptedException e1) { return ""; } String[] authorDate = test3.get(3).split(">"); String author = authorDate[0].replaceFirst("author ", "").replaceFirst("committer ", "") + ">"; String goodDate = null; try { String totmp = authorDate[1].trim().split("\\+")[0].trim(); long timestamp = Long.parseLong(totmp, 10) * 1000; Date date = new Date(); date.setTime(timestamp); goodDate = new SimpleDateFormat("yyyy:MM:dd HH:mm").format(date); } catch (Exception e) { e.toString(); } return r.getSha1String().substring(0, 8) + " " + goodDate + " " + author; }
@Before public void createGitRepository() throws IOException, InterruptedException { tempAllocator = new TemporaryDirectoryAllocator(); testGitDir = tempAllocator.allocate(); TaskListener listener = StreamTaskListener.fromStderr(); testGitClient = Git.with(listener, new EnvVars()).in(testGitDir).getClient(); testGitClient.init(); }
public void commit( final String fileName, final String fileContent, final PersonIdent author, final PersonIdent committer, final String message) throws GitException, InterruptedException { FilePath file = gitDirPath.child(fileName); try { file.write(fileContent, null); } catch (Exception e) { throw new GitException("unable to write file", e); } git.add(fileName); git.setAuthor(author); git.setCommitter(committer); git.commit(message); }
/** * Commit fileName to this git repository * * @param fileName name of file to create * @throws GitException * @throws InterruptedException */ protected void commitNewFile(final String fileName) throws GitException, InterruptedException { File newFile = new File(testGitDir, fileName); assert !newFile.exists(); // Not expected to use commitNewFile to update existing file PrintWriter writer = null; try { writer = new PrintWriter(newFile, "UTF-8"); writer.println("A file named " + fileName); writer.close(); testGitClient.add(fileName); testGitClient.commit("Added a file named " + fileName); } catch (FileNotFoundException notFound) { throw new GitException(notFound); } catch (UnsupportedEncodingException unsupported) { throw new GitException(unsupported); } finally { if (writer != null) { writer.close(); } } }
private List<String> getFilteredTestCandidates(Integer maxAgeInDays, String ancestorCommitSha1) throws Exception { GitSCM gitSCM = new GitSCM("foo"); AncestryBuildChooser chooser = new AncestryBuildChooser(maxAgeInDays, ancestorCommitSha1); gitSCM.getExtensions().add(new BuildChooserSetting(chooser)); assertEquals(maxAgeInDays, chooser.getMaximumAgeInDays()); assertEquals(ancestorCommitSha1, chooser.getAncestorCommitSha1()); // mock necessary objects GitClient git = Mockito.spy(this.testGitClient); Mockito.when(git.getRemoteBranches()).thenReturn(this.testGitClient.getBranches()); BuildData buildData = Mockito.mock(BuildData.class); Mockito.when(buildData.hasBeenBuilt(git.revParse(rootCommit))).thenReturn(false); BuildChooserContext context = Mockito.mock(BuildChooserContext.class); Mockito.when(context.getEnvironment()).thenReturn(new EnvVars()); TaskListener listener = TaskListener.NULL; // get filtered candidates Collection<Revision> candidateRevisions = gitSCM .getBuildChooser() .getCandidateRevisions(true, "**-days-old-branch", git, listener, buildData, context); // transform revision candidates to sha1 strings List<String> candidateSha1s = Lists.newArrayList( Iterables.transform( candidateRevisions, new Function<Revision, String>() { public String apply(Revision rev) { return rev.getSha1String(); } })); return candidateSha1s; }
private Collection<Revision> getHeadRevision( boolean isPollCall, String singleBranch, GitClient git, TaskListener listener, BuildData data) throws InterruptedException { try { ObjectId sha1 = git.revParse(singleBranch); verbose(listener, "rev-parse {0} -> {1}", singleBranch, sha1); // if polling for changes don't select something that has // already been built as a build candidate if (isPollCall && data.hasBeenBuilt(sha1)) { verbose(listener, "{0} has already been built", sha1); return emptyList(); } verbose(listener, "Found a new commit {0} to be built on {1}", sha1, singleBranch); Revision revision = new Revision(sha1); revision.getBranches().add(new Branch(singleBranch, sha1)); return Collections.singletonList(revision); /* // calculate the revisions that are new compared to the last build List<Revision> candidateRevs = new ArrayList<Revision>(); List<ObjectId> allRevs = git.revListAll(); // index 0 contains the newest revision if (data != null && allRevs != null) { Revision lastBuiltRev = data.getLastBuiltRevision(); if (lastBuiltRev == null) { return Collections.singletonList(objectId2Revision(singleBranch, sha1)); } int indexOfLastBuildRev = allRevs.indexOf(lastBuiltRev.getSha1()); if (indexOfLastBuildRev == -1) { // mhmmm ... can happen when branches are switched. return Collections.singletonList(objectId2Revision(singleBranch, sha1)); } List<ObjectId> newRevisionsSinceLastBuild = allRevs.subList(0, indexOfLastBuildRev); // translate list of ObjectIds into list of Revisions for (ObjectId objectId : newRevisionsSinceLastBuild) { candidateRevs.add(objectId2Revision(singleBranch, objectId)); } } if (candidateRevs.isEmpty()) { return Collections.singletonList(objectId2Revision(singleBranch, sha1)); } return candidateRevs; */ } catch (GitException e) { // branch does not exist, there is nothing to build verbose(listener, "Failed to rev-parse: {0}", singleBranch); return emptyList(); } }
public TestGitRepo(String name, File tmpDir, TaskListener listener) throws IOException, InterruptedException { this.name = name; this.listener = listener; envVars = new EnvVars(); gitDir = tmpDir; User john = User.get(johnDoe.getName(), true); UserProperty johnsMailerProperty = new Mailer.UserProperty(johnDoe.getEmailAddress()); john.addProperty(johnsMailerProperty); User jane = User.get(janeDoe.getName(), true); UserProperty janesMailerProperty = new Mailer.UserProperty(janeDoe.getEmailAddress()); jane.addProperty(janesMailerProperty); // initialize the git interface. gitDirPath = new FilePath(gitDir); git = Git.with(listener, envVars).in(gitDir).getClient(); // finally: initialize the repo git.init(); }
@CheckForNull @Override protected SCMRevision retrieve(@NonNull SCMHead head, @NonNull TaskListener listener) throws IOException, InterruptedException { String cacheEntry = getCacheEntry(); Lock cacheLock = getCacheLock(cacheEntry); cacheLock.lock(); try { File cacheDir = getCacheDir(cacheEntry); Git git = Git.with(listener, new EnvVars(System.getenv())) .in(cacheDir) .using(GitTool.getDefaultInstallation().getGitExe()); GitClient client = git.getClient(); client.addDefaultCredentials(getCredentials()); if (!client.hasGitRepo()) { listener.getLogger().println("Creating git repository in " + cacheDir); client.init(); } String remoteName = getRemoteName(); listener.getLogger().println("Setting " + remoteName + " to " + getRemote()); client.setRemoteUrl(remoteName, getRemote()); listener.getLogger().println("Fetching " + remoteName + "..."); List<RefSpec> refSpecs = getRefSpecs(); client.fetch(remoteName, refSpecs.toArray(new RefSpec[refSpecs.size()])); // we don't prune remotes here, as we just want one head's revision for (Branch b : client.getRemoteBranches()) { String branchName = StringUtils.removeStart(b.getName(), remoteName + "/"); if (branchName.equals(head.getName())) { return new SCMRevisionImpl(head, b.getSHA1String()); } } return null; } finally { cacheLock.unlock(); } }
/** * Determines which Revisions to build. * * <p>If only one branch is chosen and only one repository is listed, then just attempt to find * the latest revision number for the chosen branch. * * <p>If multiple branches are selected or the branches include wildcards, then use the advanced * usecase as defined in the getAdvancedCandidateRevisons method. * * @throws IOException * @throws GitException */ @Override public Collection<Revision> getCandidateRevisions( boolean isPollCall, String singleBranch, GitClient git, TaskListener listener, BuildData data, BuildChooserContext context) throws GitException, IOException, InterruptedException { verbose( listener, "getCandidateRevisions({0},{1},,,{2}) considering branches to build", isPollCall, singleBranch, data); // if the branch name contains more wildcards then the simple usecase // does not apply and we need to skip to the advanced usecase if (singleBranch == null || singleBranch.contains("*")) return getAdvancedCandidateRevisions( isPollCall, listener, new GitUtils(listener, git), data, context); // check if we're trying to build a specific commit // this only makes sense for a build, there is no // reason to poll for a commit if (!isPollCall && singleBranch.matches("[0-9a-f]{6,40}")) { try { ObjectId sha1 = git.revParse(singleBranch); Revision revision = new Revision(sha1); revision.getBranches().add(new Branch("detached", sha1)); verbose(listener, "Will build the detached SHA1 {0}", sha1); return Collections.singletonList(revision); } catch (GitException e) { // revision does not exist, may still be a branch // for example a branch called "badface" would show up here verbose(listener, "Not a valid SHA1 {0}", singleBranch); } } Collection<Revision> revisions = new ArrayList<Revision>(); // if it doesn't contain '/' then it could be either a tag or an unqualified branch if (!singleBranch.contains("/")) { // the 'branch' could actually be a tag: Set<String> tags = git.getTagNames(singleBranch); if (tags.size() != 0) { verbose(listener, "{0} is a tag"); return getHeadRevision(isPollCall, singleBranch, git, listener, data); } // <tt>BRANCH</tt> is recognized as a shorthand of <tt>*/BRANCH</tt> // so check all remotes to fully qualify this branch spec for (RemoteConfig config : gitSCM.getRepositories()) { String repository = config.getName(); String fqbn = repository + "/" + singleBranch; verbose( listener, "Qualifying {0} as a branch in repository {1} -> {2}", singleBranch, repository, fqbn); revisions.addAll(getHeadRevision(isPollCall, fqbn, git, listener, data)); } } else { // either the branch is qualified (first part should match a valid remote) // or it is still unqualified, but the branch name contains a '/' List<String> possibleQualifiedBranches = new ArrayList<String>(); boolean singleBranchIsQualified = false; for (RemoteConfig config : gitSCM.getRepositories()) { String repository = config.getName(); if (singleBranch.startsWith(repository + "/")) { singleBranchIsQualified = true; break; } String fqbn = repository + "/" + singleBranch; verbose( listener, "Qualifying {0} as a branch in repository {1} -> {2}", singleBranch, repository, fqbn); possibleQualifiedBranches.add(fqbn); } if (singleBranchIsQualified) { revisions.addAll(getHeadRevision(isPollCall, singleBranch, git, listener, data)); } else { for (String fqbn : possibleQualifiedBranches) { revisions.addAll(getHeadRevision(isPollCall, fqbn, git, listener, data)); } } } return revisions; }
public Map<String, String> generateContents(AbstractProject<?, ?> project, GitSCM git) throws IOException, InterruptedException { Map<String, String> paramList = new LinkedHashMap<String, String>(); // for (AbstractProject<?,?> project : // Hudson.getInstance().getItems(AbstractProject.class)) { if (project.getSomeWorkspace() == null) { this.errorMessage = "noWorkspace"; } EnvVars environment = null; try { environment = project.getSomeBuildWithWorkspace().getEnvironment(TaskListener.NULL); } catch (Exception e) { } for (RemoteConfig repository : git.getRepositories()) { LOGGER.log( Level.INFO, "generateContents contenttype " + type + " RemoteConfig " + repository.getURIs()); for (URIish remoteURL : repository.getURIs()) { GitClient newgit = git.createClient( TaskListener.NULL, environment, new Run(project) {}, project.getSomeWorkspace()); FilePath wsDir = null; if (project.getSomeBuildWithWorkspace() != null) { wsDir = project.getSomeBuildWithWorkspace().getWorkspace(); if (wsDir == null || !wsDir.exists()) { LOGGER.log( Level.WARNING, "generateContents create wsDir " + wsDir + " for " + remoteURL); wsDir.mkdirs(); if (!wsDir.exists()) { LOGGER.log(Level.SEVERE, "generateContents wsDir.mkdirs() failed."); String errMsg = "!Failed To Create Workspace"; return Collections.singletonMap(errMsg, errMsg); } newgit.init(); newgit.clone(remoteURL.toASCIIString(), "origin", false, null); LOGGER.log(Level.INFO, "generateContents clone done"); } } else { // probably our first build. We cannot yet fill in any // values. LOGGER.log(Level.INFO, "getSomeBuildWithWorkspace is null"); String errMsg = "!No workspace. Please build the project at least once"; return Collections.singletonMap(errMsg, errMsg); } long time = -System.currentTimeMillis(); FetchCommand fetch = newgit.fetch_().from(remoteURL, repository.getFetchRefSpecs()); fetch.execute(); LOGGER.finest("Took " + (time + System.currentTimeMillis()) + "ms to fetch"); if (type.equalsIgnoreCase(PARAMETER_TYPE_REVISION)) { List<ObjectId> oid; if (this.branch != null && !this.branch.isEmpty()) { oid = newgit.revList(this.branch); } else { oid = newgit.revListAll(); } for (ObjectId noid : oid) { Revision r = new Revision(noid); paramList.put(r.getSha1String(), prettyRevisionInfo(newgit, r)); } } if (type.equalsIgnoreCase(PARAMETER_TYPE_TAG) || type.equalsIgnoreCase(PARAMETER_TYPE_TAG_BRANCH)) { Set<String> tagSet = newgit.getTagNames(tagFilter); ArrayList<String> orderedTagNames; if (this.getSortMode().getIsSorting()) { orderedTagNames = sortByName(tagSet); if (this.getSortMode().getIsDescending()) Collections.reverse(orderedTagNames); } else { orderedTagNames = new ArrayList<String>(tagSet); } for (String tagName : orderedTagNames) { paramList.put(tagName, tagName); } } if (type.equalsIgnoreCase(PARAMETER_TYPE_BRANCH) || type.equalsIgnoreCase(PARAMETER_TYPE_TAG_BRANCH)) { time = -System.currentTimeMillis(); Set<String> branchSet = new HashSet<String>(); final boolean wildcard = "*".equals(branchfilter); for (Branch branch : newgit.getRemoteBranches()) { // It'd be nice if we could filter on remote branches via the GitClient, // but that's not an option. final String branchName = branch.getName(); if (wildcard || branchName.matches(branchfilter)) { branchSet.add(branchName); } } LOGGER.finest("Took " + (time + System.currentTimeMillis()) + "ms to fetch branches"); time = -System.currentTimeMillis(); List<String> orderedBranchNames; if (this.getSortMode().getIsSorting()) { orderedBranchNames = sortByName(branchSet); if (this.getSortMode().getIsDescending()) Collections.reverse(orderedBranchNames); } else { orderedBranchNames = new ArrayList<String>(branchSet); } for (String branchName : orderedBranchNames) { paramList.put(branchName, branchName); } LOGGER.finest( "Took " + (time + System.currentTimeMillis()) + "ms to sort and add to param list."); } } break; } return paramList; }
@NonNull @Override protected void retrieve(@NonNull final SCMHeadObserver observer, @NonNull TaskListener listener) throws IOException, InterruptedException { String cacheEntry = getCacheEntry(); Lock cacheLock = getCacheLock(cacheEntry); cacheLock.lock(); try { File cacheDir = getCacheDir(cacheEntry); Git git = Git.with(listener, new EnvVars(System.getenv())) .in(cacheDir) .using(GitTool.getDefaultInstallation().getGitExe()); GitClient client = git.getClient(); client.addDefaultCredentials(getCredentials()); if (!client.hasGitRepo()) { listener.getLogger().println("Creating git repository in " + cacheDir); client.init(); } String remoteName = getRemoteName(); listener.getLogger().println("Setting " + remoteName + " to " + getRemote()); client.setRemoteUrl(remoteName, getRemote()); listener.getLogger().println("Fetching " + remoteName + "..."); List<RefSpec> refSpecs = getRefSpecs(); client.fetch(remoteName, refSpecs.toArray(new RefSpec[refSpecs.size()])); listener.getLogger().println("Pruning stale remotes..."); final Repository repository = client.getRepository(); try { client.prune(new RemoteConfig(repository.getConfig(), remoteName)); } catch (UnsupportedOperationException e) { e.printStackTrace(listener.error("Could not prune stale remotes")); } catch (URISyntaxException e) { e.printStackTrace(listener.error("Could not prune stale remotes")); } listener.getLogger().println("Getting remote branches..."); SCMSourceCriteria branchCriteria = getCriteria(); RevWalk walk = new RevWalk(repository); try { walk.setRetainBody(false); for (Branch b : client.getRemoteBranches()) { if (!b.getName().startsWith(remoteName + "/")) { continue; } final String branchName = StringUtils.removeStart(b.getName(), remoteName + "/"); listener.getLogger().println("Checking branch " + branchName); if (isExcluded(branchName)) { continue; } if (branchCriteria != null) { RevCommit commit = walk.parseCommit(b.getSHA1()); final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime()); final RevTree tree = commit.getTree(); SCMSourceCriteria.Probe probe = new SCMSourceCriteria.Probe() { @Override public String name() { return branchName; } @Override public long lastModified() { return lastModified; } @Override public boolean exists(@NonNull String path) throws IOException { TreeWalk tw = TreeWalk.forPath(repository, path, tree); try { return tw != null; } finally { if (tw != null) { tw.release(); } } } }; if (branchCriteria.isHead(probe, listener)) { listener.getLogger().println("Met criteria"); } else { listener.getLogger().println("Does not meet criteria"); continue; } } SCMHead head = new SCMHead(branchName); SCMRevision hash = new SCMRevisionImpl(head, b.getSHA1String()); observer.observe(head, hash); if (!observer.isObserving()) { return; } } } finally { walk.dispose(); } listener.getLogger().println("Done."); } finally { cacheLock.unlock(); } }