Git: Recuperando os nomes dos arquivos modificados

Posted by Alberto Leal on June 4th, 2009

Cenário: Seu cliente utiliza um outro SCM, por exemplo, o Harvest, no projeto o qual você trabalha. Mas, você e sua equipe resolvem utilizar o Git. Eis que você faz uma série de scripts de automação para pegar o seu release no Git e entregá-lo ao Harvest. Bacana, não? Para que isso funcione perfeitamente, você deve passar para o sistema de automação o nome dos arquivos que foram alterados, desse jeito, não será necessário enviar arquivos que sequer sofreram modificações, o que é bem interessante, diga-se de passagem.

Legal, existe o comando git whatchanged. Você pode passa como parâmetro o total de commits que você deseja analisar, utilizando a opção -n. Se você omití-lo, todas as modificações serão exibidas. (Se você informar o parâmetro -p, serão exibidas as modificações dentro dos arquivos).

Vamos dar uma olhada na saída desse comando:

$ git whatchanged -n 3
commit 8d726556aec75e1d6ef5ae477532fcc11770ac01
Author: Alberto Leal
Date:   Wed Jun 3 16:04:23 2009 -0400
 
Message 3
 
:100755 000000 0615380... 0000000... D  workspace/xxx/yyy/cfgXPTO.jnlp
:100755 000000 37076cc... 0000000... D  workspace/xxx/yyy/packageXYZ.jar
 
commit 3ab3a5e95fa031d8eb93154d161bfba228bc5f86
Author: Alberto Leal
Date:   Wed Jun 3 15:38:00 2009 -0400
 
Message 2
 
:100755 100755 849dc69... 1e7ef9d... M  workspace/xxx/src/com/xxx/yyy/ModelXYZ.java
:100755 100755 9828364... d85e5ee... M  workspace/xxx/WebContent/WEB-INF/jsp/viewXYZ.jsp
:000000 100755 0000000... d034c28... A  workspace/xxx/WebContent/htmlXPTO.html
 
commit 7e076b5130340f28e57526cf71ce96d7cc279538
Author: Alberto Leal
Date:   Wed Jun 3 10:04:56 2009 -0400
 
Message 1
 
:100755 100755 9c322de... 9828364... M  workspace/xxx/WebContent/WEB-INF/jsp/anotherXTPO.jsp

Repare que se você quiser pegar os arquivos modificados, você terá que copiar um a um. Trabalhoso, não? Existem diversas maneiras de se recuperar apenas os nomes dos arquivos. Uma sugestão seria:

def files_changed(commits, last_commit)
  File.open(commits, "r") do |infile|
  infile.each_line do |line|
    if line.include? last_commit
      break
    else
      er = line.match(/workspace(.*)/)
      puts er unless er.nil?
    end
  end
  end
end
 
files_changed(ARGV[0], ARGV[1])

Execute o seguinte comando no seu terminal para obter o resultado desejado:

$ git whatchanged > files.txt && ruby files_changed.rb files.txt 7e076b513

Se você quiser, simplesmente, pegar todos os arquivos modificado, você pode executar o comando abaixo:

$ git whatchanged | grep workspace | awk '{print($6)}'

Fica aí mais uma dica. Afinal, seria bem chato ter que copiar arquivo por arquivo =)

Prazer, Ruby

Posted by Alberto Leal on December 8th, 2008

Pessoal,

nos últimos meses intensifiquei os meus estudos em Ruby e Rails. Como podem perceber, meus últimos posts foram emcima dessas tecnologias. E, ao longo da última semana, resolvi pegar alguns dos meus resumos e dar uns “tapas” na formatação e no conteúdo, tentando transformá-los em uma espécie de apostila para aqueles que estão começando com a linguagem e preferem material em português.

Gostaria de convidar a comunidade para contribuir com o trabalho. O projeto está no Github,  portanto, aqueles que quiserem contribuir, basta acessar o link do projeto no Github

 

Abraços

Trabalhando com Ranges

Posted by Alberto Leal on December 8th, 2008

É bastante comum trabalharmos com números sequênciais. E, para isso, não é necessário criarmos uma estrutura de iteração para incrementar um contador, por exemplo.

A melhor forma de se ter número sequênciais, em ruby, é utilizar os ranges

 

Criando um range

