Example #1
0
 public void create() throws IOException, ConfigInvalidException {
   try (Repository git = mgr.openRepository(allUsersName)) {
     initAllUsers(git);
   } catch (RepositoryNotFoundException notFound) {
     try (Repository git = mgr.createRepository(allUsersName)) {
       initAllUsers(git);
     } catch (RepositoryNotFoundException err) {
       String name = allUsersName.get();
       throw new IOException("Cannot create repository " + name, err);
     }
   }
 }
Example #2
0
 @Override
 public String apply(ProjectResource rsrc)
     throws AuthException, ResourceNotFoundException, IOException {
   try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) {
     Ref head = repo.getRefDatabase().exactRef(Constants.HEAD);
     if (head == null) {
       throw new ResourceNotFoundException(Constants.HEAD);
     } else if (head.isSymbolic()) {
       String n = head.getTarget().getName();
       if (rsrc.getControl().controlForRef(n).isVisible()) {
         return n;
       }
       throw new AuthException("not allowed to see HEAD");
     } else if (head.getObjectId() != null) {
       try (RevWalk rw = new RevWalk(repo)) {
         RevCommit commit = rw.parseCommit(head.getObjectId());
         if (rsrc.getControl().canReadCommit(db.get(), repo, commit)) {
           return head.getObjectId().name();
         }
         throw new AuthException("not allowed to see HEAD");
       } catch (MissingObjectException | IncorrectObjectTypeException e) {
         if (rsrc.getControl().isOwner()) {
           return head.getObjectId().name();
         }
         throw new AuthException("not allowed to see HEAD");
       }
     }
     throw new ResourceNotFoundException(Constants.HEAD);
   } catch (RepositoryNotFoundException e) {
     throw new ResourceNotFoundException(rsrc.getName());
   }
 }
  private static ChangeKind getChangeKindInternal(
      ChangeKindCache cache,
      ReviewDb db,
      Change change,
      PatchSet patch,
      ChangeData.Factory changeDataFactory,
      ProjectCache projectCache,
      GitRepositoryManager repoManager) {
    Repository repo = null;
    // TODO - dborowitz: add NEW_CHANGE type for default.
    ChangeKind kind = ChangeKind.REWORK;
    // Trivial case: if we're on the first patch, we don't need to open
    // the repository.
    if (patch.getId().get() > 1) {
      try {
        ProjectState projectState = projectCache.checkedGet(change.getProject());

        repo = repoManager.openRepository(change.getProject());

        ChangeData cd = changeDataFactory.create(db, change);
        Collection<PatchSet> patchSetCollection = cd.patches();
        PatchSet priorPs = patch;
        for (PatchSet ps : patchSetCollection) {
          if (ps.getId().get() < patch.getId().get()
              && (ps.getId().get() > priorPs.getId().get() || priorPs == patch)) {
            // We only want the previous patch set, so walk until the last one
            priorPs = ps;
          }
        }

        // If we still think the previous patch is the current patch,
        // we only have one patch set.  Return the default.
        // This can happen if a user creates a draft, uploads a second patch,
        // and deletes the draft.
        if (priorPs != patch) {
          kind =
              cache.getChangeKind(
                  projectState,
                  repo,
                  ObjectId.fromString(priorPs.getRevision().get()),
                  ObjectId.fromString(patch.getRevision().get()));
        }
      } catch (IOException | OrmException e) {
        // Do nothing; assume we have a complex change
        log.warn(
            "Unable to get change kind for patchSet "
                + patch.getPatchSetId()
                + "of change "
                + change.getChangeId(),
            e);
      } finally {
        if (repo != null) {
          repo.close();
        }
      }
    }
    return kind;
  }
 private LabelTypes getLabelTypes() throws Exception {
   db.create();
   ProjectConfig c = new ProjectConfig(allProjects);
   Repository repo = repoManager.openRepository(allProjects);
   try {
     c.load(repo);
     return new LabelTypes(ImmutableList.copyOf(c.getLabelSections().values()));
   } finally {
     repo.close();
   }
 }
 public PatchSetInfo get(Project.NameKey project, PatchSet patchSet)
     throws PatchSetInfoNotAvailableException {
   try (Repository repo = repoManager.openRepository(project);
       RevWalk rw = new RevWalk(repo)) {
     final RevCommit src = rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get()));
     PatchSetInfo info = get(rw, src, patchSet.getId());
     info.setParents(toParentInfos(src.getParents(), rw));
     return info;
   } catch (IOException e) {
     throw new PatchSetInfoNotAvailableException(e);
   }
 }
