Strumento per aggiungere intestazioni di licenza ai file di origine? [chiuso]


89

Sto cercando uno strumento che aggiunga in blocco un'intestazione di licenza ad alcuni file sorgente, alcuni dei quali hanno già l'intestazione. C'è uno strumento là fuori che inserirà un'intestazione, se non è già presente?

Modifica: non sto intenzionalmente segnando una risposta a questa domanda, poiché le risposte sono fondamentalmente tutte specifiche dell'ambiente e soggettive


5
"Non sto intenzionalmente contrassegnando una risposta a questa domanda, poiché le risposte sono fondamentalmente tutte specifiche dell'ambiente e soggettive" Stai cercando una soluzione agnostica dell'ambiente, come lo pseudo codice? In caso contrario, facci sapere con quale ambiente stai lavorando.
jrummell

1
jrummell: No, non sto cercando una soluzione indipendente dall'ambiente. Stavo cercando cose che un team multi-ambiente in cui mi trovavo potesse usare.
Alex Lyman

un'app dell'interfaccia utente di Windows che ti consente di farlo sarebbe una risposta accettabile?
Brady Moritz

@boomhauer Sto cercando un'app per l'interfaccia utente di Windows. Ne conosci qualcuno?
Jus12

Ho aggiunto una nuova risposta di seguito, dovrebbe fare proprio questo.
Brady Moritz

Risposte:


61
#!/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
per i in "$ @" è una buona scelta. Puoi anche essere creativo con i checkout se il tuo sistema VCS ne ha bisogno.
Jonathan Leffler

10
-1, dovresti citare"$i"
Aleks-Daniel Jakimenko-A.

