
Eu sempre usei o Subversion pra controlar as versões de meus códigos e no começo deste mês tive a necessidade de desenvolver uma aplicação que recuperasse as revisões do SVN e disponibilizasse em um site para controle dos gerentes de um dos projetos.
Como ferramenta eu optei por usar o SharpSVN, uma biblioteca escrita para .NET. Apesar do esforço não encontrei muita coisa em português então resolvi dar uma estudada na documentação (http://docs.sharpsvn.net/current) e escrever este artigo.
Aqui eu vou mostrar uma conexão simples e como resolver o seguinte erro ao publicar o site “SharpSvn.SvnFormatException: Can’t determine the user’s config path“.
Então vamos lá. Mãos a obra.
Primeiramente temos que preparar o nosso ambiente, para isso temos que baixar os arquivos do SharpSVN http://sharpsvn.open.collab.net/files/documents/180/4381/SSvn-1.6016.1637.zip
Extraia os arquivos.
Abra o Visual Studio e cria uma nova aplicação Web.
Faça referência a dll SharpSvn.dll.
Eu vou recuperar as versões de um projeto que nós do desenvolvedores.net apoiamos e que está no Sourceforge
Página oficial do projeto: http://uninfe.com.br
Página no Sourceforge: https://uninfe.svn.sourceforge.net/svnroot/uninfe
E como sempre, prestem atenção aos comentários do código. Eu coloco informações úteis no mesmo.
<%@ Page Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Exemplo SVN</title>
<script runat="server" type="text/C#">
protected void Page_Load(object sender, EventArgs e)
{
//definir o datasource do meu grid
grdRevision.DataSource = LoadSvnRevision();
//popular os dados no grid
grdRevision.DataBind();
}
private System.Collections.Generic.List<object> LoadSvnRevision()
{
//inicar o cliente svm
SharpSvn.SvnClient client = new SharpSvn.SvnClient();
//aqui iniciamos o objeto que irá receber os dados de retorno do svn.
//Obrigatoriamente tem que ser deste tipo System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs>
//pois o parâmetro é do tipo "out"
System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs> logItems = new System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs>();
//aqui chamamos o método responsável por trazer as revisões do SVN
//no primeiro parâmetro informamos a url do repositório. (targetPath)
//no segundo parâmetro informamos a nossa variável que irá receber o retorno
client.GetLog(new Uri("https://uninfe.svn.sourceforge.net/svnroot/uninfe"), out logItems);
//aqui eu crio uma variável que irá recuperar este retorno e converter
//em uma lista de obejtos para ser usada dentro do meu grid
System.Collections.Generic.List<object> data = new System.Collections.Generic.List<object>();
foreach (var item in logItems) //aqui eu uso um array nomeado do tipo Key/Value
{
data.Add(new
{
Id = item.Revision,
Autor = item.Author,
Data = item.Time,
});
}
//descarrego cliente
client.Dispose();
//limpo da memória
client = null;
//retorno minha lista de dados
return data;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView runat="server" ID="grdRevision">
</asp:GridView>
</div>
</form>
</body>
</html>
Assim temos uma aplicação básica que recupera os dados de um diretório publico. Mas, e se for em um diretório privado?
Basta acrescentar estas duas linhas ao seu código. Antes de chamar o método client.GetLog();
//Limpamos a autenticação antes de começar
client.Authentication.Clear();
//criamos uma autenticação de usuário usando o System.Net.NetworkCredential
client.Authentication.DefaultCredentials = new System.Net.NetworkCredential("Nome do usuário", "senha");
Uma outra dica que creio ser interessante passar é a opção de filtragem dos dados que iremos receber em nosso objeto de retorno. Do modo como foi feito no código de exemplo iremos recuperar todas as revisões, isso não é interessante em um projeto grande. Aqui vou ensinar a fazer o filtro por data.
//data de início do log que vamos buscar
//aqui informo +1 dia para que pegue também o dia atual
DateTime startDateTime = DateTime.Today.AddDays(1);
//iremos buscar 15 dias antes. Então informamos a segunda data
DateTime endDateTime = startDateTime.AddDays(-15);
//aqui iremos criar um "range" de datas para filtrar.
//para isso usamos o tipo SharpSvn.SvnRevisionRange
//o construtor do range aceita o tipo new SharpSvn.SvnRevision
//que por sua vez aceita vários tipos de filtros, um deles é o tipo data
//passamos então as datas de início e fim do range,
//de acordo com os parâmetros do contrutor do objeto SharpSvn.SvnRevisionRange
//primeiro e segundo parâmetro do construtor
SharpSvn.SvnRevisionRange range = new SharpSvn.SvnRevisionRange(new SharpSvn.SvnRevision(startDateTime), new SharpSvn.SvnRevision(endDateTime));
//criamos a nossa variável do tipo SharpSvn.SvnLogArgs para passar o nosso range de datas.
SharpSvn.SvnLogArgs args = new SharpSvn.SvnLogArgs(range);
//aqui chamamos o método responsável por trazer as revisões do SVN
//no primeiro parâmetro informamos a url do repositório. (targetPath)
//no segundo parâmetro passamos os argumentos de filtragem dos dados
//no terceiro parâmetro informamos a nossa variável que irá receber o retorno
client.GetLog(new Uri("https://uninfe.svn.sourceforge.net/svnroot/uninfe"), args, out logItems);
Preste atenção na linha em destaque, repare que modificamos o método client.GetLog() e passamos o parâmetro args que é o nosso filtro por data.
Vamos agora à um problema conhecido quando publicamos o nosso site. “SharpSvn.SvnFormatException: Can’t determine the user’s config path“. Este erro não acontece no modo debug porque estamos executando nossa aplicação local e a nossa configuração de usuário já foi toda carregada. Mas quando publicamos podemos receber este erro, pois normalmente a aplicação web roda como um serviço no servidor e pode não ter toda a configuração de usuário carregada. Para isso temos que informar o caminho onde iremos salvar a configuração padrão do usuário. Podemos usar um caminho temporário ou um caminho fixo na sua aplicação. Fica a seu critério. Eu optei por executar eu um caminho temporário.
Para contornar este erro, iremos usar o método LoadConfiguration() que irá indicar onde iremos salvar o arquivo de configuração temporário.
client.LoadConfiguration(System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Svn"), true);
Atenção: Este método deve ser chamado antes de client.GetLog();
Abaixo o código completo de nossa aplicação SVN
<%@ Page Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Exemplo SVN</title>
<script runat="server" type="text/C#">
protected void Page_Load(object sender, EventArgs e)
{
//definir o datasource do meu grid
grdRevision.DataSource = LoadSvnRevision();
//popular os dados no grid
grdRevision.DataBind();
}
private System.Collections.Generic.List<object> LoadSvnRevision()
{
//inicar o cliente svm
SharpSvn.SvnClient client = new SharpSvn.SvnClient();
//aqui iniciamos o objeto que irá receber os dados de retorno do svn.
//Obrigatoriamente tem que ser deste tipo System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs>
//pois o parâmetro é do tipo "out"
System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs> logItems = new System.Collections.ObjectModel.Collection<SharpSvn.SvnLogEventArgs>();
//data de início do log que vamos buscar
DateTime startDateTime = DateTime.Today.AddDays(1);
//iremos buscar 15 dias antes. Então informamos a segunda data
DateTime endDateTime = startDateTime.AddDays(-15);
//aqui iremos criar um "range" de datas para filtrar.
//para isso usamos o tipo SharpSvn.SvnRevisionRange
//o construtor do range aceita o tipo new SharpSvn.SvnRevision que por sua vez aceita vários tipos de filtros, um deles é o tipo data
//passamos então as datas de início e fim do range, de acordo com os parâmetros do contrutor do objeto SharpSvn.SvnRevisionRange
SharpSvn.SvnRevisionRange range = new SharpSvn.SvnRevisionRange(new SharpSvn.SvnRevision(startDateTime), new SharpSvn.SvnRevision(endDateTime));
//criamos a nossa variável do tipo SharpSvn.SvnLogArgs para passar o nosso range de datas.
SharpSvn.SvnLogArgs args = new SharpSvn.SvnLogArgs(range);
//aqui iremos dizer onde o arquivo de configuração do svn deverá ser salvo
client.LoadConfiguration(System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Svn"), true);
//aqui chamamos o método responsável por trazer as revisões do SVN
//no primeiro parâmetro informamos a url do repositório. (targetPath)
//no segundo parâmetro passamos os argumentos de filtragem dos dados
//no terceiro parâmetro informamos a nossa variável que irá receber o retorno
client.GetLog(new Uri("https://uninfe.svn.sourceforge.net/svnroot/uninfe"), args, out logItems);
//aqui eu crio uma variável que irá recuperar este retorno e converter
//em uma lista de obejtos para ser usada dentro do meu grid
System.Collections.Generic.List<object> data = new System.Collections.Generic.List<object>();
foreach (var item in logItems) //aqui eu uso um array nomeado do tipo Key/Value
{
data.Add(new
{
Id = item.Revision,
Autor = item.Author,
Data = item.Time,
});
}
//descarrego cliente
client.Dispose();
//limpo da memória
client = null;
//retorno minha lista de dados
return data;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView runat="server" ID="grdRevision">
</asp:GridView>
</div>
</form>
</body>
</html>
É isso ai pessoal 🙂
Até o próximo
♦ Marcelo