From 41a2044bc849f364d159e3771168ddec6458e746 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 17 Jul 2026 11:22:33 -0400 Subject: [PATCH 1/8] contributing: Define "Other GRASS authors" in COPYING Source file copyright notices are moving to SPDX tags, where the collective holder is spelled "Other GRASS authors". Define it, so that the files carrying it point at something. The definition is by authorship rather than by membership of a body: the authors of a file who are not named individually in it. COPYING already opens by saying GRASS is copyright by members of the GRASS Development Team, so the new text does not restate it. The wording avoids quotation marks and apostrophes deliberately. COPYING is wrapped line by line into C string literals by include/CMakeLists.txt and include/grass/Makefile, neither of which escapes anything, and the file has never contained either character. --- COPYING | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/COPYING b/COPYING index 3490ab98d67..b6ffe7a42c5 100644 --- a/COPYING +++ b/COPYING @@ -4,6 +4,15 @@ The Geographic Resources Analysis and Support System (GRASS) Geographic Information System (GIS) is Copyright by members of the GRASS Development Team. +Copyright notices in individual source files use SPDX tags, for example: + + SPDX-FileCopyrightText: 1999-2022 Jane Doe + SPDX-FileCopyrightText: Other GRASS authors + SPDX-License-Identifier: GPL-2.0-or-later + +Other GRASS authors denotes the authors of a file who are not named +individually in it. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your From cd3c99146b27e9dde48a0b723c02d6f836a3b396 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 17 Jul 2026 11:22:33 -0400 Subject: [PATCH 2/8] doc: Use SPDX copyright tags in style guide header templates Commit 0211182049 replaced the GPL prose in these templates with an SPDX-License-Identifier line and left the COPYRIGHT field alone. Finish that move: replace the field with SPDX-FileCopyrightText lines so the whole notice is machine readable. One holder per line, named holders first, the collective line last, and the license identifier after all copyright lines. COPYING defines the collective. State the rules next to the template, since the templates alone do not say who adds a line or when. Drafted with AI assistance (Claude Opus 4.8); the decisions are the author's. --- doc/development/style_guide.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index a94c872c42d..eb8888bfbb7 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -783,12 +783,19 @@ Use the following header in your source code. # # PURPOSE: Provide short description of module here... # -# COPYRIGHT: (C) 2024 by John Doe and the GRASS Development Team -# +# SPDX-FileCopyrightText: 2024 John Doe +# SPDX-FileCopyrightText: Other GRASS authors # SPDX-License-Identifier: GPL-2.0-or-later ############################################################################## ``` +Each copyright holder gets one `SPDX-FileCopyrightText` line carrying the years +of their own contributions. Add a line for yourself when you make a substantial +contribution, the same threshold as an `AUTHOR(S)` entry, and leave other +people's lines alone. The line `SPDX-FileCopyrightText: Other GRASS authors` +comes last and covers everyone not named individually; the `COPYING` file +defines it. The `SPDX-License-Identifier` line follows all copyright lines. + #### Use Standard Options in Interface GRASS tools must use the GRASS parser to handle its command line parameters. To @@ -975,8 +982,7 @@ Please use the following docstring template: Classes: - example::ExampleClass -(C) 2024 by the GRASS Development Team - +SPDX-FileCopyrightText: 2024 Other GRASS authors SPDX-License-Identifier: GPL-2.0-or-later @author First Author @@ -1093,8 +1099,8 @@ original work remains, it must be properly cited. * MODULE: g.foo * AUTHOR(S): John Doe * PURPOSE: Provide short description of module here... - * COPYRIGHT: (C) 2010 by John Doe, and the GRASS Development Team - * + * SPDX-FileCopyrightText: 2010 John Doe + * SPDX-FileCopyrightText: Other GRASS authors * SPDX-License-Identifier: GPL-2.0-or-later * *****************************************************************************/ From ae749690fbf1a3be9c1f87a62863c544f01eb51e Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 17 Jul 2026 11:22:33 -0400 Subject: [PATCH 3/8] g.parser: Emit SPDX copyright header from --script Scripts generated by --script carried a COPYRIGHT field and the full GPL paragraph. Emit SPDX tags instead, matching the style guide templates, so that generated scripts start out in the form the project documents. GRASS_VERSION_DATE is a bare year, so it feeds SPDX-FileCopyrightText unchanged. Update the sample output in both g.parser.md and g.parser.html in the same commit, so the documentation never shows a header the tool cannot produce. Convert this file's own header as well: a generator that emits SPDX tags while carrying a legacy notice contradicts itself. The remaining files using the bare (C) notice form are out of scope here. Drafted with AI assistance (Claude Opus 4.8); the decisions are the author's. --- general/g.parser/g.parser.html | 14 +++----------- general/g.parser/g.parser.md | 14 +++----------- lib/gis/parser_script.c | 32 ++++++-------------------------- 3 files changed, 12 insertions(+), 48 deletions(-) diff --git a/general/g.parser/g.parser.html b/general/g.parser/g.parser.html index e6329a46517..e395a977afc 100644 --- a/general/g.parser/g.parser.html +++ b/general/g.parser/g.parser.html @@ -565,17 +565,9 @@