Example #6
0
  @Override
  public Response<List<BlameInfo>> apply(FileResource resource)
      throws RestApiException, OrmException, IOException, InvalidChangeOperationException {
    if (!allowBlame) {
      throw new BadRequestException("blame is disabled");
    }

    Project.NameKey project = resource.getRevision().getChange().getProject();
    try (Repository repository = repoManager.openRepository(project);
        ObjectInserter ins = repository.newObjectInserter();
        RevWalk revWalk = new RevWalk(ins.newReader())) {
      String refName =
          resource.getRevision().getEdit().isPresent()
              ? resource.getRevision().getEdit().get().getRefName()
              : resource.getRevision().getPatchSet().getRefName();

      Ref ref = repository.findRef(refName);
      if (ref == null) {
        throw new ResourceNotFoundException("unknown ref " + refName);
      }
      ObjectId objectId = ref.getObjectId();
      RevCommit revCommit = revWalk.parseCommit(objectId);
      RevCommit[] parents = revCommit.getParents();

      String path = resource.getPatchKey().getFileName();

      List<BlameInfo> result;
      if (!base) {
        result = blame(revCommit, path, repository, revWalk);

      } else if (parents.length == 0) {
        throw new ResourceNotFoundException("Initial commit doesn't have base");

      } else if (parents.length == 1) {
        result = blame(parents[0], path, repository, revWalk);

      } else if (parents.length == 2) {
        ObjectId automerge = autoMerger.merge(repository, revWalk, ins, revCommit, mergeStrategy);
        result = blame(automerge, path, repository, revWalk);

      } else {
        throw new ResourceNotFoundException(
            "Cannot generate blame for merge commit with more than 2 parents");
      }

      Response<List<BlameInfo>> r = Response.ok(result);
      if (resource.isCacheable()) {
        r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
      }
      return r;
    }
  }
  void schedule(Project.NameKey project, String ref, URIish uri, ReplicationState state) {
    repLog.info("scheduling replication {}:{} => {}", project, ref, uri);
    if (!shouldReplicate(project, ref, state)) {
      return;
    }

    if (!config.replicatePermissions()) {
      PushOne e;
      synchronized (stateLock) {
        e = pending.get(uri);
      }
      if (e == null) {
        try (Repository git = gitManager.openRepository(project)) {
          try {
            Ref head = git.exactRef(Constants.HEAD);
            if (head != null
                && head.isSymbolic()
                && RefNames.REFS_CONFIG.equals(head.getLeaf().getName())) {
              return;
            }
          } catch (IOException err) {
            stateLog.error(String.format("cannot check type of project %s", project), err, state);
            return;
          }
        } catch (IOException err) {
          stateLog.error(String.format("source project %s not available", project), err, state);
          return;
        }
      }
    }

    synchronized (stateLock) {
      PushOne e = pending.get(uri);
      if (e == null) {
        e = opFactory.create(project, uri);
        pool.schedule(e, config.getDelay(), TimeUnit.SECONDS);
        pending.put(uri, e);
      }
      e.addRef(ref);
      state.increasePushTaskCount(project.get(), ref);
      e.addState(ref, state);
      repLog.info("scheduled {}:{} => {} to run after {}s", project, ref, e, config.getDelay());
    }
  }