Exitem duas maneiras de se criar um range: a primeira é utilizando 2(dois) pontos (..) e a segunda utilizando 3(três) pontos (…) . A diferença entre eles é que quando utilizamos “..” estamos incluindo o último número informado, já com “…” estamos excluindo o último número informado.

numeros = 1..10
numeros2 = 1...10

 

Iterando um range

(1..10).each{|num| puts num}

(1.0..5.0).each{|num| puts num}#error

 

Embora seja permitido se criar um range de Float, não é permitido iterá-lo, visto que a classe Float não possui um método succ

Convertendo para Array

num_array = numeros.to_a #[1,2,3,4,5,6,7,8,9,10]
num2_array = numeros2.to_a #[1,2,3,4,5,6,7,8,9]

Conversão implícita e explícita de Numéricos

Posted by Alberto Leal on December 4th, 2008

Falei sobre conversão implícita/explícita quando estamos trabalhando com String. Agora, chegou a vez de falar um pouco sobre conversões com classes numéricas.

A mesma confusão que encontramos quando falamos sobre os métodos to_s e to_str, encontramos quando nos deparamos com to_i, to_int, to_f, to_flt. Vamos valer da mesma regra que foi apresentada para a classe String: Conversão explícita é para os métodos curtos e implícita para os métodos longos.

Assim como o método to_str, muitas classes não definem os métodos implícitos to_int e to_flt.

Vamos ver um exemplo:

class MeuNumero
  def to_i
    5
  end

  def to_int
    10
  end
end

meu_numero = MeuNumero.new
puts meu_numero.to_i

 

O código acima imprime “5″, visto que chamamos o método explicitamente. Agora, quando o meu método de conversão implícita é executado? Vejamos outro exemplo:

meu_numero = MeuNumero.new
array_meu_numero = Array.new(meu_numero)

 
Ao executarmos o código acima, constatamos que foi criado um array com 10 posições. Isso porque quando passamos o nosso objeto (meu_numero) ele foi implicitamente convertido para um valor numérico para ser passado como parâmetro para a criação de um Array.

Conversão implícita e explícita no Ruby

Posted by Alberto Leal on December 1st, 2008

Existe um pouco de confusão quando estamos falando dos métodos: to_s e to_str. Qualquer objeto, no ruby, pode ser convertido para uma representação em string. Quando olhamos as classes no core nos deparamos com um método to_s (Por exemplo, execute Fixnum.methods e você verá o método), mas não vemos o método to_str. Pense que to_str é para conversão implícita e to_s é para conversão explícita.

Vamos ver um exemplo:

 

class Automovel
  def to_s
    "Carro"
  end

  def to_str
    "Fiat"
  end
end

auto = Automovel.new
puts auto
puts "O automóvel criado foi #{auto}"
puts "O automóvel criado foi " + auto

# Saída COM o método to_str definido
# Alberto:Desktop Alberto$ ruby post.rb
# Carro
# O automóvel criado foi Carro
# O automóvel criado foi Fiat

 

É possível notar que, quando definimos o método to_str estamos forçando uma conversão. Vamos executar o mesmo código acima, porém sem o método to_str definido:

class Automovel
  def to_s
    "Carro"
  end
end

auto = Automovel.new
puts auto
puts "O automóvel criado foi #{auto}"
puts "O automóvel criado foi " + auto

# Saída SEM o método to_str definido
# Alberto:Desktop Alberto$ ruby post.rb
# Carro
# O automóvel criado foi Carro
# post.rb:10:in `+': can't convert Automovel into String (TypeError) from post.rb:10

 

Vale ressaltar que, quando usamos o método puts, esse sempre chama o método to_s do objeto quando desejamos a representação textual de um objeto.

Vamos ver mais um exemplo: Quando tentamos concatenar uma String com um objeto do tipo Fixnum, diretamente, não conseguimos porque a classe Fixnum não possui o método to_str, para conversão implícita.

s = "Número: " + 007
TypeError: can't convert Fixnum into String
    from (irb):3:in `+'
    from (irb):3
    from :0

 

Agora, quando adicionamos o método em tempo de execução a classe Fixnum (via duck typing), conseguimos executar o código que antes acusava TypeError :

class Fixnum
  def to_str
    self.to_s
  end
end

s = "Número: "+ 007

Outra forma de executar o código, sem ter que adicionar o novo método a classe Fixnum, seria chamar o método to_s diretamente:

s = "Número: "+ 007.to_s

Copyright © 2007 Alberto Leal. All rights reserved.