Easy creation of a script

# MODULE: v.what.rast_wrapper # AUTHOR(S): username # PURPOSE: Wrapper for v.what.rast -# COPYRIGHT: (C) 2017 by username, and the GRASS Development Team -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# SPDX-FileCopyrightText: 2017 username +# SPDX-FileCopyrightText: Other GRASS authors +# SPDX-License-Identifier: GPL-2.0-or-later # ############################################################################ diff --git a/general/g.parser/g.parser.md b/general/g.parser/g.parser.md index d690724ea2d..58bcd83ad70 100644 --- a/general/g.parser/g.parser.md +++ b/general/g.parser/g.parser.md @@ -556,17 +556,9 @@ v.what.rast --script # MODULE: v.what.rast_wrapper # AUTHOR(S): username # PURPOSE: Wrapper for v.what.rast -# COPYRIGHT: (C) 2017 by username, and the GRASS Development Team -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# SPDX-FileCopyrightText: 2017 username +# SPDX-FileCopyrightText: Other GRASS authors +# SPDX-License-Identifier: GPL-2.0-or-later # ############################################################################ diff --git a/lib/gis/parser_script.c b/lib/gis/parser_script.c index 5b3dfa8eefd..e495a30b1a8 100644 --- a/lib/gis/parser_script.c +++ b/lib/gis/parser_script.c @@ -3,10 +3,8 @@ \brief GIS Library - Argument parsing functions (script) - (C) 2001-2009, 2011 by the GRASS Development Team - - This program is free software under the GNU General Public License - (>=v2). Read the file COPYING that comes with GRASS for details. + SPDX-FileCopyrightText: 2001-2009, 2011 Other GRASS authors + SPDX-License-Identifier: GPL-2.0-or-later \author Original author CERL \author Soeren Gebbert added Dec. 2009 WPS process_description document @@ -33,28 +31,10 @@ void G__script(void) fprintf(fp, "# MODULE: %s_wrapper\n", G_program_name()); fprintf(fp, "# AUTHOR(S): %s\n", G_whoami()); fprintf(fp, "# PURPOSE: Wrapper for %s\n", G_program_name()); - fprintf(fp, - "# COPYRIGHT: (C) %s by %s, and the GRASS Development Team\n", - GRASS_VERSION_DATE, G_whoami()); - fprintf(fp, "#\n"); - fprintf(fp, "# This program is free software; you can redistribute it " - "and/or modify\n"); - fprintf(fp, "# it under the terms of the GNU General Public License as " - "published by\n"); - fprintf(fp, "# the Free Software Foundation; either version 2 of the " - "License, or\n"); - fprintf(fp, "# (at your option) any later version.\n"); - fprintf(fp, "#\n"); - fprintf( - fp, - "# This program is distributed in the hope that it will be useful,\n"); - fprintf( - fp, - "# but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - fprintf( - fp, - "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); - fprintf(fp, "# GNU General Public License for more details.\n"); + fprintf(fp, "# SPDX-FileCopyrightText: %s %s\n", GRASS_VERSION_DATE, + G_whoami()); + fprintf(fp, "# SPDX-FileCopyrightText: Other GRASS authors\n"); + fprintf(fp, "# SPDX-License-Identifier: GPL-2.0-or-later\n"); fprintf(fp, "#\n"); fprintf(fp, "##############################################################" "##############\n\n"); From 173ae42ed0dc0ecb195fe87923b3a74bd12b5448 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 17 Jul 2026 11:22:33 -0400 Subject: [PATCH 4/8] g.parser: Add test for --script output header Check the properties the header has to hold to rather than its exact text: that no COPYRIGHT field or GPL paragraph survives in the generated script, and that each copyright line names one holder with the collective line last. Comparing against a copy of the template would only restate what parser_script.c already defines, and would need updating whenever that file changes, so it would report edits rather than find faults. Written with AI assistance (Claude Opus 4.8); the decisions are the author's. --- .../g.parser/tests/g_parser_script_test.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 general/g.parser/tests/g_parser_script_test.py diff --git a/general/g.parser/tests/g_parser_script_test.py b/general/g.parser/tests/g_parser_script_test.py new file mode 100644 index 00000000000..c1eda170970 --- /dev/null +++ b/general/g.parser/tests/g_parser_script_test.py @@ -0,0 +1,63 @@ +"""Tests of the header emitted by g.parser --script + +The header is produced by G__script() in lib/gis/parser_script.c. +""" + +import os +import re + +import pytest + +import grass.script as gs +from grass.tools import Tools + +TOOL = "v.what.rast" + + +@pytest.fixture(scope="module") +def session(tmp_path_factory): + """Set up a GRASS session for the tests.""" + tmp_path = tmp_path_factory.mktemp("grass_session") + project = "test_project" + gs.create_project(tmp_path, project) + with gs.setup.init(tmp_path / project, env=os.environ.copy()) as session: + yield session + + +@pytest.fixture(scope="module") +def script(session): + """Return the script generated by TOOL --script.""" + tools = Tools(session=session) + return tools.run_cmd([TOOL, "--script"]).stdout + + +def test_script_header_has_no_obsolete_license_text(script): + """The generated header carries no COPYRIGHT field and no GPL paragraph.""" + for obsolete in ("COPYRIGHT:", "free software", "GNU General Public License"): + assert obsolete not in script, ( + f"Generated script still contains obsolete license text: {obsolete!r}" + ) + + +def test_script_header_has_one_holder_per_line(script): + """Each copyright line names one holder, and the collective one comes last.""" + lines = script.splitlines() + copyright_lines = [ + i for i, line in enumerate(lines) if "SPDX-FileCopyrightText:" in line + ] + identifiers = [ + i for i, line in enumerate(lines) if "SPDX-License-Identifier:" in line + ] + + assert len(identifiers) == 1, "Expected exactly one SPDX-License-Identifier line." + assert copyright_lines, "Expected at least one SPDX-FileCopyrightText line." + assert max(copyright_lines) < identifiers[0], ( + "All SPDX-FileCopyrightText lines must precede SPDX-License-Identifier." + ) + assert ( + lines[max(copyright_lines)] == "# SPDX-FileCopyrightText: Other GRASS authors" + ), "The last copyright line must be the collective line." + for i in copyright_lines: + assert not re.search(r",\s+and\s|\sand\sthe\s", lines[i]), ( + f"Copyright line names more than one holder: {lines[i]!r}" + ) From 6dcf534b9eb7aa7ef342f12694966c70a98bfe02 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 17 Jul 2026 11:22:33 -0400 Subject: [PATCH 5/8] utils: Remove unused copywrite.pl The script is unreferenced, and it cannot run: it shells out to cvs2cl.pl, which is not in the repository and which reads CVS history that no longer exists, and it hardcodes launching xemacs. It also embeds a third header template, which would otherwise have to be kept in sync with the style guide and with g.parser --script. Its method, deriving copyright holders by parsing commit history, is not one the project wants to carry forward. Removing the file does not strip a copyright notice from any surviving file, and its authorship remains in the history. --- utils/copywrite.pl | 191 --------------------------------------------- 1 file changed, 191 deletions(-) delete mode 100755 utils/copywrite.pl diff --git a/utils/copywrite.pl b/utils/copywrite.pl deleted file mode 100755 index 6cebce8e140..00000000000 --- a/utils/copywrite.pl +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/perl - -## Script to easily add missing copyright statements in -## GRASS source code files -## 2006, written by Schuyler Erle -## -## COPYRIGHT: (C) 2006 by the GRASS Development Team -## -## This program is free software under the GNU General Public -## License (>=v2). Read the file COPYING that comes with GRASS -## for details. -## -## The script searches and opens sequentially all files -## which lack the word "copyright". Additionally the local -## ChangeLog is fetched and contributor names are extracted. -## Then a new header is inserted containing the GPL statement, -## purpose template and authors. -## -## Please run from top source code directory. -## For usage details, see below. - -use File::Find; -use File::Basename; -use strict; -use warnings; -use Cwd; -use File::Basename; - -#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-# -# edit this, and edit the bottom of the file after __END__ - -# my $editor = "vi -o"; -# my $editor = "nedit"; -my $editor = "xemacs"; - -# don't forget to get a copy of -# http://www.red-bean.com/cvs2cl/cvs2cl.pl -# and put it in the same directory as this script -# -# run this script as: -# perl copywrite.pl contributors.csv -# committer identities can be provided in a file on the commandline -# the format of the file should be "username,identity", one per line -# The contributors.csv is already in the main directory of the GRASS -# source code, so it should be found. - -#### -# to work offline: -# $ export PATH=$PATH:$(pwd) -# $ find . -name main.c | while read i; do \ -# echo $i; (cd `dirname $i`; cvs2cl.pl -f ChangeLog.tmp main.c); done -# -# to clean up after: -# $ find -name ChangeLog.tmp | xargs rm -# -# otherwise, this script will assume you are online and fetch -# the ChangeLogs on the fly (and remove them automatically). -# -#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-#-=-# - -my $ChangeLog = "ChangeLog.tmp"; -my $cvs2cl = getcwd . "/cvs2cl.pl -f $ChangeLog"; -my $template = do {local $/; }; -my %identity; - -sub evaluate_file { - my $name = do { no warnings; $File::Find::name }; - - # only process main.c - return unless $_ eq 'main.c'; - - warn "+ Reading $name\n"; - - # slurp main.c - my $main_c = do {local $/; open my $F, '<', $_ or die "reading $name: $!"; <$F>}; - - # continue if main.c is 25 lines or longer - return unless ($main_c =~ y/\n/\n/) >= 25; - - # continue if main.c doesn't mention "copyright" - return if $main_c =~ /\(?c\)?opyright/gios; - - # run cvs2cl - warn "+ Checking CVS log $name\n"; - my $fetched_ChangeLog = 0; - unless (-f $ChangeLog) { - system "$cvs2cl $_" and die "$cvs2cl $_: $!"; - $fetched_ChangeLog++; - } - - # get the list of contributors - my (%username, %year, $user); - my $original_author = ""; - { - # Read whole paras at once - local $/ = ""; - open my $LOG, '<', $ChangeLog or die "$ChangeLog: $!"; - while (my $line = $LOG) { - - # Hack out the pretty printing - $line =~ s/\s+/ /gos; - - # And drop trailing spaces - $line =~ s/\s+$//gos; - - # Match individual check ins - if ($line =~ /^(\d{4})-\d\d-\d\d\s+\d\d:\d\d\s+(.+)$/gos) { - $year{$1}++; - $user = $2; - $username{$user}++; - } - - # Note when a user did the initial check in - # if ($line =~ /^\s+\*\s+[^:]+:\s+(?:initial|new$)/gios) { - # $original_author = $user; - # } - $original_author = $user; - - # Note when a contributor submitted code - if ($line =~ /:\s+([^:<]+\s*<[^>]+>)\s*:/gos) { - $username{$1}++; - } - } - } - - # don't duplicate the original author - delete $username{$original_author} if $original_author; - - #figure out module name - my $fullname = $name; - my $mymodule = basename(dirname($fullname)); - - # append the list of contributors - my @years = sort map {$_ + 0} keys %year; - my @authors = sort keys %username; - - # map committers to identities - @authors = map { exists( $identity{$_} ) ? $identity{$_} : $_ } @authors; - $original_author = $identity{$original_author} - if exists $identity{$original_author}; - - # execute the template - { - local $" = ", "; - $main_c = eval{ - "<', $_ or die "writing $name: $!"; - print F $main_c; - close F; - - # load it up in an editor for vetting - system "$editor $_ $ChangeLog description.html" and die "$editor $_ $ChangeLog: $!"; - - # delete the ChangeLog after *only* if this script created it - unlink $ChangeLog if $fetched_ChangeLog; -} - -# committer identities can be provided in a file on the commandline -# the format of the file should be "username,identity", one per line -# -if ($ARGV[0]) { - while (<>) { - chomp; - next unless /^[a-z]/ios; - my ($user, $id) = split(",", $_, 2); - $identity{$user} = $id; - } -} - -find( \&evaluate_file, "." ); - -### edit the template after __END__ -__END__ -/**************************************************************************** - * - * MODULE: $mymodule - * AUTHOR(S): $original_author (original contributor) - * @authors - * PURPOSE: - * COPYRIGHT: (C) $years[0]-$years[-1] by the GRASS Development Team - * - * This program is free software under the GNU General Public - * License (>=v2). Read the file COPYING that comes with GRASS - * for details. - * - *****************************************************************************/ -$main_c From 3ade3fe8a96972d95f03ff2e02def4458ab35362 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Sat, 29 Aug 2026 06:27:37 -0400 Subject: [PATCH 6/8] contributing: Use GRASS Development Team as the collective copyright line Replace "Other GRASS authors" with "GRASS Development Team", the name the notices used before, so the collective line keeps the established holder name rather than introducing a new term. COPYING keeps defining what the line stands for. --- COPYING | 6 +++--- doc/development/style_guide.md | 13 +++++++------ general/g.parser/g.parser.html | 2 +- general/g.parser/g.parser.md | 2 +- general/g.parser/tests/g_parser_script_test.py | 3 ++- lib/gis/parser_script.c | 4 ++-- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/COPYING b/COPYING index b6ffe7a42c5..5ad8f63f587 100644 --- a/COPYING +++ b/COPYING @@ -7,11 +7,11 @@ of the GRASS Development Team. Copyright notices in individual source files use SPDX tags, for example: SPDX-FileCopyrightText: 1999-2022 Jane Doe - SPDX-FileCopyrightText: Other GRASS authors + SPDX-FileCopyrightText: GRASS Development Team SPDX-License-Identifier: GPL-2.0-or-later -Other GRASS authors denotes the authors of a file who are not named -individually in it. +The GRASS Development Team line stands for the authors of a file who are +not named individually in it. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index eb8888bfbb7..5fbc8446465 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -784,7 +784,7 @@ Use the following header in your source code. # PURPOSE: Provide short description of module here... # # SPDX-FileCopyrightText: 2024 John Doe -# SPDX-FileCopyrightText: Other GRASS authors +# SPDX-FileCopyrightText: GRASS Development Team # SPDX-License-Identifier: GPL-2.0-or-later ############################################################################## ``` @@ -792,9 +792,10 @@ Use the following header in your source code. Each copyright holder gets one `SPDX-FileCopyrightText` line carrying the years of their own contributions. Add a line for yourself when you make a substantial contribution, the same threshold as an `AUTHOR(S)` entry, and leave other -people's lines alone. The line `SPDX-FileCopyrightText: Other GRASS authors` -comes last and covers everyone not named individually; the `COPYING` file -defines it. The `SPDX-License-Identifier` line follows all copyright lines. +people's lines alone. The line +`SPDX-FileCopyrightText: GRASS Development Team` comes last and covers everyone +not named individually; the `COPYING` file defines it. The +`SPDX-License-Identifier` line follows all copyright lines. #### Use Standard Options in Interface @@ -982,7 +983,7 @@ Please use the following docstring template: Classes: - example::ExampleClass -SPDX-FileCopyrightText: 2024 Other GRASS authors +SPDX-FileCopyrightText: 2024 GRASS Development Team SPDX-License-Identifier: GPL-2.0-or-later @author First Author @@ -1100,7 +1101,7 @@ original work remains, it must be properly cited. * AUTHOR(S): John Doe * PURPOSE: Provide short description of module here... * SPDX-FileCopyrightText: 2010 John Doe - * SPDX-FileCopyrightText: Other GRASS authors + * SPDX-FileCopyrightText: GRASS Development Team * SPDX-License-Identifier: GPL-2.0-or-later * *****************************************************************************/ diff --git a/general/g.parser/g.parser.html b/general/g.parser/g.parser.html index e395a977afc..642175838f4 100644 --- a/general/g.parser/g.parser.html +++ b/general/g.parser/g.parser.html @@ -566,7 +566,7 @@

