Ferramenta para adicionar cabeçalhos de licença aos arquivos de origem? [fechadas]


90

Estou procurando uma ferramenta que irá, em massa, adicionar um cabeçalho de licença a alguns arquivos de origem, alguns dos quais já têm o cabeçalho. Existe alguma ferramenta que insira um cabeçalho, se ainda não estiver presente?

Edit: Eu intencionalmente não estou marcando uma resposta a esta pergunta, uma vez que as respostas são basicamente específicas do ambiente e subjetivas


5
"Eu intencionalmente não estou marcando uma resposta para esta pergunta, uma vez que as respostas são basicamente todas específicas do ambiente e subjetivas" Você está procurando uma solução agnóstica de ambiente, como pseudocódigo? Caso contrário, informe-nos em qual ambiente você está trabalhando.
jrummell de

1
jrummell: Não, não estou procurando uma solução independente do meio ambiente. Estava procurando coisas que uma equipe de vários ambientes de que eu fazia parte pudesse usar.
Alex Lyman

um aplicativo de interface do usuário do Windows que permitisse isso seria uma resposta aceitável?
Brady Moritz,

@boomhauer Estou procurando um aplicativo de interface do usuário do Windows. Você conhece algum?
Jus12,

Eu adicionei uma nova resposta abaixo, ela deve fazer exatamente isso.
Brady Moritz

Respostas:


64
#!/bin/bash

for i in *.cc # or whatever other pattern...
do
  if ! grep -q Copyright $i
  then
    cat copyright.txt $i >$i.new && mv $i.new $i
  fi
done

1
para i em "$ @" é uma escolha muito boa. Você também pode ser criativo com checkouts, se o seu sistema VCS precisar deles.
Jonathan Leffler

10
-1, você deve citar"$i"
Aleks-Daniel Jakimenko-A.

