5. Subversion Primer

Supõe-se que novos committers já estejam familiarizados com a operação básica do Subversion. Se não, comece lendo o Subversion Book.

5.1. Introdução

O repositório de código fonte do FreeBSD mudou do CVS para o Subversion em 31 de maio de 2008. O primeiro commit real no SVN é o r179447.

O repositório do FreeBSD doc/www foi migrado do CVS para o Subversion em 19 de Maio de 2012. O primeiro commit real no SVN foi o r38821.

O repositório da coleção de ports do FreeBSD foi migrado do CVS para o Subversion em 14 de Julho 2012. O primeiro commit real no SVN foi o r300894.

O Subversion pode ser instalado a partir da Coleção de Ports do FreeBSD, executando o comando:

# pkg install subversion

5.2. Primeiros Passos

Existem algumas maneiras de obter uma cópia de trabalho da árvore do Subversion. Esta seção irá explicá-las.

5.2.1. Checkout direto

O primeiro é fazer check-out diretamente do repositório principal. Para a árvore src, use:

% svn checkout svn+ssh://repo.freebsd.org/base/head /usr/src

Para a árvore doc, use:

% svn checkout svn+ssh://repo.freebsd.org/doc/head /usr/doc

Para a árvore da coleção de ports, use:

% svn checkout svn+ssh://repo.freebsd.org/ports/head /usr/ports

Nota:

Embora os exemplos restantes neste documento tenham sido escritos tendo o workflow de trabalho com a árvore src em mente, os conceitos básicos são os mesmos para se trabalhar com o doc e com a árvore dos ports. Os ports relacionados às operações do Subversion estão listados em Seção 20, “FAQ específico dos Ports”.

O comando acima irá fazer o checkout da árvore de código-fonte CURRENT como /usr/src/, o qual pode ser qualquer diretório de destino no sistema de arquivos local. Omitir o argumento final desse comando faz com que a cópia de trabalho, neste caso, seja nominada como head, mas ela poderá ser renomeada com segurança.

O svn+ssh significa que o protocolo SVN será tunelado sobre o SSH. O nome do servidor é repo.freebsd.org, e base é o caminho para o repositório, e head é o subdiretório dentro do repositório.

