1. 18 Nov, 2020 2 commits
  2. 17 Nov, 2020 2 commits
  3. 16 Nov, 2020 1 commit
    • Georges Racinet's avatar
      Branch acces checks: direct identification of legit merges · 948dac54b949
      Georges Racinet authored
      Closes #368
      To let merges done from the Rails application be checked
      against the distinct set of merge rules rather that push
      rules, GitLab looks for MRs matching the pre-receive changes by
      comparing with the merge commit sha that's always available
      (and set by the Repository Model) before the actual branch move.
      Because the Mercurial change can be atomic, we have no other
      option than passing a special parameter down from
      `Repository#merge` through the Mercurial backend, with the
      `HEPTAPOD_ACCEPT_MERGE_ID` environment variable.
      In turn the Mercurial process will add it to its pre-receive
      hook payload, and the target branch can be compared to switch
      from (direct) push to (Rails) merge mode.
      In the case of merges intended from the very beginning to be
      fast forwards, the commit sha is already known in advance,
      but we're using the same mechanism for consistency in the
      Finally, there was a good dose of wrestling with those RSpec
      examples that care about merging to a protected branch, because
      of the on-demand nature of instantiation.
      branch : heptapod-stable
  4. 15 Nov, 2020 1 commit
  5. 07 Nov, 2020 1 commit
    • Georges Racinet's avatar
      gitaly_client: plugging in HGitaly in CommitService · d3f9a208d676
      Georges Racinet authored
      This is more complicated than what we've done earlier for
      - Upstream passes down storage to `GitalyClient.call` as
        `@repository.storage`. We don't want to change all methods
        of CommitService because it wouldn't apply readily to new
        methods from upstream.
        Hence we actually re-instantiate `@repository`,
        with the VCS-qualified storage, with the new `vcs_storage_clone`
        method. On the side, this also requires a small change
        in HgGitRepository to make the value admissible.
      - only a subset of Commit service methods are actually involved
        in our first round of HGitaly implementation (getting rid of
        Git SHAs, see HGitaly1 milestone). We're deciding here that
        the other methods will use directly the original storage name,
        that we store as a new instance variable, `@git_storage`.
        In particular, we're trying to avoid the implementation of the
        various methods for Commit content (files, trees, diffs…) for
        the HGitaly1 milestone. This part is WIP (we'll need to
        convert back to Git revisions to complete it).
      - Finally, this hack also requires to make sure that the resulting
        Commit instances refer to the original Repository, so that further
        (H)Gitaly calls done from these Commits don't reuse a VCS-qualified
        storage, which would defeat the very purpose of separation.
      This is all very hacky. The only thing that makes it admissible is
      that it is temporary scaffolding. For the HGitaly2 milestone, all
      methods will go to HGitaly, and perhaps we can convince upstream to
      use a `@storage` instance variable here for the sake of uniformity.
      branch : heptapod
  6. 25 Oct, 2020 2 commits
    • Georges Racinet on mutations.racinet.fr's avatar
      Commit: introducing hpd_display_id · b10c60a26265
      In some cases it makes sense to display a different commit ID than the
      one used for addressing. Of course our existing `HgGitRepository` is
      a prime example of that, but it's not hard to imagine other ones.
      Up to now, we've changed some templates and user-facing to code to
      use directly some 'hgid'. For dual VCS support, as well as intermediate
      steps towards Mercurial native support, we'll need something more
      abstract than that.
      The method name, `hpd_display_id`, is voluntary obnoxious: we want
      to recognize at first glance that it's Heptapod-specific, and we want
      it to be easy to find all occurrences in the code base, in preparation
      for potential future times when we won't be needing it any more.
      branch : heptapod
    • Georges Racinet on mutations.racinet.fr's avatar
      archive_sha: tests for Git::Repository and Mercurial::HgGitRepository · ab8bb59acad1
      We're also using the `override` helper, which makes sure that there
      is a method with the same name to be overridden, hence providing
      protection in the case of renames in the base class.
      We don't provide tests in the HGitalyRepository case in this commit:
      this will be the point of the next one.
      branch : heptapod
  7. 19 Oct, 2020 9 commits
  8. 18 Oct, 2020 1 commit
    • Georges Racinet's avatar
      HgGitRepository#hg_pull · 667641b1a538
      Georges Racinet authored
      This will be an interesting low-level helper, being exposed
      on the `Repository` model automatically, like all "raw"
      repository methods.
      Like all write methods, a valid `user` argument must be passed.
      branch : heptapod
  9. 14 Oct, 2020 1 commit
    • Georges Racinet's avatar
      Repository archives: dispatching to HGitaly for Mercurial repos · 2e2da0334c73
      Georges Racinet authored
      For archive production, the Rails app duty is to return
      direct connection information to Workhorse, so that it can call
      Gitaly directly.
      We're reusing the dispatching logic for our existing (yet unplugged)
      HGitaly integration: by prefixing the storage (shard) with `hg:` for
      Mercurial repositories, we have the `GitalyClient.address` return
      connection information for the HGitaly server.
      For this to work, we need `archive_metadata` method of the
      Mercurial Repository classes to provide the Mercurial SHA, which we do
      by intoducing the dedicated `archive_sha` method.
      branch : heptapod
  10. 09 Oct, 2020 1 commit
    • Georges Racinet's avatar
      HgGitRepository: low level hg_tag method · 74b64d425d85
      Georges Racinet authored
      This is for now mostly intended as a helper for tests.
      We're using one of the HGitaly tags test to make sure it works,
      and in turn that test gets simplified.
      There's a catch: `hg_git_repository.hg_tag` would not
      work before `subject` has been used at least once, so that the
      repository is indeed initialized on disk.
      If we were in need to use `hg_git_repository` here, we'd have
      to switch to `subject!` instead of just `subject`.
      branch : heptapod
  11. 24 Sep, 2020 2 commits
  12. 10 Sep, 2020 1 commit
    • Georges Racinet's avatar
      Markdown renderings: lookup for Mercurial short nodes · 31146d7c450d
      Georges Racinet authored
      The `CommitReferenceFilter` class is the one responsible for
      the rendering.
      We're *adding* resolution of truncated Mercurial Node ids for
      the case of the `hg_git` VCS type, relying on the existing
      map of full Mercurial SHA (Node id) to Git SHA.
      This is very inefficient, and proper calls with low startup
      overhead to a persistent Mercurial nodemap would do much better
      above a certain repository size (persistent nodemap is provided
      by Rust native extensions, and low overhead would be achieved only
      by a fastpath without Python or a long-running process, such as
      While the `Git::Commit.batch_by_oid` method
      doesn't seem to be called except from the `#commits_by` method of the
      `Repository` model, the latter is used in several places
      of the application, with risks of breakage and/or severe performance
      degradation. For `hg_git` VCS type, most callers don't need the Mercurial
      resolution. That's why we're executing the new lookup only if
      the new `hg_full_resolution` argument is set to `true`.
      Preliminary performance analysis (non scientific, on my workstation)
      shows that in the 100k changesets range (pypy repo) this naive lookup takes
      about 30ms, whereas `hg log -T` is in the 100-200ms ballpark.
      Around 500k changesets (mozilla-central repo), times have the same order
      of magnitude (around 100-200ms again). To insist, this is with the hg startup
      overhead and without the Rust persistent nodemap (would take less than 1ms).
      We fully expect the current hg<->git maps to be an unbereable performance
      problem in Heptapod anyway around 500k to 1M changesets anyway, only solved
      by HGitaly.
      All in all, the performance question seems to be acceptable in the current
      inefficient context *for Note rendering*.
      HGitaly would provide an efficient RPC call anyway.
      branch : heptapod-stable
  13. 27 Aug, 2020 3 commits
    • Georges Racinet's avatar
      Forwarding actual permissions to Mercurial processes · 4c45dfe84231
      Georges Racinet authored
      Closes #334
      Normally, the abstraction layers in GitLab mean that the Project
      should not be accessible from the low level repository. However,
      we need it to pass it down to the `hg` processes. Doing it in
      `hg_env_for_write` is the way to make it really robust, since all
      write operations basically have to use it.
      To mitigate somewhat this breach of abstraction, we make the
      attribute writable only, and we give it a more specific name than
      just '@project'. Aesthetically, it would be better to store only
      a factory for the `UserAccess` instance that we really need, but
      that could be done separately.
      This required running some of `HgAccess` RSpec tests with empty
      repositories, because in them, the project owner does not have enough
      rights to create a first commit any more, and there's not even
      an admin user around for that.
      branch : heptapod
    • Georges Racinet's avatar
      HgGitRepository: removed duplication · 4fb9222b604b
      Georges Racinet authored
      We still have a deprecated compatibility alias, and the
      rebase tests prove that it works.
      branch : heptapod
    • Georges Racinet on mutations.racinet.fr's avatar
      HgGitRepository: attribute to skip Git hooks for tests · db821ec4ea3f
      This new attribute is not meant to be used in any other context
      than RSpec tests, whence the name. It allows us to use higher
      level methods such as `multi_action` in tests setups and will be
      necessary to test them.
      Upstream does something similar with no need to involve the tested code:
      they launch Gitaly server with the `GITALY_TESTING_NO_GIT_HOOKS` environment
      branch : heptapod
  14. 26 Aug, 2020 2 commits
  15. 24 Aug, 2020 2 commits
    • Georges Racinet's avatar
      Repository files (multi_action): check publisher permission · e029134a44f0
      Georges Racinet authored
      This is a variant of #332 for multi_action.
      As with the case of merge requests, the check should also be
      performed at low level by Mercurial, but doing it at the model
      level makes for early failure, avoiding atomicity issues.
      A difference with MRs is that we don't have a simple way *not* to
      propose the action to the user yet, because higher layers are more
      complicated and don't involve checks, since they are meant to produce
      forks for users without write permission.
      This currently provides 500 errors, but at least it closes the
      security problem, and we can later on add the necessary catching.
      We didn't want to affect Wikis, because for them, allowing publication
      for Developers is pretty normal.
      branch : heptapod-stable
    • Georges Racinet's avatar
      HgGitRepository: split out hg_config_item_bool? method · ff5823e89d14
      Georges Racinet authored
      This is just cleaner and prone to reuse.
      branch : heptapod-stable
  16. 03 Aug, 2020 1 commit
    • Georges Racinet's avatar
      Operations: port over HGRC files from main repo to share · db7ee4fbacad
      Georges Racinet authored
      Closes #324
      The specific repo configuration was ignored in all Mercurial
      operations initiated by the Rails app.
      I've considered making links instead of copying the file, but
      it could give rise to funny situations if the original HGRC
      files get changed in concurrency with some operation.
      Edition of the HGRC files is by no means atomic in itself,
      but that's a separate issue. On the other hand, operations can be
      arbitrary long, involving several calls to the `hg` executable.
      One would not want the rules to change in the middle of that.
      branch : heptapod
  17. 17 Jul, 2020 1 commit
  18. 16 Jul, 2020 4 commits
    • Georges Racinet's avatar
      HgGitRepository#get_hg_heptapod_config can ignore global conf · 05ed90b0af75
      Georges Racinet authored
      This will be useful for an incremental approach of configuration
      setting, and spares us INI format parsing in Ruby (GitLab does not
      come with a gem for this).
      branch : heptapod-stable
    • Georges Racinet's avatar
      HgGitRepository: make get_hg_heptapod_config work if empty · e70d3a5eb8d7
      Georges Racinet authored
      Because `hg config SECTION` exits with code 1 if no matching
      setting have been found, we previously had an error if this
      method (and the corresponding API endpoint) was called before
      any local setting is set in the `[heptapod]` section.
      This can be considered part of #299, too
      Also fixed the exception raising, Ruby has its quirks, not the
      same as Python's.
      branch : heptapod-stable
    • Georges Racinet's avatar
      HgGitRepository: don't crash if no managed hgrc exists yet · c23adf095138
      Georges Racinet authored
      Closes #299
      We'll return content to be `nil` in that case, which will be
      conveyed as `null` in the JSON API.
      branch : heptapod-stable
    • Georges Racinet's avatar
      HgGitRepository: taking Mercurial repo size into account · 2d5d3aff9555
      Georges Racinet authored
      Closes #314
      Previously only the Git repository was considered.
      Note that this is cached in the `projects_statistics` table,
      and can be invalidated by doing
      This seems in turn to be triggered by `UpdateProjectStatisticsWorker`,
      iself called by `ProjectCacheWorker`, from the likes of `PostReceiveWorker`
      branch : heptapod-stable
  19. 14 Jun, 2020 2 commits
    • Georges Racinet's avatar
      Post-receives for repository files and merges with changeset · 376d59c06826
      Georges Racinet authored
      Post-receive notificiations are necessary to trigger pipelines and
      other post branch update actions that must be taken on the GitLab
      Previously, we enabled them in merges with changeset performed by the
      Rails app itself, but we had only the publication step send them
      to avoid unnecessary consequences like redundant pipelines, but that
      was wrong: if there's already an added commit on `branch/default`
      a publication doesn't trigger any change on `branch/default`. The
      only post-receive it can send is a topic branch prune.
      branch : heptapod-stable
    • Georges Racinet's avatar
      Passing vcs_type to GitlabShellWorker and fixing repo removal · 1f9e56d13b01
      Georges Racinet authored
      Because sidekiq workers don't seem to take named arguments, we
      pass it as the last required positional one and convert it to
      named argument in the actual call to `Gitlab::Shell`.
      Then it was simpler just to let `Gitlab::Shell#rm_namespace`, the
      only method not taking a `vcs_type` named arg to accept it for
      All call sites for GitlabShellWorker are updated. There aren't so
      many, due to the general deprecation of `Gitlab::Shell`, also a
      reason not to worry about new callers appearing in future versions.
      Finally, the `remove` method wasn't even implemented in
      branch : heptapod
  20. 08 Jun, 2020 1 commit