Immagino che questo non funzioni in modo ricorsivo nelle sottodirectory :-(
knocte

2
@knocte Sostituisci il ciclo for con questo for i in $(find /folder -name '*.cc');per eseguire lo script nelle sottodirectory
Joyce

16

Soluzione Python, modifica in base alle tue esigenze

Caratteristiche:

  • gestisce le intestazioni UTF (importante per la maggior parte degli IDE)
  • aggiorna ricorsivamente tutti i file nella directory di destinazione passando la maschera data (modifica il parametro .endswith per la maschera di file della tua lingua (.c, .java, ..etc)
  • capacità di sovrascrivere il testo del copyright precedente (fornire il vecchio parametro del copyright per farlo)
  • opzionalmente omette le directory fornite nell'array 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
Probabilmente non sarebbe male menzionare che il tuo script è in Python.
Dana

16

Controlla l' intestazione del copyright RubyGem. Supporta file con estensioni che terminano in php, c, h, cpp, hpp, hh, rb, css, js, html. Può anche aggiungere e rimuovere intestazioni.

Installalo digitando " sudo gem install copyright-header"

Dopodiché, puoi fare qualcosa come:

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 ./

Supporta anche file di licenza personalizzati utilizzando l'argomento --license-file.


Questo è ottimo tranne per il fatto che non rimuove le intestazioni esistenti personalizzate :(
pgpb.padilla

3
Puoi rimuovere le intestazioni esistenti se crei un modello per esse. Passa il modello come argomento allo script con l' --license-fileargomento e usa il --remove-pathflag per rimuovere quell'intestazione esatta da tutti i file. Fondamentalmente, ci sono così tanti diversi tipi di intestazioni, creare un algoritmo per rimuoverli in modo affidabile non è banale.
Erik Osterman

1
Recentemente abbiamo aggiunto un Dockerfilecosì l'installazione di dipendenze ruby ​​onerose non è più un problema
Erik Osterman

15

Ecco uno script Bash che farà il trucco, supponendo che tu abbia l'intestazione della licenza nel file license.txt:

File 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  

Ora eseguilo nella tua directory di origine:

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

1
L'espressione sed non funzionerà bene se il nome del file contiene cifre. Invece, considera l'utilizzo dicut -f1 -d ' '
schweerelos

1
@Rosenfield La virgoletta singola di chiusura viene persa nella dichiarazione di esportazione.
Talespin_Kit

perché hai bisogno delle parentesi nel comando find? non è riuscito per me
knocte

13

Modifica: se stai usando eclipse, c'è un plugin

Ho scritto un semplice script Python basato sulla risposta di Silver Dragon. Avevo bisogno di una soluzione più flessibile, quindi ho pensato a questo. Ti consente di aggiungere un file di intestazione a tutti i file in una directory, in modo ricorsivo. Puoi opzionalmente aggiungere una regex che i nomi dei file dovrebbero corrispondere, e una regex che i nomi delle directory dovrebbero corrispondere e una regex che la prima riga del file non dovrebbe corrispondere. È possibile utilizzare quest'ultimo argomento per verificare se l'intestazione è già inclusa.

Questo script salterà automaticamente la prima riga in un file se inizia con uno shebang (#!). Questo per non rompere altri script che si basano su questo. Se non desideri questo comportamento dovrai commentare 3 righe in writeheader.

Ecco qui:

#!/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 interrotto per il plugin
mjaggard

Penso che potrebbe essere questo: wiki.eclipse.org/Development_Resources/…
mbdevpl

Non sono riuscito a google completamente prima di scrivere la mia versione del pacchetto Python di questo. Probabilmente attingerò alla tua soluzione per miglioramenti futuri. github.com/zkurtz/license_proliferator
zkurtz


11

Ok, ecco un semplice strumento di interfaccia utente solo per Windows che cerca tutti i file del tipo specificato in una cartella, antepone il testo che desideri all'inizio (il testo della tua licenza) e copia il risultato in un'altra directory (evitando potenziali problemi di sovrascrittura) . È anche gratuito. Richiesto .Net 4.0.

In realtà sono l'autore, quindi sentiti libero di richiedere correzioni o nuove funzionalità ... nessuna promessa sui tempi di consegna però. ;)

maggiori informazioni: strumento License Header su Amazify.com


inoltre, apprezzerei qualsiasi feedback su questo, grazie
Brady Moritz

1
Il software mi piace molto, ma è necessaria una macro per inserire il nome del file nell'intestazione. Sarebbe anche bello mostrare l'elenco dei file da modificare con un'opzione per escludere i file. (:
hs2d

Grazie, macro ed elenco di esclusione è un'ottima idea
Brady Moritz

Il tuo link è scaduto. Non è possibile scaricarlo nemmeno dal sito
valijon

Grazie, lo farò riparare
Brady Moritz

5

Dai un'occhiata al sommatore di licenze. Supporta più file di codice (anche quelli personalizzati) e gestisce correttamente le intestazioni esistenti. Viene già fornito con modelli per le licenze Open Source più comuni.


1
Grazie per questo, a cosa license-adderti riferisci esattamente? Ho trovato License-Adder - applicazione .NET gratuita - Google Project Hosting e License-Adder · semplice script python · GitHub
sdaau


4

Eccone uno che ho inserito in PHP per modificare i file PHP. Avevo anche le informazioni sulla vecchia licenza da eliminare, quindi sostituisce prima il vecchio testo, quindi aggiunge il nuovo testo immediatamente dopo l'apertura

<?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

Eccone uno che ho trovato nell'elenco di Apache. È scritto in Ruby e sembra abbastanza facile da leggere. Dovresti anche essere in grado di chiamarlo da rake per una gentilezza speciale. :)


1

Se ne hai ancora bisogno, c'è un piccolo strumento che ho scritto, chiamato SrcHead . Puoi trovarlo su http://www.solvasoft.nl/downloads.html


3
Dalla pagina di download: "È scritto per Windows e necessita di .NET Framework 2.0 per funzionare."
Riccardo Murri

Aggiunge intestazioni in stile C / C ++ e una distinta componenti Unicode. Significato: il contenuto di header.txtè anteposto //a ciascuna riga e la prima riga inizia con Unicode BOM.
koppor

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.