Example #8
0
  @Override
  protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    String keyStr = req.getPathInfo();

    // We shouldn't have to do this extra decode pass, but somehow we
    // are now receiving our "^1" suffix as "%5E1", which confuses us
    // downstream. Other times we get our embedded "," as "%2C", which
    // is equally bad. And yet when these happen a "%2F" is left as-is,
    // rather than escaped as "%252F", which makes me feel really really
    // uncomfortable with a blind decode right here.
    //
    keyStr = URLDecoder.decode(keyStr, "UTF-8");

    if (!keyStr.startsWith("/")) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }
    keyStr = keyStr.substring(1);

    final Patch.Key patchKey;
    final int side;
    {
      final int c = keyStr.lastIndexOf('^');
      if (c == 0) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      if (c < 0) {
        side = 0;

      } else {
        try {
          side = Integer.parseInt(keyStr.substring(c + 1));
          keyStr = keyStr.substring(0, c);
        } catch (NumberFormatException e) {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }
      }

      try {
        patchKey = Patch.Key.parse(keyStr);
      } catch (NumberFormatException e) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    }

    final Change.Id changeId = patchKey.getParentKey().getParentKey();
    final Project project;
    final PatchSet patchSet;
    try {
      final ReviewDb db = requestDb.get();
      final ChangeControl control = changeControl.validateFor(changeId);

      project = control.getProject();
      patchSet = db.patchSets().get(patchKey.getParentKey());
      if (patchSet == null) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    } catch (NoSuchChangeException e) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    } catch (OrmException e) {
      getServletContext().log("Cannot query database", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    }

    final Repository repo;
    try {
      repo = repoManager.openRepository(project.getNameKey());
    } catch (RepositoryNotFoundException e) {
      getServletContext().log("Cannot open repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    }

    final ObjectLoader blobLoader;
    final RevCommit fromCommit;
    final String suffix;
    final String path = patchKey.getFileName();
    try {
      final ObjectReader reader = repo.newObjectReader();
      try {
        final RevWalk rw = new RevWalk(reader);
        final RevCommit c;
        final TreeWalk tw;

        c = rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get()));
        if (side == 0) {
          fromCommit = c;
          suffix = "new";

        } else if (1 <= side && side - 1 < c.getParentCount()) {
          fromCommit = rw.parseCommit(c.getParent(side - 1));
          if (c.getParentCount() == 1) {
            suffix = "old";
          } else {
            suffix = "old" + side;
          }

        } else {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }

        tw = TreeWalk.forPath(reader, path, fromCommit.getTree());
        if (tw == null) {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }

        if (tw.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) {
          blobLoader = reader.open(tw.getObjectId(0), Constants.OBJ_BLOB);

        } else {
          rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
          return;
        }
      } finally {
        reader.release();
      }
    } catch (IOException e) {
      getServletContext().log("Cannot read repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    } catch (RuntimeException e) {
      getServletContext().log("Cannot read repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    } finally {
      repo.close();
    }

    final byte[] raw = blobLoader.isLarge() ? null : blobLoader.getCachedBytes();
    final long when = fromCommit.getCommitTime() * 1000L;

    rsp.setDateHeader("Last-Modified", when);
    rsp.setDateHeader("Expires", 0L);
    rsp.setHeader("Pragma", "no-cache");
    rsp.setHeader("Cache-Control", "no-cache, must-revalidate");

    OutputStream out;
    ZipOutputStream zo;

    final MimeType contentType = registry.getMimeType(path, raw);
    if (!registry.isSafeInline(contentType)) {
      // The content may not be safe to transmit inline, as a browser might
      // interpret it as HTML or JavaScript hosted by this site. Such code
      // might then run in the site's security domain, and may be able to use
      // the user's cookies to perform unauthorized actions.
      //
      // Usually, wrapping the content into a ZIP file forces the browser to
      // save the content to the local system instead.
      //

      rsp.setContentType(ZIP.toString());
      rsp.setHeader(
          "Content-Disposition",
          "attachment; filename=\"" + safeFileName(path, suffix) + ".zip" + "\"");

      zo = new ZipOutputStream(rsp.getOutputStream());

      final ZipEntry e = new ZipEntry(safeFileName(path, rand(req, suffix)));
      e.setComment(fromCommit.name() + ":" + path);
      e.setSize(blobLoader.getSize());
      e.setTime(when);
      zo.putNextEntry(e);
      out = zo;

    } else {
      rsp.setContentType(contentType.toString());
      rsp.setHeader("Content-Length", "" + blobLoader.getSize());

      out = rsp.getOutputStream();
      zo = null;
    }

    if (raw != null) {
      out.write(raw);
    } else {
      blobLoader.copyTo(out);
    }

    if (zo != null) {
      zo.closeEntry();
    }
    out.close();
  }
Example #9
0
  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
    Repository git;
    try {
      git = mgr.openRepository(allProjects);
    } catch (IOException e) {
      throw new OrmException(e);
    }
    try {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
      ProjectConfig config = ProjectConfig.read(md);
      Map<Integer, ContributorAgreement> agreements = getAgreementToAdd(db, config);
      if (agreements.isEmpty()) {
        return;
      }
      ui.message("Moved contributor agreements to project.config");

      // Create the auto verify groups.
      List<AccountGroup.UUID> adminGroupUUIDs = getAdministrateServerGroups(db, config);
      for (ContributorAgreement agreement : agreements.values()) {
        if (agreement.getAutoVerify() != null) {
          getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
        }
      }

      // Scan AccountAgreement
      long minTime = addAccountAgreements(db, config, adminGroupUUIDs, agreements);

      ProjectConfig base = ProjectConfig.read(md, null);
      for (ContributorAgreement agreement : agreements.values()) {
        base.replace(agreement);
      }
      base.getAccountsSection()
          .setSameGroupVisibility(config.getAccountsSection().getSameGroupVisibility());

      BatchMetaDataUpdate batch = base.openUpdate(md);
      try {
        // Scan AccountGroupAgreement
        List<AccountGroupAgreement> groupAgreements = getAccountGroupAgreements(db, agreements);

        // Find the earliest change
        for (AccountGroupAgreement aga : groupAgreements) {
          minTime = Math.min(minTime, aga.getTime());
        }
        minTime -= 60 * 1000; // 1 Minute

        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(new PersonIdent(serverUser, new Date(minTime)));
        commit.setCommitter(new PersonIdent(serverUser, new Date(minTime)));
        commit.setMessage(
            "Add the ContributorAgreements for upgrade to Gerrit Code Review schema 65\n");
        batch.write(commit);

        for (AccountGroupAgreement aga : groupAgreements) {
          AccountGroup group = db.accountGroups().get(aga.groupId);
          if (group == null) {
            continue;
          }

          ContributorAgreement agreement = agreements.get(aga.claId);
          agreement.getAccepted().add(new PermissionRule(config.resolve(group)));
          base.replace(agreement);

          PersonIdent ident = null;
          if (aga.reviewedBy != null) {
            Account ua = db.accounts().get(aga.reviewedBy);
            if (ua != null) {
              String name = ua.getFullName();
              String email = ua.getPreferredEmail();

              if (email == null || email.isEmpty()) {
                // No preferred email is configured. Use a generic identity so we
                // don't leak an address the user may have given us, but doesn't
                // necessarily want to publish through Git records.
                //
                String user = ua.getUserName();
                if (user == null || user.isEmpty()) {
                  user = "******" + ua.getId().toString();
                }

                String host = SystemReader.getInstance().getHostname();
                email = user + "@" + host;
              }

              if (name == null || name.isEmpty()) {
                final int at = email.indexOf('@');
                if (0 < at) {
                  name = email.substring(0, at);
                } else {
                  name = anonymousCowardName;
                }
              }

              ident = new PersonIdent(name, email, new Date(aga.getTime()), TimeZone.getDefault());
            }
          }
          if (ident == null) {
            ident = new PersonIdent(serverUser, new Date(aga.getTime()));
          }

          // Build the commits such that it keeps track of the date added and
          // who added it.
          commit = new CommitBuilder();
          commit.setAuthor(ident);
          commit.setCommitter(new PersonIdent(serverUser, new Date(aga.getTime())));

          String msg =
              String.format(
                  "Accept %s contributor agreement for %s\n", agreement.getName(), group.getName());
          if (!Strings.isNullOrEmpty(aga.reviewComments)) {
            msg += "\n" + aga.reviewComments + "\n";
          }
          commit.setMessage(msg);
          batch.write(commit);
        }

        // Merge the agreements with the other data in project.config.
        commit = new CommitBuilder();
        commit.setAuthor(serverUser);
        commit.setCommitter(serverUser);
        commit.setMessage("Upgrade to Gerrit Code Review schema 65\n");
        commit.addParentId(config.getRevision());
        batch.write(config, commit);

        // Save the the final metadata.
        batch.commitAt(config.getRevision());
      } finally {
        batch.close();
      }
    } catch (IOException e) {
      throw new OrmException(e);
    } catch (ConfigInvalidException e) {
      throw new OrmException(e);
    } finally {
      git.close();
    }
  }
Example #10
0
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    handleAuth(req);
    resp.setCharacterEncoding("UTF-8");
    final PrintWriter out = resp.getWriter();
    try {
      String pathInfo = req.getPathInfo();
      Pattern pattern = Pattern.compile("/([^/]*)(?:/([^/]*)(?:/(.*))?)?");
      Matcher matcher = pattern.matcher(pathInfo);
      matcher.matches();
      String projectName = null;
      String refName = null;
      String filePath = null;
      if (matcher.groupCount() > 0) {
        projectName = matcher.group(1);
        refName = matcher.group(2);
        filePath = matcher.group(3);
        if (projectName == null || projectName.equals("")) {
          projectName = null;
        } else {
          projectName = java.net.URLDecoder.decode(projectName, "UTF-8");
        }
        if (refName == null || refName.equals("")) {
          refName = null;
        } else {
          refName = java.net.URLDecoder.decode(refName, "UTF-8");
        }
        if (filePath == null || filePath.equals("")) {
          filePath = null;
        } else {
          filePath = java.net.URLDecoder.decode(filePath, "UTF-8");
        }
      }
      if (projectName != null) {
        if (filePath == null) filePath = "";
        NameKey projName = NameKey.parse(projectName);

        ProjectControl control;
        try {
          control = projControlFactory.controlFor(projName);
          if (!control.isVisible()) {
            log.debug("Project not visible!");
            resp.sendError(
                HttpServletResponse.SC_UNAUTHORIZED,
                "You need to be logged in to see private projects");
            return;
          }
        } catch (NoSuchProjectException e1) {
        }
        Repository repo = repoManager.openRepository(projName);
        if (refName == null) {
          JSONArray contents = new JSONArray();
          List<Ref> call;
          try {
            call = new Git(repo).branchList().call();
            Git git = new Git(repo);
            for (Ref ref : call) {
              JSONObject jsonObject = new JSONObject();
              try {
                jsonObject.put("name", ref.getName());
                jsonObject.put("type", "ref");
                jsonObject.put("size", "0");
                jsonObject.put("path", "");
                jsonObject.put("project", projectName);
                jsonObject.put("ref", ref.getName());
                lastCommit(git, null, ref.getObjectId(), jsonObject);
              } catch (JSONException e) {
              }
              contents.put(jsonObject);
            }
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "W/\"" + response.length() + "-" + response.hashCode() + "\"");
            log.debug(response);
            out.write(response);
          } catch (GitAPIException e) {
          }
        } else {
          Ref head = repo.getRef(refName);
          if (head == null) {
            JSONArray contents = new JSONArray();
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "W/\"" + response.length() + "-" + response.hashCode() + "\"");
            log.debug(response);
            out.write(response);
            return;
          }
          RevWalk walk = new RevWalk(repo);
          // add try catch to catch failures
          Git git = new Git(repo);
          RevCommit commit = walk.parseCommit(head.getObjectId());
          RevTree tree = commit.getTree();
          TreeWalk treeWalk = new TreeWalk(repo);
          treeWalk.addTree(tree);
          treeWalk.setRecursive(false);
          if (!filePath.equals("")) {
            PathFilter pathFilter = PathFilter.create(filePath);
            treeWalk.setFilter(pathFilter);
          }
          if (!treeWalk.next()) {
            CanonicalTreeParser canonicalTreeParser =
                treeWalk.getTree(0, CanonicalTreeParser.class);
            JSONArray contents = new JSONArray();
            if (canonicalTreeParser != null) {
              while (!canonicalTreeParser.eof()) {
                String path = canonicalTreeParser.getEntryPathString();
                FileMode mode = canonicalTreeParser.getEntryFileMode();
                listEntry(
                    path,
                    mode.equals(FileMode.TREE) ? "dir" : "file",
                    "0",
                    path,
                    projectName,
                    head.getName(),
                    git,
                    contents);
                canonicalTreeParser.next();
              }
            }
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "\"" + tree.getId().getName() + "\"");
            log.debug(response);
            out.write(response);
          } else {
            // if (treeWalk.isSubtree()) {
            // treeWalk.enterSubtree();
            // }

            JSONArray contents = getListEntries(treeWalk, repo, git, head, filePath, projectName);
            String response = contents.toString();

            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "\"" + tree.getId().getName() + "\"");
            log.debug(response);
            out.write(response);
          }
          walk.release();
          treeWalk.release();
        }
      }
    } catch (RepositoryNotFoundException e) {
      handleException(resp, e, 400);
    } catch (MissingObjectException e) {
      // example "Missing unknown 7035305927ca125757ecd8407e608f6dcf0bd8a5"
      // usually indicative of being unable to locate a commit from a submodule
      log.error(e.getMessage(), e);
      String msg =
          e.getMessage()
              + ".  This exception could have been caused by the use of a git submodule, "
              + "which is currently not supported by the repository browser.";
      handleException(resp, new Exception(msg), 501);
    } catch (IOException e) {
      handleException(resp, e, 500);
    } finally {
      out.close();
    }
  }