Tool zum Hinzufügen von Lizenz-Headern zu Quelldateien? [geschlossen]

89

Ich suche nach einem Tool, das einigen Quelldateien, von denen einige bereits über den Header verfügen, in großen Mengen einen Lizenzheader hinzufügt. Gibt es ein Tool, das einen Header einfügt, falls dieser noch nicht vorhanden ist?

Bearbeiten: Ich markiere absichtlich keine Antwort auf diese Frage, da die Antworten grundsätzlich alle umweltspezifisch und subjektiv sind

Alex Lyman
quelle
5
"Ich markiere absichtlich keine Antwort auf diese Frage, da die Antworten im Grunde alle umweltspezifisch und subjektiv sind." Suchen Sie eine umweltunabhängige Lösung wie Pseudocode? Wenn nicht, teilen Sie uns bitte mit, mit welcher Umgebung Sie arbeiten.
Jrummell
1
jrummell: Nein, ich suche keine umweltunabhängige Lösung. Ich suchte nach Dingen, die ein Team mit mehreren Umgebungen nutzen konnte.
Alex Lyman
Wäre eine Windows-UI-App, mit der Sie dies tun können, eine akzeptable Antwort?
Brady Moritz
@boomhauer Ich suche eine Windows UI App. Kennen Sie welche?
Jus12
Ich habe unten eine neue Antwort hinzugefügt, die genau dies tun sollte.
Brady Moritz