Se seu nome de login no projeto FreeBSD for diferente do nome de login usado na sua máquina local, inclua-o na URL (por exemplo svn+ssh://jarjar@repo.freebsd.org/base/head) ou adicione uma entrada no arquivo ~/.ssh/config no formato:

Host repo.freebsd.org
	User jarjar

Este é o método mais simples, mas é difícil dizer quanta carga ele irá colocar no repositório.

Nota:

O svn diff não requer acesso ao servidor pois o SVN armazena uma cópia de referência de todos os arquivos na cópia de trabalho. Isto, no entanto, significa que as cópias de trabalho do Subversion são muito grandes em tamanho.

5.2.2. Branches RELENG_* e Layout Geral

No svn+ssh://repo.freebsd.org/base, base refere-se à árvore de código fonte. Similarmente, ports refere-se à árvore de ports e assim por diante. Estes são repositórios separados com suas próprias seqüências de números de mudança, controles de acesso e email de commit.

Para o repositório base, HEAD refere-se a árvore -CURRENT. Por exemplo, head/bin/ls é o que entraria como /usr/src/bin/ls em uma release. Alguns locais importantes são:

  • /head/ que corresponde a HEAD, também conhecido como -CURRENT.

  • /stable/n que corresponde a RELENG_n.

  • /releng/n.n que corresponde a RELENG_n_n.

  • /release/n.n.n que corresponde a RELENG_n_n_n_RELEASE.

  • /vendor* é uma área de trabalho para importar branches de vendors. Este diretório em si não contém branches, no entanto, os seus subdiretórios contém. Isso contrasta com os diretórios stable, releng e release.

  • /projects e /user são áreas de trabalho de branch. Como acima, o diretório /user não contém branches em si.

5.2.3. Branches e Layout do Projeto de Documentação do FreeBSD

no svn+ssh://repo.freebsd.org/doc, doc refere-se à raiz do repositório da árvore de código fonte.

Em geral, a maior parte do trabalho do Projeto de Documentação do FreeBSD será feito dentro do branch head/ da árvore com os arquivos fontes da documentação.

A documentação do FreeBSD é escrita e/ou traduzida para vários idiomas, cada um em um diretório separado no branch head/.

Cada conjunto de tradução contém vários subdiretórios para as várias partes do Projeto de Documentação do FreeBSD. Alguns diretórios notáveis são:

  • /articles/ contém o código fonte para artigos escritos por vários colaboradores do FreeBSD.

  • /books/ contém o código fonte para os diferentes livros, como o Handbook do FreeBSD.

  • /htdocs/ contém o código-fonte do website do FreeBSD.

5.2.4. Branches e Layout da Árvore de Ports do FreeBSD

No svn+ssh: //repo.freebsd.org/ports, ports refere-se à raiz do repositório da árvore de ports.

Em geral, a maior parte do trabalho na coleção de ports do FreeBSD será feito dentro da branch head/ da árvore de ports, que é a árvore de ports real usada para instalar software. Alguns outros locais importantes são:

  • /branches/RELENG_n_n_n que corresponde a RELENG_n_n_n e é usado para mesclar atualizações de segurança em preparação para uma release.

  • /tags/RELEASE_n_n_n que corresponde a RELEASE_n_n_n e representa uma tag de release da árvore de ports.

  • /tags/RELEASE_n_EOL representa o tag de end of life de um branch específico do FreeBSD.

5.3. Uso diário

Esta seção explicará como realizar operações comuns do dia-a-dia com o Subversion.

5.3.1. Ajuda

O SVN traz em si uma documentação interna de ajuda. Ela pode ser acessada digitando:

% svn help

Informações adicionais podem ser encontradas no Subversion Book.

5.3.2. Checkout

Como visto anteriormente, para fazer o checkout da branch principal (head) do FreeBSD:

% svn checkout svn+ssh://repo.freebsd.org/base/head /usr/src

Em algum momento, provavelmente será útil ter uma copia de trabalho mais do que apenas do HEAD, por exemplo, ao mesclar as alterações para stable/7. Portanto, pode ser útil ter uma verificação parcial da árvore completa (um check-out completo seria muito doloroso).

Para fazer isso, primeiro confira a raiz do repositório:

% svn checkout --depth=immediates svn+ssh://repo.freebsd.org/base

Isso vai obter o base com todos os arquivos que ele contém (no momento da escrita, apenas o ROADMAP.txt) e subdiretórios vazios para head, stable, vendor e assim por diante.

É possível expandir a cópia de trabalho. Basta alterar a profundidade dos vários subdiretórios:

% svn up --set-depth=infinity base/head
% svn up --set-depth=immediates base/release base/releng base/stable

O comando acima irá baixar uma cópia completa do head, além de cópias vazias de cada tag de release, de cada branch de releng, e de cada branch stable.

Se numa data posterior você tiver necessidade de mesclar algo, por exemplo, com a 7-STABLE, expanda a cópia de trabalho:

% svn up --set-depth=infinity base/stable/7

As subárvores não precisam ser expandidas completamente. Por exemplo, para expandir apenas o stable/7/sys e depois expandir o resto do stable/7:

% svn up --set-depth=infinity base/stable/7/sys
% svn up --set-depth=infinity base/stable/7

Atualizar a árvore com svn update irá apenas atualizar o que foi pedido anteriormente (neste caso, head e stable/7), ele não irá puxar a árvore inteira.

5.3.3. Checkout Anonimo

É possível efetuar o checkout anonimo o repositório Subversion do FreeBSD. Isso dará acesso a uma árvore somente leitura que pode ser atualizada, mas que não poderá ser enviada de volta para o repositório principal por meio de um commit. Para fazer isso, use:

% svn co https://svn.FreeBSD.org/base/head /usr/src

Mais detalhes sobre o uso do Subversion podem ser encontrados emUsando o Subversion.

5.3.4. Atualizando a Árvore

Para atualizar uma cópia de trabalho para a revisão mais recente ou uma revisão específica:

% svn update
% svn update -r12345

5.3.5. Status

Para ver as alterações locais que foram feitas na cópia de trabalho:

% svn status

Para mostrar alterações locais e arquivos que estão desatualizados, execute:

% svn status --show-updates

5.3.6. Editando e efetuando o commit

O SVN não precisa ser avisado com antecedência sobre a edição de arquivos.

Para efetuar o commit de todas as alterações no diretório atual e em todos os seus subdiretórios:

% svn commit

Para efetuar o commit de todas as alterações, por exemplo, nos arquivos lib/libfetch/ e usr/bin/fetch/ em uma única operação, execute:

% svn commit lib/libfetch usr/bin/fetch

Também existe um wrapper de commit para a árvore de ports para manipular as propriedades e para verificar a sanidade das mudanças:

% /usr/ports/Tools/scripts/psvn commit

5.3.7. Adicionando e Removendo Arquivos

Nota:

Antes de adicionar arquivos, obtenha uma cópia do auto-props.txt (há também um versão específica da árvore de ports) e adicione-o ao ~/.subversion/config seguindo as instruções contidas no arquivo. Se você adicionou algo antes de ler isto, use o comando svn rm --keep-local para apenas os arquivos adicionados, corrija seu arquivo de configuração e adicione-os novamente. O arquivo de configuração inicial é criado quando você executa um comando svn pela primeira vez, até mesmo algo tão simples quanto svn help.

Os arquivos são adicionados a um SVN repositório com svn add. Para adicionar um arquivo chamado foo, edite-o e depois execute:

% svn add foo

Nota:

A maioria dos novos arquivos fonte deve incluir uma string $FreeBSD: head/pt_BR.ISO8859-1/articles/committers-guide/article.xml 53167 2019-06-19 00:46:00Z dbaio $ próxima ao início do arquivo. Ao efetuar o commit, o svn expandirá a string $FreeBSD: head/pt_BR.ISO8859-1/articles/committers-guide/article.xml 53167 2019-06-19 00:46:00Z dbaio $, adicionando o caminho do arquivo, o número da revisão, a data e a hora da confirmação e o nome de usuário do committer. Arquivos que não podem ser modificados podem ser enviados sem a string $FreeBSD: head/pt_BR.ISO8859-1/articles/committers-guide/article.xml 53167 2019-06-19 00:46:00Z dbaio $.

Os arquivos podem ser removidos com svn remove:

% svn remove foo

O subversion não requer a exclusão do arquivo antes de usaramos o comando svn rm e, de fato, ele reclama se isso acontecer.

É possível adicionar diretórios com svn add:

% mkdir bar
% svn add bar

Apesar que o svn mkdir torna isso mais fácil, combinando a criação do diretório e a adição dele:

% svn mkdir bar

Como arquivos, os diretórios são removidos com svn rm. Não existe um comando separado especificamente para remover diretórios.

% svn rm bar

5.3.8. Copiando e Movendo Arquivos

Este comando cria uma cópia do arquivo foo.c nomeado bar.c, com o novo arquivo também sob controle de versão e com o histórico completo de foo.c:

% svn copy foo.c bar.c

Geralmente é preferível copiar desta forma ao invés de copiar o arquivo com comando cp e adicionando-o ao repositório com svn add porque desta forma o novo arquivo não herda a história do original.

Para mover e renomear um arquivo:

% svn move foo.c bar.c

5.3.9. Logs e Anotações

O svn log mostra revisões e mensagens de commit, as mais recentes são exibidas primeiro, para arquivos ou diretórios. Quando usado em um diretório, todas as revisões que afetaram o diretório e os arquivos nesse diretório são mostradas.

O svn annotate , ou igualmente o svn praise ou svn blame, mostra o número de revisão mais recente e quem fez o commit dessa revisão para cada linha de um arquivo.

5.3.10. Diffs

O svn diff exibe alterações na cópia de trabalho. Diffs gerado por SVN são unificados e incluem novos arquivos por padrão na saída do diff.

O svn diff pode mostrar as mudanças entre duas revisões do mesmo arquivo:

% svn diff -r179453:179454 ROADMAP.txt

Ele também pode mostrar todas as alterações para um changeset específico. Este comando mostra quais alterações foram feitas no diretório atual e em todos os subdiretórios do changeset 179454:

% svn diff -c179454 .

5.3.11. Revertendo

Mudanças locais (incluindo adições e deleções) podem ser revertidas usando svn revert. Ele não atualiza arquivos desatualizados, apenas os substitui por cópias originais da versão original.

5.3.12. Conflitos

Se um svn update resultou em um conflito de mesclagem, o Subversion irá lembrar quais arquivos têm conflitos e se recusará a fazer o commit de quaisquer alterações nesses arquivos até que seja explicitamente informado que os conflitos foram resolvidos. O procedimento simples, ainda não obsoleto, é:

% svn resolved foo

No entanto, o procedimento preferido é:

% svn resolve --accept=working foo

Os dois exemplos são equivalentes. Os valores possíveis para --accept são:

  • working: use a versão em seu diretório de trabalho (a qual se presume que foi editada para resolver os conflitos).

  • base: usar uma cópia original da versão que você tinha antes do svn update, descartando suas próprias alterações, as mudanças conflitantes e possivelmente outras mudanças intervenientes também.

  • mine-full: use o que você tinha antes do svn update, incluindo suas próprias mudanças, mas descartando as mudanças conflitantes, e possivelmente outras mudanças intervenientes também.

  • theirs-full: use a versão que foi recuperada quando você fez o svn update, descartando as suas próprias mudanças.

5.4. Uso Avançado

5.4.1. Checkouts dispersos

O SVN permite sparse, ou checkouts parciais de um diretório adicionando --depth a um svn checkout.

Os argumentos válidos para --depth são:

  • empty: o próprio diretório sem qualquer conteúdo.

  • files: o diretório e quaisquer arquivos nele contidos.

  • immediates: o diretório e quaisquer arquivos e diretórios contidos nele, mas nenhum dos conteúdos dos subdiretórios.

  • infinity: qualquer coisa.

A opção --depth se aplica a muitos outros comandos, incluindo svn commit, svn revert e o svn diff.

Como o parâmetro --depth utilizado é persistente, existe uma opção --set-depth para o svn update que irá mudar a profundidade selecionada. Assim, dada a cópia de trabalho produzida pelo exemplo anterior:

% cd ~/freebsd
% svn update --set-depth=immediates .

O comando acima irá popular a cópia de trabalho em ~/freebsd com ROADMAP.txt e subdiretórios vazios, e nada acontecerá quando svn update for executado nos subdiretórios. No entanto, esse comando definirá a profundidade para head (nesse caso) como infinito e o populará totalmente:

% svn update --set-depth=infinity head

5.4.2. Operação Direta

Certas operações podem ser realizadas diretamente no repositório sem tocar na cópia de trabalho. Especificamente, isso se aplica a qualquer operação que não exija a edição de um arquivo, incluindo:

  • log, diff

  • mkdir

  • remove, copy, rename

  • propset, propedit, propdel

  • merge

A criação de uma branch é muito rápida. Este comando seria usado para criar a branch RELENG_8:

% svn copy svn+ssh://repo.freebsd.org/base/head svn+ssh://repo.freebsd.org/base/stable/8

Isso equivale a esses comandos, que levam minutos e horas, em vez de segundos, dependendo da sua conexão de rede:

% svn checkout --depth=immediates svn+ssh://repo.freebsd.org/base
% cd base
% svn update --set-depth=infinity head
% svn copy head stable/8
% svn commit stable/8

5.4.3. Mesclando com SVN

Esta seção lida com o merge de código de um branch para outro (normalmente, do head para um brach stable).

Nota:

Em todos os exemplos abaixo, $FSVN refere-se à localização do repositório Subversion do FreeBSD, svn+ssh://repo.freebsd.org/base .

5.4.3.1. Sobre o acompanhamento de mesclagem

Do ponto de vista do usuário, informações de acompanhamento de mesclagem (ou mergeinfo) são armazenadas em uma propriedade chamada svn:mergeinfo, que é uma lista separada por vírgulas de revisões e intervalos de revisões que foram mescladas. Quando definido em um arquivo, ele se aplica somente a esse arquivo. Quando definido em um diretório, ele se aplica a esse diretório e seus descendentes (arquivos e diretórios), exceto aqueles que possuem o seu próprio svn:mergeinfo.

Ele não é herdado. Por exemplo, stable/6/contrib/openpam/ não herda implicitamente o mergeinfo de stable/6/, ou do stable/6/contrib/. Isso faria com que os checkouts parciais fossem difíceis de gerenciar. Em vez disso, o mergeinfo é explicitamente propagado pela árvore. Para mesclar algo em branch/foo/bar/, estas regras se aplicam:

  1. Se branch/foo/bar/ ainda não tiver um registro mergeinfo, mas um ancestral direto (por exemplo, branch/foo/) tem, então esse registro será propagado para abaixo até branch/foo/bar/ antes que as informações sobre a mesclagem atual sejam registradas.

  2. As informações sobre a mesclagem atual não serão propagadas para o ancestral.

  3. Se um descendente direto de branch/foo/bar/ (por exemplo, branch/foo/bar/baz/) já tiver um registro mergeinfo, as informações sobre a mesclagem atual serão propagadas para ele.

Se você considerar o caso em que uma revisão altera várias partes separadas da árvore (por exemplo, branch/foo/bar/ e branch/foo/quux/), mas você só deseja mesclar alguns deles (por exemplo, branch/foo/bar/), você verá que essas regras fazem sentido. Se mergeinfo fosse propagado, pareceria que a revisão também foi mesclada com branch/foo/quux/, quando na verdade não foi.

5.4.3.2. Selecionando a branch de origem e de destino ao mesclar

Mesclagens para as branches stable/ devem originar-se da head/. Por exemplo:

% svn merge -c r123456 ^/head/ stable/11
% svn commit stable/11

Mesclagens para as branches releng/ devem sempre se originar da branch stable/ correspondente. Por exemplo:

% svn merge -c r123456 ^/stable/11  releng/11.0
% svn commit releng/11.0

Nota:

Os committers só podem se efetuar um commit para as branches releng/ durante um ciclo de release após receber aprovação da Equipe de Engenharia de Release, após o qual somente o Security Officer pode efetuar commits para o branch releng/ para um Aviso de Segurança ou Aviso de Errata.

Todas as mesclagens são mescladas e enviadas por commit a partir da raiz da branch. Todas as mesclagens se parecem com:

% svn merge -c r123456 ^/head/ checkout
% svn commit checkout

Observe que checkout deve ser uma verificação completa da branch na qual a mesclagem ocorre.

% svn merge -c r123456 ^/stable/10 releng/10.0
5.4.3.3. Preparando o Alvo de Mesclagem (Merge Target)

Devido aos problemas de propagação do mergeinfo descritos anteriormente, é muito importante nunca mesclar as alterações em uma cópia de trabalho esparsa. Sempre use um checkout completo do branch que está sendo mesclado. Por exemplo, ao mesclar de HEAD para 7, use um checkout completo de stable/7:

% cd stable/7
% svn up --set-depth=infinity

O diretório de destino também deve estar atualizado e não deve conter alterações que ainda não foram enviadas por commit ou arquivos perdidos.

5.4.3.4. Identificando Revisões

Identificar revisões a serem mescladas é uma obrigação. Se o alvo já tiver mergeinfo completo, solicite uma lista para o SVN:

% cd stable/6/contrib/openpam
% svn mergeinfo --show-revs=eligible $FSVN/head/contrib/openpam

Se o destino não tiver mergeinfo completo, verifique o log da origem de mesclagem.

5.4.3.5. Mesclando

Agora vamos começar a mesclar!

5.4.3.5.1. Os princípios

Por exemplo, para mesclar:

  • revisão $R

  • no diretório $target na branch stable $B

  • a partir do diretório $source no head

  • $FSVN é o svn+ssh://repo.freebsd.org/base

Supondo que as revisões $P e $Q já tenham sido mescladas e que o diretório atual seja uma cópia de trabalho atualizada de stable/$B, a mergeinfo existente será semelhante a:

% svn propget svn:mergeinfo -R $target
$target - /head/$source:$P,$Q

A mesclagem é feita assim:

% svn merge -c$R $FSVN/head/$source $target

É possível verificar os resultados disso com um svn diff.

O svn:mergeinfo agora se parece com:

% svn propget svn:mergeinfo -R $target
$target - head/$source:$P,$Q,$R

Se os resultados não forem exatamente como os mostrados, você pode precisar de assistência antes de efetuar o commit pois erros podem ter sido cometidos, ou pode haver algo errado com o mergeinfo existente, ou pode haver um bug no Subversion.

5.4.3.5.2. Exemplo Prático

Como um exemplo prático, considere este cenário. As alterações no netmap.4 no r238987 devem ser mescladas do CURRENT para o 9-STABLE. O arquivo reside em head/share/man/man4. De acordo com o Seção 5.4.3, “Mesclando com SVN, também é onde devemos fazer a mesclagem. Note que neste exemplo todos os caminhos são relativos ao topo do repositório svn. Para obter mais informações sobre o layout do diretório, consulte Seção 5.2.2, “Branches RELENG_* e Layout Geral”.

O primeiro passo é inspecionar o mergeinfo existente.

% svn propget svn:mergeinfo -R stable/9/share/man/man4

Tome uma nota rápida de como ele se parece antes de avançar para o próximo passo; fazendo a mesclagem real:

% svn merge -c r238987 svn+ssh://repo.freebsd.org/base/head/share/man/man4 stable/9/share/man/man4
--- Merging r238987 into 'stable/9/share/man/man4':
U    stable/9/share/man/man4/netmap.4
--- Recording mergeinfo for merge of r238987 into
'stable/9/share/man/man4':
 U   stable/9/share/man/man4

Verifique se o número de revisão da revisão mesclada foi adicionado. Quando isso for verificado, a única coisa que resta é o commit em si.

% svn commit stable/9/share/man/man4
5.4.3.6. Precauções antes de efetuar o commit

Como sempre, faça um build world (ou as partes apropriadas dele).

Verifique as mudanças com o svn diff e svn stat. Certifique-se de que todos os arquivos que deveriam ter sido adicionados ou excluídos foram de fato adicionados ou excluídos.

Dê uma olhada mais de perto em qualquer mudança de propriedade (marcada por um M na segunda coluna do svn stat). Normalmente, nenhuma propriedade svn:mergeinfo deve estar em qualquer lugar, exceto o diretório (ou diretórios) de destino.

Se algo parecer suspeito, peça ajuda.

5.4.3.7. Fazendo o commit

Certifique-se de efetuar o commit de um diretório de nível superior para incluir também o mergeinfo. Não especifique arquivos individuais na linha de comando. Para mais informações sobre como submeter arquivos em geral, veja a seção relevante deste manual.

5.4.4. Importações de fornecedores com SVN

Importante:

Por favor, leia toda esta seção antes de iniciar uma importação de fornecedores.

Nota:

Os patches para o código do fornecedor se enquadram em duas categorias:

  • Patches do fornecedor: são patches que foram emitidos pelo fornecedor ou que foram extraídos do sistema de controle de versão do fornecedor, que abordam problemas que não podem esperar até a próxima versão do fornecedor.

  • Patches do FreeBSD: são patches que modificam o código do fornecedor para resolver problemas específicos do FreeBSD.

A natureza de um patch determina para onde ele deve ser enviado por commit:

  • Os patches do fornecedor devem ser enviados por commit para o branch do fornecedor e mesclados a partir dele. Se o patch resolver um problema em uma nova versão que está sendo importada atualmente, ele não deve ser enviado por commit junto com a nova versão: a versão deve ser importada e marcada primeiro, então a correção pode ser aplicada e o commit efetuado. Não há necessidade de marcar novamente as fontes do fornecedor depois de confirmar o patch.

  • Patches do FreeBSD são enviados diretamente para o head.

5.4.4.1. Preparando a Árvore

Se estiver importando pela primeira vez após a mudança para o Subversion, é necessário achatar e limpar a árvore do fornecedor, bem como inicializar o histórico de mesclagem na árvore principal.

5.4.4.1.1. Achatamento

Durante a conversão do CVS para o Subversion, as branches do fornecedor foram importadas com o mesmo layout da árvore principal. Isso significa que as fontes do fornecedor pf foram armazenadas originalmente em vendor/pf/dist/contrib/pf. O código fonte do fornecedor fica melhor se armazenado diretamente em vendor/pf/dist.

Para achatar a árvore do pf:

% cd vendor/pf/dist/contrib/pf
% svn mv $(svn list) ../..
% cd ../..
% svn rm contrib
% svn propdel -R svn:mergeinfo .
% svn commit

O bit propdel é necessário porque, começando com 1.5, o Subversion adicionará svn:mergeinfo em qualquer diretório que seja copiado ou movido. Nesse caso, como nada está sendo mesclado da árvore excluída, eles apenas atrapalham.

As tags também podem ser achatadas (3, 4, 3.5 etc.); o procedimento é exatamente o mesmo, mudando apenas dist para 3.5 ou similar, e aguardando para executar o svn commit apenas no final do processo.

5.4.4.1.2. Limpando

A árvore dist pode ser limpa conforme necessário. A desativação da expansão de palavras-chave é recomendada, pois não faz sentido no código do fornecedor não modificado e, em alguns casos, pode até mesmo ser prejudicial. O OpenSSH, por exemplo, inclui dois arquivos que se originaram do FreeBSD e ainda contêm as tags da versão original. Para fazer isso:

% svn propdel svn:keywords -R .
% svn commit
5.4.4.1.3. Bootstrapping o historico de mesclagem

Se estiver importando pela primeira vez após a mudança para o Subversion, faça o bootstrap do svn:mergeinfo no diretório de destino da árvore principal para a revisão que corresponde à última alteração relacionada à árvore do fornecedor, antes de importar novos fontes:

% cd head/contrib/pf
% svn merge --record-only svn+ssh://repo.freebsd.org/base/vendor/pf/dist@180876 .
% svn commit
5.4.4.2. Importando Novas Fontes

Com dois commits - um para a importação em si e outro para a tag - essa etapa pode ser opcionalmente repetida para cada release upstream entre a última importação e a importação atual.

5.4.4.2.1. Preparando os fontes do fornecedor

O Subversion é capaz de armazenar uma distribuição completa na árvore do fornecedor. Portanto, importe tudo, mas mescle apenas o que é necessário.

Um svn add é necessário para adicionar quaisquer arquivos que foram adicionados desde a última importação do fornecedor, e o svn rm é necessário para remover todos os que foram removidos desde então. Recomenda-se a preparação de listas ordenadas do conteúdo da árvore do fornecedor e das fontes que serão importadas, para facilitar o processo.

% cd vendor/pf/dist
% svn list -R | grep -v '/$' | sort >../old
% cd ../pf-4.3
% find . -type f | cut -c 3- | sort >../new

Com esses dois arquivos, o comm -23 ../old ../new listará os arquivos removidos (arquivos somente em old), enquanto comm -13 .. /old ../new listará os arquivos adicionados somente no new.

5.4.4.2.2. Importando para a Árvore do Fornecedor

Agora, os fontes devem ser copiados para dist e os comandos svn add e svn rm são usados ​​conforme necessário:

% cd vendor/pf/pf-4.3
% tar cf - . | tar xf - -C ../dist
% cd ../dist
% comm -23 ../old ../new | xargs svn rm
% comm -13 ../old ../new | xargs svn add --parents

Se algum diretório foi removido, ele terá que ser removido manualmente com o svn rm. Nada vai quebrar se eles não forem, mas eles permanecerão na árvore.

Verifique as propriedades em qualquer novo arquivo. Todos os arquivos de texto devem ter o svn:eol-style definido como native. Todos os arquivos binários devem ter o svn:mime-type configurado para application/octet-stream , a menos que haja um tipo de mídia mais apropriado. Arquivos executáveis ​​devem ter svn:executable definido como *. Nenhuma outra propriedade deve existir em qualquer arquivo da árvore.

Agora é possível fazer o commit. No entanto, é uma boa prática certificar-se de que tudo está correto, usando os comandos svn stat e svn diff.

5.4.4.2.3. Marcação (Tagging)

Depois de realizado o commit, as versões do fornecedor são marcadas para referência futura. A melhor e mais rápida maneira de fazer isso é diretamente no repositório:

% svn cp svn+ssh://repo.freebsd.org/base/vendor/pf/dist svn+ssh://repo.freebsd.org/base/vendor/pf/4.3

Quando isso estiver concluído, execute o svn up para a cópia de trabalho do vendor/pf para obter a nova tag, embora isso raramente seja necessário.

Se você criar a tag na cópia de trabalho da árvore, os resultados do svn:mergeinfo deverão ser removidos:

% cd	vendor/pf
% svn cp dist 4.3
% svn propdel svn:mergeinfo -R 4.3
5.4.4.3. Mesclagem para o Head
% cd head/contrib/pf
% svn up
% svn merge --accept=postpone svn+ssh://repo.freebsd.org/base/vendor/pf/dist .

O --accept=postpone diz ao Subversion para não reclamar sobre conflitos de mesclagem, pois eles serão manipulados manualmente.

Dica:

A mudança do cvs2svn ocorreu em 3 de junho de 2008. Ao realizar mesclagens de fornecedores para pacotes que já estavam presentes e convertidos pelo processo cvs2svn, o comando usado para mesclar /vendor/package_name/dist para /head/package_location (por exemplo, head/contrib/sendmail) deve usar -c REV para indicar a revisão a ser mesclada a partir da árvore /vendor. Por exemplo:

% svn checkout svn+ssh://repo.freebsd.org/base/head/contrib/sendmail
% cd sendmail
% svn merge -c r261190 '^/vendor/sendmail/dist' .

^ é um alias para o caminho do repositório.

Nota:

Se estiver usando o shell Zsh, o ^ deve ser escapado com \ ou entre aspas.

É necessário resolver quaisquer conflitos de mesclagem.

Certifique-se de que todos os arquivos adicionados ou removidos na árvore do fornecedor tenham sido adicionados ou removidos corretamente na árvore principal. Para verificar os diffs com relação ao branch do fornecedor:

% svn diff --no-diff-deleted --old=svn+ssh://repo.freebsd.org/base/vendor/pf/dist --new=.

O --no-diff-deleted diz ao Subversion para não reclamar sobre os arquivos que estão na árvore do fornecedor, mas que não estão na árvore principal. Coisas que teriam sido removidas antes da importação do fornecedor, como os makefiles do fornecedor e os scripts de configuração.

Usando o CVS, uma vez que um arquivo estava fora do branch do fornecedor, ele não podia ser colocado de volta. Com o Subversion, não há nenhum conceito dentro ou fora do branch do fornecedor. Se um arquivo que anteriormente tinha modificações locais, para fazer com que ele não apareça em diffs na árvore do fornecedor, tudo o que tem que ser feito é remover qualquer sobra como as tags de versões do FreeBSD, o que é muito mais fácil.

Se alguma mudança for necessária para o "world" compilar com os novos fontes, faça-as agora e continue testando até que tudo seja compilado e executado perfeitamente.

5.4.4.4. Fazendo o commit da Importação de Fornecedores

Agora é possível fazer o commit! O commit deve ser feito de tudo de uma só vez. Se feito corretamente, a árvore passará de um estado consistente com o código antigo para um estado consistente com o novo código.

5.4.4.5. A partir do zero
5.4.4.5.1. Importando para a Árvore do Fornecedor

Esta seção é um exemplo de importação e marcação do byacc no head.

Primeiro, prepare o diretório em vendor:

% svn co --depth immediates $FSVN/vendor
% cd vendor
% svn mkdir byacc
% svn mkdir byacc/dist

Agora, importe os fontes para o diretório dist. Uma vez que os arquivos estiverem no lugar, faça o svn add dos novos, e então faça o svn commit e aplique a tag na versão importada. Para poupar tempo e largura de banda, é possível efetuar diretamente o commit e as marcações de forma remota:

% svn cp -m "Tag byacc 20120115" $FSVN/vendor/byacc/dist $FSVN/vendor/byacc/20120115
5.4.4.5.2. Mesclando para o head

Devido a este ser um novo arquivo, copie-o para a mesclagem:

% svn cp -m "Import byacc to contrib" $FSVN/vendor/byacc/dist $FSVN/head/contrib/byacc

Ainda é possível trabalhar normalmente nos fontes recém importados.

5.4.5. Revertendo um Commit

A reversão de um commit para uma versão anterior é bem fácil:

% svn merge -r179454:179453 ROADMAP.txt
% svn commit

Alterar a sintaxe do número, com o negativo significando a reversão de uma mudança, também pode ser usado:

% svn merge -c -179454 ROADMAP.txt
% svn commit

Isso também pode ser feito diretamente no repositório:

% svn merge -r179454:179453 svn+ssh://repo.freebsd.org/base/ROADMAP.txt

Nota:

É importante assegurar que o mergeinfo esteja correto ao reverter um arquivo para permitir que o svn mergeinfo --eligible funcione como esperado.

A reversão da exclusão de um arquivo é um pouco diferente. É necessário copiar a versão do arquivo que antecede a exclusão. Por exemplo, para restaurar um arquivo que foi excluído na revisão N, restaure a versão N-1:

% svn copy svn+ssh://repo.freebsd.org/base/ROADMAP.txt@179454
% svn commit

ou, igualmente:

% svn copy svn+ssh://repo.freebsd.org/base/ROADMAP.txt@179454 svn+ssh://repo.freebsd.org/base

Simplesmente não recrie o arquivo manualmente e o adicione com o svn add - isso fará com que o histórico seja perdido.

5.4.6. Corrigindo Erros

Por mais que possamos realizar uma cirurgia em uma emergência, não planeje ou corrija erros por baixo dos panos. Planos para erros permanecem nos registros para sempre. Certifique-se de verificar a saída do svn status e do svn diff antes de enviar o commit.

Erros acontecerão, mas eles geralmente podem ser corrigidos sem perturbar.

No caso de adicionar um arquivo no local errado. A coisa certa a fazer é usar o svn move e mover o arquivo para o local correto e fazer o commit. Isso altera apenas algumas linhas de metadados no journal do repositório, e os logs serão todos conectados corretamente.

A coisa errada a fazer é apagar o arquivo e, em seguida, usar svn add para adicionar uma cópia independente no local correto. Em vez de algumas linhas de texto, o repositório journal cria uma nova cópia inteira do arquivo. Isso é um desperdício.

5.4.7. Usando um Espelho do Subversion

Há uma séria desvantagem neste método: toda vez que for feito o commit de algo, terá que executar um svn relocate no repositório master, não esquecendo de executar o svn relocate de volta para o mirror após o commit. Além disso, como o svn relocate só funciona entre os repositórios que possuem o mesmo UUID, algum hacking do UUID do repositório local deve ocorrer antes que seja possível começar a usá-lo.

5.4.7.1. Checkout a partir de um Mirror

Faça o checkout de uma cópia de trabalho a partir de um mirror substituindo a URL do mirror por svn+ssh://repo.freebsd.org/base. Este pode ser um mirror oficial ou um mirror mantido usando o svnsync.

5.4.7.2. Configurando um Mirror svnsync

Evite configurar um mirror svnsync a menos que haja uma boa razão para isso. Na maioria das vezes, um mirror git é uma alternativa melhor. Começar um novo mirror do zero leva muito tempo. Espere um mínimo de 10 horas para conectividade de alta velocidade. Se o trafego for passar por links internacionais, espere que isso leve de quatro a dez vezes mais.

Uma maneira de limitar o tempo necessário é pegar um arquivo de seed. Ele é grande (~1GB), mas consome menos tráfego de rede e leva menos tempo para baixar do que o svnsync.

Extraia o arquivo e o atualize:

% tar xf svnmirror-base-r261170.tar.xz
% svnsync sync file:///home/svnmirror/base

Agora, configure isso para executar a partir do cron(8), faça checkouts localmente, configure um servidor svnserve para as máquinas locais com as quais conversar, etc.

O mirror seed está definido para buscar o conteúdo a partir de svn://svn.freebsd.org/base. A configuração para o mirror é armazenada em revprop 0 no mirror local. Para ver a configuração, tente:

% svn proplist -v --revprop -r 0 file:///home/svnmirror/base

Use svn propset para mudar as coisas.

5.4.8. Fazendo commit de dados HighASCII

Os arquivos que possuem bits high-ASCII são considerados arquivos binários no SVN, portanto, as verificações de pré-commit falham e indicam que a propriedade mime-type deve ser definida como application/octet-stream. No entanto, o uso deste é desencorajado, por isso, não o defina. A melhor maneira é sempre evitar dados high-ASCII, para que possam ser lidos em qualquer lugar com qualquer editor de texto, mas se não for possivel evitar, em vez de alterar o mime-type, defina a propriedade fbsd:notbinary com o propset:

% svn propset fbsd:notbinary yes foo.data

5.4.9. Mantendo um branch de projeto

Uma branch de projeto é aquela que está sincronizada com o head (ou outra branch) e é usada para desenvolver um projeto e, em seguida, fazer o seu commit de volta para o head. No SVN, o branch dolphin é usado para isso. Uma branch dolphin é aquela que diverge por um tempo e é finalmente enviada de volta ao branch original. Durante a migração do código de desenvolvimento em uma direção (do head para o branch apenas). Não é feito o commit de nenhum código de volta ao head até o final. Depois que é feito o commit da branch no final, ela estará morta (embora uma nova branch com o mesmo nome possa ser criada depois que a que está morta é excluída).

Como explicado em https://people.FreeBSD.org/~peter/svn_notes.txt, o trabalho que destina-se a ser mesclado de volta para o HEAD deve estar em base/projects/. Se o trabalho é benéfico para a comunidade do FreeBSD de alguma forma, mas não se destina a ser mesclado diretamente no HEAD, então o local apropriado é base/user/username/. Esta página contém mais detalhes.

Para criar um branch de projeto:

% svn copy svn+ssh://repo.freebsd.org/base/head svn+ssh://repo.freebsd.org/base/projects/spif

Para mesclar as alterações do HEAD de volta ao branch de projeto:

% cd copy_of_spif
% svn merge svn+ssh://repo.freebsd.org/base/head
% svn commit

É importante resolver quaisquer conflitos de mesclagem antes de fazer o commit.

5.5. Algumas dicas

Nos logs de commit, etc., rev 179872 é soletrado r179872 conforme a convenção.

É possível acelerar o svn adicionando estas entradas ao ~/.ssh/config:

Host *
ControlPath ~/.ssh/sockets/master-%l-%r@%h:%p
ControlMaster auto
ControlPersist yes

e depois digitando

mkdir ~/.ssh/sockets

Fazer o check-out de uma cópia de trabalho com um cliente Subversion padrão sem patches específicos do FreeBSD (OPTIONS_SET=FREEBSD_TEMPLATE) significará que as tags $FreeBSD: head/pt_BR.ISO8859-1/articles/committers-guide/article.xml 53167 2019-06-19 00:46:00Z dbaio $ não serão expandidas. Uma vez que a versão correta foi instalada, engane o Subversion para expandi-las da seguinte forma:

% svn propdel -R svn:keywords .
% svn revert -R .

Isso eliminará os patches para os quais ainda não foi feito o commit.

É possível preencher automaticamente os campos de log de commit "Sponsored by" e "MFC after" configurando os campos "freebsd-sponsored-by" e "freebsd-mfc-after" na seção "[miscellany]" do arquivo de configuração ~/.subversion/config. Por exemplo:

freebsd-sponsored-by = The FreeBSD Foundation
freebsd-mfc-after = 2 weeks

All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.