Acho que isso não funciona em subdiretórios recursivamente :-(
knocte

3
@knocte Substitua o for-loop por este for i in $(find /folder -name '*.cc');para executar o script nos subdiretórios
Joyce

16

Solução Python, modifique conforme sua necessidade

Características:

  • lida com cabeçalhos UTF (importante para a maioria dos IDEs)
  • atualiza recursivamente todos os arquivos no diretório de destino passando a máscara dada (modifique o parâmetro .endswith para a máscara de arquivo do seu idioma (.c, .java, ..etc)
  • capacidade de sobrescrever texto de copyright anterior (fornecer parâmetro de copyright antigo para fazer isso)
  • opcionalmente, omite diretórios fornecidos na matriz excludedir

-

# updates the copyright information for all .cs files
# usage: call recursive_traversal, with the following parameters
# parent directory, old copyright text content, new copyright text content

import os

excludedir = ["..\\Lib"]

def update_source(filename, oldcopyright, copyright):
    utfstr = chr(0xef)+chr(0xbb)+chr(0xbf)
    fdata = file(filename,"r+").read()
    isUTF = False
    if (fdata.startswith(utfstr)):
        isUTF = True
        fdata = fdata[3:]
    if (oldcopyright != None):
        if (fdata.startswith(oldcopyright)):
            fdata = fdata[len(oldcopyright):]
    if not (fdata.startswith(copyright)):
        print "updating "+filename
        fdata = copyright + fdata
        if (isUTF):
            file(filename,"w").write(utfstr+fdata)
        else:
            file(filename,"w").write(fdata)

def recursive_traversal(dir,  oldcopyright, copyright):
    global excludedir
    fns = os.listdir(dir)
    print "listing "+dir
    for fn in fns:
        fullfn = os.path.join(dir,fn)
        if (fullfn in excludedir):
            continue
        if (os.path.isdir(fullfn)):
            recursive_traversal(fullfn, oldcopyright, copyright)
        else:
            if (fullfn.endswith(".cs")):
                update_source(fullfn, oldcopyright, copyright)


oldcright = file("oldcr.txt","r+").read()
cright = file("copyrightText.txt","r+").read()
recursive_traversal("..", oldcright, cright)
exit()

6
Provavelmente não faria mal mencionar que seu script está em python.
Dana

16

Verifique o cabeçalho de direitos autorais do RubyGem. Suporta arquivos com extensões que terminam em php, c, h, cpp, hpp, hh, rb, css, js, html. Ele também pode adicionar e remover cabeçalhos.

Instale-o digitando " sudo gem install copyright-header"

Depois disso, pode fazer algo como:

copyright-header --license GPL3 \
  --add-path lib/ \
  --copyright-holder 'Dude1 <dude1@host.com>' \
  --copyright-holder 'Dude2 <dude2@host.com>' \
  --copyright-software 'Super Duper' \
  --copyright-software-description "A program that makes life easier" \
  --copyright-year 2012 \
  --copyright-year 2012 \
  --word-wrap 80 --output-dir ./

Ele também suporta arquivos de licença personalizados usando o argumento --license-file.


Isso é ótimo, exceto que não remove cabeçalhos personalizados existentes :(
pgpb.padilla

3
Você pode remover cabeçalhos existentes se criar um modelo para eles. Passe o modelo como um argumento para o script com o --license-fileargumento e use o --remove-pathsinalizador para retirar o cabeçalho exato de todos os arquivos. Basicamente, existem tantos tipos diferentes de cabeçalhos, criar um algoritmo para removê-los de forma confiável não é trivial.
Erik Osterman

1
Recentemente adicionamos uma Dockerfileinstalação de dependências de ruby ​​onerosas não é mais um problema
Erik Osterman

15

Aqui está um script Bash que fará o truque, supondo que você tenha o cabeçalho da licença no arquivo license.txt:

Arquivo addlicense.sh:

#!/bin/bash  
for x in $*; do  
head -$LICENSELEN $x | diff license.txt - || ( ( cat license.txt; echo; cat $x) > /tmp/file;  
mv /tmp/file $x )  
done  

Agora execute isso em seu diretório de origem:

export LICENSELEN=`wc -l license.txt | cut -f1 -d ' '`  
find . -type f \(-name \*.cpp -o -name \*.h \) -print0 | xargs -0 ./addlicense.sh  

1
A expressão sed não funcionará bem se o nome do arquivo contiver dígitos. Em vez disso, considere usarcut -f1 -d ' '
schweerelos

1
@Rosenfield A aspa simples de fechamento está perdida na declaração de exportação.
Talespin_Kit

por que você precisa do parêntese no comando find? falhou para mim
knocte de

13

Edit: Se você estiver usando o Eclipse, há um plugin

Escrevi um script python simples baseado na resposta do Silver Dragon. Eu precisava de uma solução mais flexível, então pensei nisso. Ele permite que você adicione um headerfile a todos os arquivos em um diretório, recursivamente. Você pode opcionalmente adicionar uma regex que os nomes de arquivo devem corresponder, e uma regex que os nomes de diretório devem corresponder e uma regex que a primeira linha do arquivo não deve corresponder. Você pode usar este último argumento para verificar se o cabeçalho já está incluído.

Este script irá pular automaticamente a primeira linha em um arquivo se este começar com um shebang (#!). Isso para não quebrar outros scripts que dependem disso. Se você não deseja este comportamento, você terá que comentar 3 linhas no cabeçalho de escrita.

Aqui está:

#!/usr/bin/python
"""
This script attempts to add a header to each file in the given directory 
The header will be put the line after a Shebang (#!) if present.
If a line starting with a regular expression 'skip' is present as first line or after the shebang it will ignore that file.
If filename is given only files matchign the filename regex will be considered for adding the license to,
by default this is '*'

usage: python addheader.py headerfile directory [filenameregex [dirregex [skip regex]]]

easy example: add header to all files in this directory:
python addheader.py licenseheader.txt . 

harder example adding someone as copyrightholder to all python files in a source directory,exept directories named 'includes' where he isn't added yet:
python addheader.py licenseheader.txt src/ ".*\.py" "^((?!includes).)*$" "#Copyright .* Jens Timmerman*" 
where licenseheader.txt contains '#Copyright 2012 Jens Timmerman'
"""
import os
import re
import sys

def writeheader(filename,header,skip=None):
    """
    write a header to filename, 
    skip files where first line after optional shebang matches the skip regex
    filename should be the name of the file to write to
    header should be a list of strings
    skip should be a regex
    """
    f = open(filename,"r")
    inpt =f.readlines()
    f.close()
    output = []

    #comment out the next 3 lines if you don't wish to preserve shebangs
    if len(inpt) > 0 and inpt[0].startswith("#!"): 
        output.append(inpt[0])
        inpt = inpt[1:]

    if skip and skip.match(inpt[0]): #skip matches, so skip this file
        return

    output.extend(header) #add the header
    for line in inpt:
        output.append(line)
    try:
        f = open(filename,'w')
        f.writelines(output)
        f.close()
        print "added header to %s" %filename
    except IOError,err:
        print "something went wrong trying to add header to %s: %s" % (filename,err)


def addheader(directory,header,skipreg,filenamereg,dirregex):
    """
    recursively adds a header to all files in a dir
    arguments: see module docstring
    """
    listing = os.listdir(directory)
    print "listing: %s " %listing
    #for each file/dir in this dir
    for i in listing:
        #get the full name, this way subsubdirs with the same name don't get ignored
        fullfn = os.path.join(directory,i) 
        if os.path.isdir(fullfn): #if dir, recursively go in
            if (dirregex.match(fullfn)):
                print "going into %s" % fullfn
                addheader(fullfn, header,skipreg,filenamereg,dirregex)
        else:
            if (filenamereg.match(fullfn)): #if file matches file regex, write the header
                writeheader(fullfn, header,skipreg)


def main(arguments=sys.argv):
    """
    main function: parses arguments and calls addheader
    """
    ##argument parsing
    if len(arguments) > 6 or len(arguments) < 3:
        sys.stderr.write("Usage: %s headerfile directory [filenameregex [dirregex [skip regex]]]\n" \
                         "Hint: '.*' is a catch all regex\nHint:'^((?!regexp).)*$' negates a regex\n"%sys.argv[0])
        sys.exit(1)

    skipreg = None
    fileregex = ".*"
    dirregex = ".*"
    if len(arguments) > 5:
        skipreg = re.compile(arguments[5])
    if len(arguments) > 3:
        fileregex =  arguments[3]
    if len(arguments) > 4:
        dirregex =  arguments[4]
    #compile regex    
    fileregex = re.compile(fileregex)
    dirregex = re.compile(dirregex)
    #read in the headerfile just once
    headerfile = open(arguments[1])
    header = headerfile.readlines()
    headerfile.close()
    addheader(arguments[2],header,skipreg,fileregex,dirregex)

#call the main method
main()

3
Link quebrado para o plugin
mjaggard


Não consegui pesquisar completamente no Google antes de escrever minha própria versão do pacote Python disso. Provavelmente, recorrerei à sua solução para melhorias futuras. github.com/zkurtz/license_proliferator
zkurtz


11

Ok, aqui está uma ferramenta de interface do usuário simples do Windows que procura todos os arquivos do seu tipo especificado em uma pasta, adiciona o texto que você deseja no início (o texto da licença) e copia o resultado para outro diretório (evitando possíveis problemas de substituição) . Também é grátis. Requerido .Net 4.0.

Na verdade, sou o autor, então fique à vontade para solicitar correções ou novos recursos ... sem promessas de prazo de entrega. ;)

mais informações: ferramenta License Header em Amazify.com


Além disso, gostaria de receber qualquer feedback sobre isso, obrigado
Brady Moritz

1
Eu gosto muito do software, mas é necessário uma macro para inserir o nome do arquivo no cabeçalho. Allso seria bom mostrar a lista de arquivos a serem editados com uma opção para excluir arquivos. (:
hs2d

Obrigado, macro e lista de exclusão são uma ótima ideia
Brady Moritz

Seu link expirou. Também não é possível baixá-lo do site
valijon

Obrigado, vou consertá-lo
Brady Moritz

5

Confira o adicionador de licença. Ele oferece suporte a vários arquivos de código (até mesmo os personalizados) e trata os cabeçalhos existentes corretamente. Já vem com modelos para as licenças de código aberto mais comuns.


1
Obrigado por isso, a que license-addervocê está se referindo exatamente? Encontrei o License-Adder - aplicativo .NET gratuito - Google Project Hosting e License-Adder · script python simples · GitHub
sdaau

O GitHub agora encontra: github.com/sanandrea/License-Adder
koppor de

4

Aqui está um que usei em PHP para modificar arquivos PHP. Eu também tinha informações de licença antigas para excluir, para que substituísse o texto antigo primeiro e, em seguida, adicionasse o novo texto imediatamente após a abertura

<?php
class Licenses
{
    protected $paths = array();
    protected $oldTxt = '/**
 * Old license to delete
 */';
    protected $newTxt = '/**
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */';

    function licensesForDir($path)
    {
        foreach(glob($path.'/*') as $eachPath)
        {
            if(is_dir($eachPath))
            {
                $this->licensesForDir($eachPath);
            }
            if(preg_match('#\.php#',$eachPath))
            {
                $this->paths[] = $eachPath;
            }
        }
    }

    function exec()
    {

        $this->licensesForDir('.');
        foreach($this->paths as $path)
        {
            $this->handleFile($path);
        }
    }

    function handleFile($path)
    {
        $source = file_get_contents($path);
        $source = str_replace($this->oldTxt, '', $source);
        $source = preg_replace('#\<\?php#',"<?php\n".$this->newTxt,$source,1);
        file_put_contents($path,$source);
        echo $path."\n";
    }
}

$licenses = new Licenses;
$licenses->exec();

3

Aqui está um que encontrei na lista do Apache. Está escrito em Ruby e parece fácil de ler. Você deve até ser capaz de chamá-lo do rake para uma gentileza especial extra. :)


1

Se você ainda precisar de um, existe uma pequena ferramenta que escrevi, chamada SrcHead . Você pode encontrá-lo em http://www.solvasoft.nl/downloads.html


3
Na página de download: "Ele foi escrito para Windows e precisa do .NET Framework 2.0 para funcionar."
Riccardo Murri

Adiciona cabeçalhos de estilo C / C ++ e um Unicode BOM. Significado: o conteúdo de header.txté prefixado //em cada linha e a primeira linha começa com o Unicode BOM.
koppor de

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.