Antworten:

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
Tim
quelle
1
für i in "$ @" ist eine ziemlich gute Wahl. Sie können auch mit Kassen erfinderisch werden, wenn Ihr VCS-System diese benötigt.
Jonathan Leffler
10
-1, sollten Sie zitieren"$i"
Aleks-Daniel Jakimenko-A.
Ich denke, das funktioniert nicht rekursiv in Unterverzeichnissen :-(
knocte
2
@knocte Ersetzen Sie die for-Schleife durch diese for i in $(find /folder -name '*.cc');, um das Skript in Unterverzeichnissen auszuführen
Joyce
16

Python-Lösung, ändern Sie sie für Ihre eigenen Bedürfnisse

Eigenschaften:

  • behandelt UTF-Header (wichtig für die meisten IDEs)
  • Aktualisiert rekursiv alle Dateien im Zielverzeichnis, wobei die angegebene Maske übergeben wird (ändern Sie den Parameter .endswith für die Dateimaske Ihrer Sprache (.c, .java, ..etc).
  • Möglichkeit, vorherigen Copyright-Text zu überschreiben (geben Sie dazu den alten Copyright-Parameter an)
  • Optional werden Verzeichnisse im ausgeschlossenen Array weggelassen

- -

# 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()
Silberdrache
quelle
6
Es würde wahrscheinlich nicht schaden zu erwähnen, dass Ihr Skript in Python ist.
Dana
16

Überprüfen Sie den Copyright-Header RubyGem. Es unterstützt Dateien mit Erweiterungen, die auf php, c, h, cpp, hpp, hh, rb, css, js, html enden. Es können auch Header hinzugefügt und entfernt werden.

Installieren Sie es, indem Sie " sudo gem install copyright-header" eingeben

Danach kann man so etwas machen wie:

copyright-header --license GPL3 \
  --add-path lib/ \
  --copyright-holder 'Dude1 <[email protected]>' \
  --copyright-holder 'Dude2 <[email protected]>' \
  --copyright-software 'Super Duper' \
  --copyright-software-description "A program that makes life easier" \
  --copyright-year 2012 \
  --copyright-year 2012 \
  --word-wrap 80 --output-dir ./

Es unterstützt auch benutzerdefinierte Lizenzdateien mit dem Argument --license-file.

Erik Osterman
quelle
Dies ist großartig, außer dass es keine benutzerdefinierten vorhandenen Header entfernt :(
pgpb.padilla
3
Sie können vorhandene Header entfernen, wenn Sie eine Vorlage für sie erstellen. Übergeben Sie die Vorlage als Argument an das Skript mit dem --license-fileArgument und entfernen Sie mit dem --remove-pathFlag genau diesen Header aus allen Dateien. Grundsätzlich gibt es so viele verschiedene Arten von Headern, dass es nicht trivial ist, einen Algorithmus zu erstellen, um sie zuverlässig zu entfernen.
Erik Osterman
1
Wir haben kürzlich eine hinzugefügt, Dockerfileso dass die Installation lästiger Rubinabhängigkeiten kein Problem mehr ist
Erik Osterman
15

Hier ist ein Bash-Skript, das den Trick macht, vorausgesetzt, Sie haben den Lizenzheader in der Datei license.txt:

Datei 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  

Führen Sie dies nun in Ihrem Quellverzeichnis aus:

export LICENSELEN=`wc -l license.txt | cut -f1 -d ' '`  
find . -type f \(-name \*.cpp -o -name \*.h \) -print0 | xargs -0 ./addlicense.sh  
Adam Rosenfield
quelle
1
Der sed-Ausdruck funktioniert nicht gut, wenn der Dateiname Ziffern enthält. Verwenden cut -f1 -d ' '
Sie
1
@ Rosenfeld Das abschließende einfache Anführungszeichen fehlt in der Exportanweisung.
Talespin_Kit
Warum benötigen Sie die Klammer im Befehl find? es ist für mich gescheitert
knocte
13

Bearbeiten: Wenn Sie Eclipse verwenden, gibt es ein Plugin

Ich habe ein einfaches Python-Skript geschrieben, das auf der Antwort von Silver Dragon basiert. Ich brauchte eine flexiblere Lösung, also kam ich auf diese. Sie können rekursiv allen Dateien in einem Verzeichnis eine Header-Datei hinzufügen. Sie können optional eine Regex hinzufügen, mit der die Dateinamen übereinstimmen sollen, und eine Regex, mit der die Verzeichnisnamen übereinstimmen sollen, und eine Regex, mit der die erste Zeile in der Datei nicht übereinstimmen soll. Mit diesem letzten Argument können Sie überprüfen, ob der Header bereits enthalten ist.

Dieses Skript überspringt automatisch die erste Zeile in einer Datei, wenn dies mit einem Shebang (#!) Beginnt. Dies, um andere Skripte, die darauf angewiesen sind, nicht zu beschädigen. Wenn Sie dieses Verhalten nicht wünschen, müssen Sie 3 Zeilen in Writeheader auskommentieren.

hier ist es:

#!/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()
Jens Timmerman
quelle
3
Defekter Link für das Plugin
mjaggard
Ich denke, das könnte es sein: wiki.eclipse.org/Development_Resources/…
mbdevpl
Ich konnte nicht gründlich googeln, bevor ich meine eigene Python-Paketversion davon schrieb. Ich werde wahrscheinlich auf Ihre Lösung für zukünftige Verbesserungen zurückgreifen. github.com/zkurtz/license_proliferator
zkurtz
11

Ok, hier ist ein einfaches Nur-Windows-UI-Tool, das in einem Ordner nach allen Dateien Ihres angegebenen Typs sucht, den gewünschten Text nach oben (Ihren Lizenztext) stellt und das Ergebnis in ein anderes Verzeichnis kopiert (um mögliche Probleme beim Überschreiben zu vermeiden). . Es ist auch kostenlos. Erforderlich .Net 4.0.

Ich bin eigentlich der Autor, also zögern Sie nicht, Korrekturen oder neue Funktionen anzufordern ... aber keine Versprechungen bezüglich des Lieferplans. ;)

Weitere Informationen: License Header Tool bei Amazify.com

Brady Moritz
quelle
Ich würde mich auch über Feedback dazu
Brady Moritz
1
Ich mag die Software sehr, aber es ist ein Makro erforderlich, um den Dateinamen in den Header einzugeben. Allso wäre schön, die Liste der zu bearbeitenden Dateien mit der Option zum Ausschließen von Dateien anzuzeigen. (:
hs2d
Danke, Makro und Ausschlussliste ist eine großartige Idee
Brady Moritz
Ihr Link ist abgelaufen. Es ist auch nicht möglich, es von der Website herunterzuladen
Valijon
Danke, ich werde es reparieren lassen
Brady Moritz
5

Überprüfen Sie den Lizenzaddierer. Es unterstützt mehrere Codedateien (auch benutzerdefinierte) und behandelt vorhandene Header korrekt. Kommt bereits mit Vorlagen für die gängigsten Open Source-Lizenzen.

Peter Pratscher
quelle
GitHub findet jetzt: github.com/sanandrea/License-Adder
koppor
4

Hier ist eine, die ich in PHP gerollt habe, um PHP-Dateien zu ändern. Ich hatte auch alte Lizenzinformationen zu löschen, so dass sie zuerst den alten Text ersetzen und dann den neuen Text unmittelbar nach dem Öffnen hinzufügen

<?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();
Josh Ribakoff
quelle
3

Hier ist eine, die ich auf der Apache-Liste gefunden habe. Es ist in Ruby geschrieben und scheint leicht zu lesen zu sein. Sie sollten es sogar von Rechen für besondere Schönheit nennen können. :) :)

Richard Hurt
quelle
1

Wenn Sie noch eines benötigen, habe ich ein kleines Tool namens SrcHead geschrieben . Sie finden es unter http://www.solvasoft.nl/downloads.html


quelle
3
Von der Download-Seite: "Es ist für Windows geschrieben und benötigt .NET Framework 2.0, um zu funktionieren."
Riccardo Murri
Fügt C / C ++ - Style-Header und eine Unicode-Stückliste hinzu. Bedeutung: Der Inhalt von header.txtwird //in jeder Zeile vorangestellt und die erste Zeile beginnt mit der Unicode-Stückliste.
Koppor