Easy creation of a script

# AUTHOR(S): username # PURPOSE: Wrapper for v.what.rast # SPDX-FileCopyrightText: 2017 username -# SPDX-FileCopyrightText: Other GRASS authors +# SPDX-FileCopyrightText: GRASS Development Team # SPDX-License-Identifier: GPL-2.0-or-later # ############################################################################ diff --git a/general/g.parser/g.parser.md b/general/g.parser/g.parser.md index 58bcd83ad70..ae4eca3d6ca 100644 --- a/general/g.parser/g.parser.md +++ b/general/g.parser/g.parser.md @@ -557,7 +557,7 @@ v.what.rast --script # AUTHOR(S): username # PURPOSE: Wrapper for v.what.rast # SPDX-FileCopyrightText: 2017 username -# SPDX-FileCopyrightText: Other GRASS authors +# SPDX-FileCopyrightText: GRASS Development Team # SPDX-License-Identifier: GPL-2.0-or-later # ############################################################################ diff --git a/general/g.parser/tests/g_parser_script_test.py b/general/g.parser/tests/g_parser_script_test.py index c1eda170970..fb8bad586c4 100644 --- a/general/g.parser/tests/g_parser_script_test.py +++ b/general/g.parser/tests/g_parser_script_test.py @@ -55,7 +55,8 @@ def test_script_header_has_one_holder_per_line(script): "All SPDX-FileCopyrightText lines must precede SPDX-License-Identifier." ) assert ( - lines[max(copyright_lines)] == "# SPDX-FileCopyrightText: Other GRASS authors" + lines[max(copyright_lines)] + == "# SPDX-FileCopyrightText: GRASS Development Team" ), "The last copyright line must be the collective line." for i in copyright_lines: assert not re.search(r",\s+and\s|\sand\sthe\s", lines[i]), ( diff --git a/lib/gis/parser_script.c b/lib/gis/parser_script.c index e495a30b1a8..67abc4d952a 100644 --- a/lib/gis/parser_script.c +++ b/lib/gis/parser_script.c @@ -3,7 +3,7 @@ \brief GIS Library - Argument parsing functions (script) - SPDX-FileCopyrightText: 2001-2009, 2011 Other GRASS authors + SPDX-FileCopyrightText: 2001-2009, 2011 GRASS Development Team SPDX-License-Identifier: GPL-2.0-or-later \author Original author CERL @@ -33,7 +33,7 @@ void G__script(void) fprintf(fp, "# PURPOSE: Wrapper for %s\n", G_program_name()); fprintf(fp, "# SPDX-FileCopyrightText: %s %s\n", GRASS_VERSION_DATE, G_whoami()); - fprintf(fp, "# SPDX-FileCopyrightText: Other GRASS authors\n"); + fprintf(fp, "# SPDX-FileCopyrightText: GRASS Development Team\n"); fprintf(fp, "# SPDX-License-Identifier: GPL-2.0-or-later\n"); fprintf(fp, "#\n"); fprintf(fp, "##############################################################" From 2a8d40893d58924e258673123fd1ec2658380158 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Wed, 16 Sep 2026 22:22:21 -0400 Subject: [PATCH 7/8] contributing: Leave COPYING unchanged and describe the team line as the project The paragraph added to COPYING defined GRASS Development Team as the authors of a file who are not named individually, which reads as changing what the existing copyright holder means. COPYING already states that GRASS is copyright by members of the GRASS Development Team, so drop the addition and let the style guide point to that. --- COPYING | 9 --------- doc/development/style_guide.md | 12 ++++++------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/COPYING b/COPYING index 5ad8f63f587..3490ab98d67 100644 --- a/COPYING +++ b/COPYING @@ -4,15 +4,6 @@ The Geographic Resources Analysis and Support System (GRASS) Geographic Information System (GIS) is Copyright by members of the GRASS Development Team. -Copyright notices in individual source files use SPDX tags, for example: - - SPDX-FileCopyrightText: 1999-2022 Jane Doe - SPDX-FileCopyrightText: GRASS Development Team - SPDX-License-Identifier: GPL-2.0-or-later - -The GRASS Development Team line stands for the authors of a file who are -not named individually in it. - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index 5fbc8446465..42b465aa108 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -789,12 +789,12 @@ Use the following header in your source code. ############################################################################## ``` -Each copyright holder gets one `SPDX-FileCopyrightText` line carrying the years -of their own contributions. Add a line for yourself when you make a substantial -contribution, the same threshold as an `AUTHOR(S)` entry, and leave other -people's lines alone. The line -`SPDX-FileCopyrightText: GRASS Development Team` comes last and covers everyone -not named individually; the `COPYING` file defines it. The +Each `SPDX-FileCopyrightText` line names one copyright holder with the years +of their contributions. The line `SPDX-FileCopyrightText: GRASS Development +Team` is present in every file and stands for the project, as `COPYING` +states; it carries years only when it is the sole copyright line. Add a line +for yourself when you make a substantial contribution, the same threshold as +an `AUTHOR(S)` entry, and leave other people's lines alone. The `SPDX-License-Identifier` line follows all copyright lines. #### Use Standard Options in Interface From ffe523793dc69f1ac9e28e700f25f5fcfafd3e0f Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Wed, 16 Sep 2026 23:07:19 -0400 Subject: [PATCH 8/8] contributing: Simplify the wording of the copyright header rules --- doc/development/style_guide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index 42b465aa108..524decabbcb 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -790,12 +790,12 @@ Use the following header in your source code. ``` Each `SPDX-FileCopyrightText` line names one copyright holder with the years -of their contributions. The line `SPDX-FileCopyrightText: GRASS Development -Team` is present in every file and stands for the project, as `COPYING` -states; it carries years only when it is the sole copyright line. Add a line -for yourself when you make a substantial contribution, the same threshold as -an `AUTHOR(S)` entry, and leave other people's lines alone. The -`SPDX-License-Identifier` line follows all copyright lines. +of their contributions. The line with `GRASS Development Team` is present +in every file and stands for the project, as `COPYING` states. +It carries years only when it is the sole copyright line. Add a line +for yourself when you make a substantial contribution (the same threshold as +an `AUTHOR(S)` entry), and leave other people's lines alone. +The `SPDX-License-Identifier` line follows all copyright lines. #### Use Standard Options in Interface