diff mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java @ 399:45f25ca68312 Faradi-7.0.x

Support local mirrors for subrepos
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Fri, 02 Mar 2012 14:24:58 +0400
parents
children e33c3e4918f5 4a76645fe087
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Fri Mar 02 14:24:58 2012 +0400
@@ -0,0 +1,216 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
+import jetbrains.buildServer.util.FileUtil;
+import jetbrains.buildServer.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.intellij.openapi.util.io.FileUtil.delete;
+import static java.util.Collections.emptyMap;
+import static jetbrains.buildServer.util.FileUtil.isEmptyDir;
+
+/**
+* @author dmitry.neverov
+*/
+public class HgRepo {
+
+  protected final File myWorkingDir;
+  protected final String myHgPath;
+  protected final AuthSettings myAuthSettings;
+  private final Map<String, Map<String, SubRepo>> mySubreposCache = new HashMap<String, Map<String, SubRepo>>();
+
+  public HgRepo(@NotNull File workingDir, @NotNull String hgPath, @NotNull AuthSettings authSettings) {
+    myWorkingDir = workingDir;
+    myHgPath = hgPath;
+    myAuthSettings = authSettings;
+  }
+
+  public PullCommand pull() {
+    return new PullCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public PushCommand push() {
+    return new PushCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public CloneCommand doClone() {
+    return new CloneCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public IdentifyCommand id() {
+    return new IdentifyCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public Init init() {
+    return new Init(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public LogCommand log() {
+    return new LogCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public UpdateCommand update() {
+    return new UpdateCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public BranchesCommand branches() {
+    return new BranchesCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public StatusCommand status() {
+    return new StatusCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public TagCommand tag() {
+    return new TagCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public CatCommand cat() {
+    return new CatCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public ArchiveCommand archive() {
+    return new ArchiveCommand(myHgPath, myWorkingDir, myAuthSettings);
+  }
+
+  public String path() {
+    return myWorkingDir.getAbsolutePath();
+  }
+
+  public File getWorkingDir() {
+    return myWorkingDir;
+  }
+
+  public boolean isEmpty() {
+    return isEmptyDir(myWorkingDir);
+  }
+
+  public String getWorkingDirRevision() throws VcsException {
+    return id().inLocalRepository().call();
+  }
+
+  public boolean containsRevision(@NotNull String revision) {
+    return containsRevision(new ChangeSet(revision));
+  }
+
+  public boolean containsRevision(@NotNull ChangeSet cset) {
+    try {
+      id().revision(cset).inLocalRepository().call();
+      return true;
+    } catch (VcsException e) {
+      return false;
+    }
+  }
+
+  public boolean isValidRepository() {
+    // need better way to check that repository copy is ok
+    return myWorkingDir.isDirectory() && new File(myWorkingDir, ".hg").isDirectory();
+  }
+
+  public void setDefaultPath(@NotNull String defaultPath) {
+    File hgrc = new File(new File(myWorkingDir, ".hg"), "hgrc");
+    String content = "[paths]\ndefault = " + defaultPath;
+    FileUtil.writeFile(hgrc, content);
+  }
+
+  public boolean hasSubreposAtRevision(@NotNull String revision) {
+    return !getSubrepositories(new ChangeSet(revision)).isEmpty();
+  }
+
+  public boolean hasSubreposAtRevision(@NotNull ChangeSet cset) {
+    return !getSubrepositories(cset).isEmpty();
+  }
+
+  public Map<String, SubRepo> getSubrepositories(@NotNull String revision) {
+    return getSubrepositories(new ChangeSet(revision));
+  }
+
+  public Map<String, SubRepo> getSubrepositories(@NotNull ChangeSet cset) {
+    String revId = cset.getId();
+    Map<String, SubRepo> subrepos = mySubreposCache.get(revId);
+    if (subrepos != null)
+      return subrepos;
+    CatCommand cc = cat();
+    cc.setRevId(revId);
+    File catDir = null;
+    try {
+      catDir = cc.execute(Arrays.asList(".hgsub", ".hgsubstate"), false);
+      File hgsub = new File(catDir, ".hgsub");
+      File hgsubstate = new File(catDir, ".hgsubstate");
+      subrepos = readSubrepositories(hgsub, hgsubstate);
+      mySubreposCache.put(revId, subrepos);
+      return subrepos;
+    } catch (VcsException e) {
+      return emptyMap();
+    } finally {
+      if (catDir != null)
+        delete(catDir);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return myWorkingDir.getAbsolutePath();
+  }
+
+  private Map<String, SubRepo> readSubrepositories(@NotNull final File hgsub, @NotNull final File hgsubstate) {
+    if (hgsub.exists() && hgsubstate.exists()) {
+      try {
+        Map<String, String> path2repo = readHgsub(hgsub);
+        Map<String, String> path2revision = readHgsubstate(hgsubstate);
+        Map<String, SubRepo> result = new HashMap<String, SubRepo>();
+        for (Map.Entry<String, String> entry : path2repo.entrySet()) {
+          String path = entry.getKey();
+          String url = entry.getValue();
+          String revision = path2revision.get(path);
+          if (revision != null) {
+            result.put(path, new SubRepo(this, path, url, revision));
+          } else {
+//              myLogger.warning("Cannot find revision for subrepository at path " + path + " skip it");
+          }
+        }
+        return result;
+      } catch (IOException e) {
+//          myLogger.warning("Error while trying to read subrepositories " + e.getMessage());
+        return emptyMap();
+      }
+    } else {
+      return emptyMap();
+    }
+  }
+
+  /*returns map: relative path -> repository url */
+  private Map<String, String> readHgsub(@NotNull final File hgsub) throws IOException {
+    Map<String, String> result = new HashMap<String, String>();
+    for (String line : FileUtil.readFile(hgsub)) {
+      String[] parts = line.split(" = ");
+      if (parts.length == 2) {
+        result.put(parts[0], parts[1]);
+      } else {
+//          myLogger.warning("Cannot parse the line '" + line + "' from .hgsub, skip it");
+      }
+    }
+    return result;
+  }
+
+
+  /*returns map: relative path -> revision */
+  private Map<String, String> readHgsubstate(@NotNull final File hgsubstate) throws IOException {
+    Map<String, String> result = new HashMap<String, String>();
+    for (String line : FileUtil.readFile(hgsubstate)) {
+      String[] parts = line.split(" ");
+      if (parts.length == 2) {
+        result.put(parts[1], parts[0]);
+      } else {
+//          myLogger.warning("Cannot parse the line '" + line + "' from .hgsubstate, skip it");
+      }
+    }
+    return result;
+  }
+}