Este guia mostrará como o Mercurial pode ser usado para conversar com repositórios remotos usando HTTP e SSH.
Contents
In the Basic Mercurial guide, you saw how Alice and Bob could push and pull between each other on the same filesystem. This is a fine setup when Alice and Bob share a filesystem between them, but most users don’t have direct access to each other’s files like that. This is why Mercurial can access remote repositories over a network connection.
O Mercurial fala dois protocolos de rede:
HTTP: o protocolo usado por servidores web normais.
Mercurial vem com um pequeno servidor web embutido que você pode iniciar através do comando hg serve e que permite que você naveque pelo histórico do repositório com um browser. Para um uso mais pesado, o script hgweb.cgi é recomendado.
SSH: Secure Shell Protocol, usado nos sistemas Unix.
If you already have SSH login on a server with Mercurial installed, then using SSH is the easiest way to clone a repository. It is possible to setup an account with a restricted login shell so that users can only execute Mercurial-related commands do not get a full login shell, see the hg-ssh script for details.
Começaremos olhando como você pode interagir com repositórios sobre HTTP. Este protocolo é muito popular já que se integra bem com a maioria das infraestruturas das empresas: quando você tem um servidor web funcional que pode ser acessado pela porta 80, então você tem tudo o que precisa para servir os repositórios do Mercurial também.
Alice clona um repositório que contém um pequeno exemplo:
alice$ hg clone https://bitbucket.org/aragost/hello destination directory: hello requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Como você pode ver, não é realmente diferente de clonar um repositório a partir de um caminho no sistema de arquivos: em ambos os casos, Alice acaba com uma cópia completa do repositório e o ramo default é escolhido.
Internamente, o Mercurial é capaz de fazer uma clonagem local muito mais eficiente que uma clonagem pelo HTTP. Isto não é apenas pelo fato de que ler dados pela rede é mais lento que ler de um disco, mas também porque um clone local pode reusar o espaço do diretório .hg através de hardlinks entre os arquivos. Os dois clones compartilharão o espaço de disco usado pelos dois diretórios .hg e apenas as cópias de trabalho que tomam novo espaço em disco. Isto é o que torna possível criar tantas cópias locais descartáveis quanto se queira.
Alice pode fazer suas consolidações no seu clone:
alice$ cd hello alice$ echo "Hello, World!" > hello.txt alice$ hg commit -m "Add comma"
This is the essence of distributed revision control — Alice can get her own independent copy of the repository and work on it locally. She can compare her clone with the remote server:
alice$ hg outgoing comparing with https://bitbucket.org/aragost/hello searching for changes changeset: 1:61c1daa1d929 tag: tip user: Alice <alice@example.net> date: Sat Jan 22 10:00:00 2011 +0000 summary: Add comma
Ela não pode empurrar seu changeset para o servidor pois não tem permissão de escrita para este repositório.
Como mencionado antes, o Mercurial tem um servidor web embutido. Você pode usá-lo para um compartilhamento rápido de um repositório com outra máquina pela LAN, ou mesmo para navegar pelo histórico você mesmo.
Alice disponibiliza seu clone do repositório hello:
alice$ hg serve listening at http://localhost:8000/ (bound to 127.0.0.1:8000)
O repositório pode ser navegado com um browser normal a partir do endereço http://localhost:8000/. Lá, pode-se ver o histórico do projeto e o grafo de changesets. Pode-se examinar changesets individuais, ver a lista de rótulos e ramos, anotações dos arquivos e pode-se recuperar qualquer revisão na forma de um arquivo tar ou zip. Em outras palavras, o servidor web embutido é bastante conveniente para humanos, tanto quanto para computadores :-)
Bob pode fazer um clone do repositório de Alice:
bob$ hg clone http://localhost:$HGPORT hello requesting all changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 1 files updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved bob$ cd hello bob$ cat hello.txt Hello, World!
Se Bob fizer uma mudança e tentar empurrar de volta, ele encontra o seguinte erro:
bob$ hg push pushing to http://localhost:8000/ searching for changes remote: ssl required remote: ssl required updating 61c1daa1d929 to public failed!
O que acontece é que o webserver do Mercurial não deixa você empurrar sobre HTTP por padrão. Ele precisa que você use uma URL em HTTPS. Alice pode desabilitar esta exigência através da opção --config web.push_ssl=No pela linha de comando quando ela inicia o servidor embutido. Ela primeiro interrompe o processo do hg serve antigo e então começa um novo:
alice$ hg serve --config web.push_ssl=No listening at http://localhost:8000/ (bound to 127.0.0.1:8000)
Quanto Bob tenta novamente, ele encontra um novo erro devido aos repositórios serem apenas para leitura por padrão:
bob$ hg push pushing to http://localhost:8000/ searching for changes abort: authorization failed
Note que a operação de push foi abortada sem dar a Bob a chance de fornecer o nome do usuário ou a senha. A razão disso é que o servidor web embutido não suporta autenticação. Isto é, não possui gerenciamento de usuários. Isto pode parecer estranho, mas a ideia é que você não executará hg serve em um ambiente de produção. Ao invés disso, você executaria o script hgweb.cgi fornecido com o Mercurial em um servidor web de verdade como o Apache. Este servidor web teria a infraestrutura necessária para fazer apropriadamente a autenticação de usuário. Uma vantagem dessa configuração é que você pode fazer a autenticação usando o método que preferir: se já tiver uma autenticação baseada em LDAP, então é possível reusar essa autenticação para o Mercurial também.
Para o nosso exemplo, vamos deixar Alice desabilitar a verificação de autenticação com uma outra opção de linha de comando:
alice$ hg serve --config web.push_ssl=No --config "web.allow_push=*" listening at http://localhost:8000/ (bound to 127.0.0.1:8000)
Bob agora consegue empurrar seu changeset para Alice:
bob$ hg push pushing to http://localhost:8000/ searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files
Aqui não há autenticação alguma, mas para a maior parte dos repositórios reais você terá de autenticar para empurrar seus changesets (e algumas vezes também para puxá-los). Vamos discutir o armazenamento de credenciais HTTP(S) abaixo.
Quando você acessa um repositório através do script hgweb.cgi, então o acesso é feito realmente pelo servidor web. O processo do servidor web executa como um certo usuário no servidor e este usuário deve ter acesso de leitura aos arquivos do repositório para que possa servi-los.
Quando as pessoas empurram changesets de volta pelo HTTP, também é o processo do servidor web que escreve os arquivos no diretório .hg. Os nomes de usuários embutidos nos changesets não tem nenhum significado aqui.
O outro protocolo de rede suportado pelo Mercurial é o SSH. Quando se usa URLs de SSH, o Mercurial se registra no servidor e estabelece um túnel SSH entre dois processos do Mercurial. Estes processos podem então comunicar um com o outro para empurrar ou puxar changesets.
Isto implica a necessidade de haver uma conta SSH no servidor. Muitos administradores de sistemas preferem, portanto, uma configuração baseada em HTTP ao invés porque ela já se adequa à configuração existente do servidor web.
Contudo, se você tiver uma conta no servidor e se o Mercurial está instalado no sistema, então o protocolo SSH é muito suave para o usuário. A única coisa que precisa ser lembrada é que a sintaxe é a de uma URL e não um caminho SSH como usado em scp ou rsync. Então, deve-se escrever:
$ hg clone ssh://server/caminho/para/repositorio
e não:
$ hg clone server:caminho/para/repositorio
Note também que caminho/para/repositório é relativo ao seu diretório de usuário no servidor. Se você quiser usar um caminho absoluto no servidor, então use uma URL como esta:
$ hg clone ssh://server//caminho/absoluto/para/repositorio
A primeira barra é parte da sintaxe de URL, a segunda é parte do caminho no servidor, de modo que a URL acima se refere a caminho/absoluto/para/repositorio no servidor.
Diferente de URLs com HTTP, você pode usar URL com SSH como alvo para hg clone. Isto permite que você faça:
$ hg clone . ssh://server/path/to/repository
para clonar o repositório atual para o servidor.
Como o Mercurial faz um login no servidor, é o usuário no servidor que precisa ter acesso à leitura aos arquivos do repositório para fazer um clone ou puxar changesets. Do mesmo modo, é o usuário no servidor que precisa ter acesso à escrita aos arquivos do repositório para empurrar changesets de volta.
Se acontecer algum erro na operação de empurrar mudanças pelo SSH, então adicione --debug ao comando para ver o que o Mercurial está fazendo. Tente logar pelo SSH com o mesmo usuário e verifique se você pode acessar os arquivos.
Durante a conversa, o servidor web pede ao Mercurial um nome de usuário e uma senha para autenticação. Será pedido que você forneça esta informação pelo prompt:
$ hg clone https://bitbucket.org/aragost/private http authorization required realm: Bitbucket.org HTTP user: aragost password: <secret> abort: http authorization required
Já que é necessário autenticar a cada comando que envolve o repositório remoto (isto é, comandos como hg clone, hg pull, hg push, hg incoming e hg outgoing), esse pedido se torna repetitivo e cansativo. Há várias maneiras de fazer o Mercurial salvar as credenciais. Vamos apresentá-las em ordem de preferência.
Tip
Você pode estar imaginando como fazer o Mercurial armazenar sua frase de segurança do SSH. A resposta é que não pode — a autenticação do SSH é externa ao Mercurial e você deve usar um agente SSH para armazenar a frase.
Um agente SSH é um programa que roda no plano de fundo e mantém uma versão descriptografada da sua chave privada do SSH na memória. Sempre que você precisa fazer uma conexão SSH, o ssh pergunta primeiro ao agente se ele tem uma chave descriptografada adequada. Se tiver, a conexão pode ser feita sem fornecer nenhuma senha, caso contrário o ssh pedirá a senha.
Você pode adicionar o agente SSH com o comando ssh-add no Linux e no Mac OS X e usar o Pageant quando usar o Putty no Windows.
In short:
Pros: passwords are stored in a OS-specific secure backend, most secure option.
Cons: requires third-party extension.
The keyring extension will hook into Mercurial and intercept password requests. The passwords you enter a then stored securely in an OS-specific password database and you won’t have to enter them again. It stores passwords used for HTTP(S) authentication and SMTP authentication (as done by the patchbomb extension among others).
Esta solução é a padrão para Windows quando se usa TortoiseHg, que já vem com tanto com a extensão quanto as bibliotecas extras necessárias para conversar com o Windows. Em outros sistemas, você precisará instalar instalar as bibliotecas extras por si mesmo.
In short:
Pros: standard feature in Mercurial. Makes it easy to setup the password used for all repositories on a given host.
Cons: passwords are stored in a plaintext configuration file. Care must be used if the file is shared with others.
You can save the credentials directly in your Mercurial configuration file. You do this with the auth section:
[auth] bb.prefix = https://bitbucket.org/ bb.username = alice bb.password = <secret>
A seção [auth] pode conter várias declarações, e essas declarações são agrupadas por uma chave arbitrária definida por você. Acima, foi usado bb como a chave para o BitBucket, mas poderia ter sido qualquer coisa. Se você tiver mais sites para os quais deseja armazenar a senha, então você deve usar diferentes chaves para cada host:
[auth] site-a.prefix = https://hg.site-a.net/ site-a.username = userA site-a.password = <secret-a> site-b.prefix = https://site-b.org/repos/ site-b.username = userB site-b.password = <secret-b>
In short:
Pros: requires no out-side configuration.
Cons: password is stored in plaintext.
Esta maneira tira vantagem da característica própria da especificação de URLs: é possível definir diretamente o nome do usuário e a senha nelas. A sintaxe é a seguinte:
scheme://username:password@domain:port/path
Você pode executar:
hg clone https://alice:<secret>@bitbucket.org/aragost/private
O Mercurial automaticamente usará alice como nome de usuário e <secret> como senha quando logar no Bitbucket. Se o clone for bem sucedido, então a URL inteira é armazenada como caminho padrão no arquivo .hg/hgrc. Como tanto o nome do usuário quanto a senha são armazenados na URL, invocações futuras de hg pull e hg push farão a autenticação automaticamente, sem pedir nada.
Quando você trabalha em muitos repositórios no mesmo endereço de hospedagem, então se torna chato digitar repetidamente:
hg clone https://hg.my-long-servername.com/repos/
Mercurial tem uma extensão padrão que ajuda encurtar essas URLs. Você pode habilitar a extensão schemes e pode adicioná-la ao seu arquivo de configuração:
[schemes] bb = https://bitbucket.org/
Isto permite que você escreva:
hg clone bb://aragost/private
ao invés da longa:
hg clone https://bitbucket.org/aragost/private
Veja hg help schemes depois de habilitar a extensão para a sintaxe completa.
Você pode usar a extensão schemes para encurtar URLs SSH também, mas é interessante notar que o OpenSSH tem seu próprio modo de encurtar URLs. Adicione estas linhas ao arquivo ~/.ssh/config (criando-o se for necessário):
Host bb Compression yes HostName bitbucket.org User hg
Isto permitirá escrever:
hg clone ssh://bb/aragost/private
ao invés de:
hg clone ssh://hg@bitbucket.org/aragost/private
Note como esta configuração define até mesmo o nome do usuário, algo particularmente fácil de esquecer quando se usa SSH com o Bitbucket. Nós também aproveitamos a oportunidade para habilitar a compressão pelo túnel SSH, que melhorará o desempenho geral.
Se você estiver usando o Putty no Windows (o TortoiseHg vem com o Putty instalado) então você pode fazer o mesmo configurando e salvando a conexão. Se você salvar a configuração sob o nome bb, então pode usar URLs no estilo ssh://bb/ com o Mercurial.
Vá para https://bitbucket.org/ e crie uma conta para si.
Crie um repositório particular chamado test e faça um clone para a sua máquina local.
Adicione a consolide um arquivo no repositório e empurre-o de volta ao Bitbucket.
Faça um clone de https://bitbucket.org/aragost/hello/ na sua máquina local.
Crie um novo repositório no Bitbucket chamado hello e empurre o clone hello da sua máquina para o Bitbucket.
Note que você pode empurrar changesets em um repositório vazio. Isto é porque você pode expandir um hg clone para um hg init seguido por um hg pull (exceto que você não terá os hardlinks descritos acima).
O que acontece se você tentar empurrar do seu clone hello para seu clone test no Bitbucket? Como o Mercurial sabe se os repositórios são relacionados?