# Mercurial projects in Heptapod

The primary objective of Heptapod is to add Mercurial support to GitLab.

## Version Control System (VCS) types

Each project has a `vcs_type` field to describe the VCS in use. Administrators
can select which of these are allowed in the application settings
(Admin Area > Settings > General > Visibility and access controls).


We are currently using two distinct VCS types for Mercurial projects, to support our
effort towards "native" handling of Mercurial.

### Mercurial VCS type

Value of the `vcs_type` field: `hg_git`.


This is the historical way to handle Mercurial repositories, exposing to the rest of
GitLab by maintaining a conversion to Git. Even though the server side Mercurial
repository is the single source of truth, this has many drawbacks.

The Rails (web) application accesses content for display through Gitaly, but also needs
to perform operations (such as merges) on the local file system. Hence the Gitaly server
*must* be local.

This does not prevent using also remote Gitaly servers, as long as they serve Git
projects only.

### Mercurial (native) VCS type

Value of the `vcs_type` field: `hg`.

Still experimental as of Heptapod 0.21, these are meant to eventually replace the `hg_git`
projects. Projects created right now under this mode should not need heavy and risky migrations
in the future.

The native Mercurial projects are exposed to the various GitLab components via the HGitaly
service. Although content is still converted to Git at this point, the auxiliary Git repository
will eventually become completely superfluous and fade away.

There are three stages of development:

+ HGitaly1: references and commits are served via HGitaly, but files and directories are still read
  from the Git repository. This is the norm as of Heptapod 0.21
+ HGitaly2 (fully native, currently under evaluation via feature flags): All Mercurial content is
  served via HGitaly. The auxiliary Git repository is useful only to be able to get back to the
  HGitaly1 stage
+ HGitaly3 (development not started): all read and write operations, including creation and
  maintenance tasks happen through HGitaly. The web application does not need to access
  the repositories directly, and the HGitaly servers can be remote.

More insight on these different ways to handle Mercurial is avalaible
[on the Heptapod web site](https://heptapod.net/the-road-to-fully-native-mercurial-in-heptapod.md#the-road-to-fully-native-mercurial-in-heptapod)


## Managing the fully native mode

Warning: as of Heptapod 0.21, this is highly experimental, but you can get back to
the HGitaly1 stage easily.

In all cases, only native Mercurial projects are affected by this.

#### The feature flags

- `hg_fully_native`: switches on the fully native mode
- `hgitaly1_fallback`: make a given project still use the HGitaly1 mode, even
  if the whole instance is using the fully native mode

#### For the whole instance

To have all "Mercurial (native)" projects use the fully native mode, do this under the
[Rails console]

```ruby
Feature.enable(:hg_fully_native)
```

To get back to the HGitaly1 mode of operation:

```ruby
Feature.disable(:hg_fully_native)
```

It is not possible to use `disable()` for a single project. To exclude a given project
from the fully native mode, do:

```ruby
project = Project.find(project_id)  # project_id is the numeric ID,
Feature.enable(:hgitaly1_fallback, project)
```

Of course, you are free to use other means to retrieve a `Project` instance, using
the `ActiveRecord` API (the Object Relational Mapping in use).

#### For a given project

##### Introspection

To know whether a given project is running under the fully native mode, retrieve its
details using the [Projects API](../api/projects.md).

- if `vcs_type` is `hg` and `hgitaly1` is `false`, the project is running under the fully
native mode.
- if `hgitaly1` is `true`, the project is running the HGitaly1 mode of operation
- if `vcs_type` is not `hg`, this is not a native Mercurial repository, the value of
  `hgitaly1` is meaningless.

##### Using the Rest API

This is perhaps the simplest. Use the [Features flags API](../api/features.md#set-or-create-a-feature)
with this data:

- `name`: `hg_fully_native`
- `value`: `true` or `false` whether you want to enable or disable
- `project`: full web path to the project

Note: disabling the fully native mode this way does not work if it is enabled for the
whole instance. Enable the `hgitaly1_fallback` feature flag instead.


##### Under the [Rails console]:

```ruby
project = Project.find(project_id)  # project_id is the numeric ID,
Feature.enable(:hg_fully_native, project)
```

This has no impact on non-native Mercurial projects nor on Git projects either

To get back to HGitaly1 mode of operation (assuming the feature flag is not
activated for the whole instance):

```ruby
project = Project.find(project_id)  # project_id is the numeric ID,
Feature.disable(:hg_fully_native, project)
```



[Rails console]: operations/rails_console.md




