Page MenuHomePhabricator

Consolidate source code licenses to single line per file
Open, Needs TriagePublic

Description

GPL
/**
 * 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.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 */

You're probably wondering what this task is about but needed to read past that legal preamble. Sorry about that. Just try to ignore it so we can focus on the task. I am not a lawyer but as a coder, I claim that unnecessary legal notices should be avoided as they compound and create significant noise as much as any boilerplate does.

For example, consider a typical GPL license like the one above ^. Imagine this was at the start of every page of your favorite book and you'll quickly understand how distracting it can be! It is my understanding that the suggested usage is to copy and paste this legal notice into the top of every file of every project. That's a lot of text to ignore! Fortunately, many editors help diminish the visual impact these license blocks have but that is a workaround, non-default configuration, and not all tooling can support it. For example, ripgrep supports ignoring specific files like:

.rgignore
license
LICENSE
license.txt
LICENSE.txt
package-lock.json
COPYING

But ignoring entire passages of code that is actually legalese is less straightforward when it's intermingled with real code. I would even go so far as to claim that it adds a micro-friction to getting things done and Grep help you if you have to search for a term that happens to appear in the legal preamble for a repo that religiously adheres to per file licensing! I think it would be far more ideal from a development perspective to use a single line license reference if that's legally viable to do so.

In fact, there are already many files that do not have any licensing information. While this isn't justification to do the wrong thing, it does exemplify that simply saying this per file licensing is necessary doesn't make it so.

As an example, from MinervaNeue's menu entries:

MinervaNeue/includes/menu/Entries
find includes/menu/Entries -type f -name \*.php|xargs -rd\\n wc -l
   35 includes/menu/Entries/LogInMenuEntry.php
   48 includes/menu/Entries/IMenuEntry.php
   68 includes/menu/Entries/AuthMenuEntry.php
  149 includes/menu/Entries/SingleMenuEntry.php
   54 includes/menu/Entries/CompositeMenuEntry.php
   95 includes/menu/Entries/MenuEntry.php
  116 includes/menu/Entries/LanguageSelectorEntry.php
   40 includes/menu/Entries/LogOutMenuEntry.php
  103 includes/menu/Entries/HomeMenuEntry.php
   40 includes/menu/Entries/IProfileMenuEntry.php
   93 includes/menu/Entries/ProfileMenuEntry.php
  841 total

The license is 14 lines long and there are 11 files so 154 lines or 18.5% of the code is licensing.

I propose to strategically replace this licensing information with a single attribution per file similar to how all of Wikibase does. In my opinion, this will improve the readability, grepability, and consistency of all code.

There seems to be precedence for single line licenses @license usage suggetings it's a defacto convention already:

462 projects with one or more @license references
Assert
CLDRPluralRuleParser
Extension:AbuseFilter
Extension:AccessControl
Extension:AddThis
Extension:AdvancedSearch
Extension:AkismetKlik
Extension:Arrays
Extension:ArticleMetaDescription
Extension:ArticlePlaceholder
Extension:ArticleToCategory2
Extension:Athena
Extension:Awesomeness
Extension:AzharAuth
Extension:Babel
Extension:BetaFeatures
Extension:BibManager
Extension:BlockAndNuke
Extension:BlogPage
Extension:BlueSpiceAbout
Extension:BlueSpiceArticleInfo
Extension:BlueSpiceArticlePreviewCapture
Extension:BlueSpiceAuthors
Extension:BlueSpiceAvatars
Extension:BlueSpiceBookshelf
Extension:BlueSpiceBookshelfUI
Extension:BlueSpiceCategoryManager
Extension:BlueSpiceChecklist
Extension:BlueSpiceConfigManager
Extension:BlueSpiceContextMenu
Extension:BlueSpiceCountThings
Extension:BlueSpiceCustomMenu
Extension:BlueSpiceDashboards
Extension:BlueSpiceEditNotifyConnector
Extension:BlueSpiceEmoticons
Extension:BlueSpiceExpiry
Extension:BlueSpiceExportTables
Extension:BlueSpiceExtendedSearch
Extension:BlueSpiceExtendedStatistics
Extension:BlueSpiceFilterableTables
Extension:BlueSpiceFoundation
Extension:BlueSpiceGroupManager
Extension:BlueSpiceHideTitle
Extension:BlueSpiceInsertCategory
Extension:BlueSpiceInsertFile
Extension:BlueSpiceInsertLink
Extension:BlueSpiceInsertMagic
Extension:BlueSpiceInsertTemplate
Extension:BlueSpiceInterWikiLinks
Extension:BlueSpiceNSFileRepoConnector
Extension:BlueSpiceNamespaceCSS
Extension:BlueSpiceNamespaceManager
Extension:BlueSpicePageAccess
Extension:BlueSpicePageAssignments
Extension:BlueSpicePageTemplates
Extension:BlueSpicePagesVisited
Extension:BlueSpicePermissionManager
Extension:BlueSpiceRSSFeeder
Extension:BlueSpiceRating
Extension:BlueSpiceReaders
Extension:BlueSpiceReminder
Extension:BlueSpiceSMWConnector
Extension:BlueSpiceSaferEdit
Extension:BlueSpiceSignHere
Extension:BlueSpiceSmartList
Extension:BlueSpiceSocial
Extension:BlueSpiceSocialArticleActions
Extension:BlueSpiceSocialBlog
Extension:BlueSpiceSocialComments
Extension:BlueSpiceSocialMicroBlog
Extension:BlueSpiceSocialProfile
Extension:BlueSpiceSocialRating
Extension:BlueSpiceSocialResolve
Extension:BlueSpiceSocialTags
Extension:BlueSpiceSocialTimelineUpdate
Extension:BlueSpiceSocialTopics
Extension:BlueSpiceSocialWatch
Extension:BlueSpiceSocialWikiPage
Extension:BlueSpiceTagCloud
Extension:BlueSpiceUEModuleBookPDF
Extension:BlueSpiceUEModuleDOCX
Extension:BlueSpiceUEModuleHTML
Extension:BlueSpiceUEModulePDF
Extension:BlueSpiceUEModulePDFRecursive
Extension:BlueSpiceUEModulePDFSubpages
Extension:BlueSpiceUEModuleTable2Excel
Extension:BlueSpiceUniversalExport
Extension:BlueSpiceUsageTracker
Extension:BlueSpiceUserInfo
Extension:BlueSpiceUserManager
Extension:BlueSpiceUserSidebar
Extension:BlueSpiceVisualDiff
Extension:BlueSpiceVisualEditorConnector
Extension:BlueSpiceWatchList
Extension:BlueSpiceWhoIsOnline
Extension:BlueSpiceWikiExplorer
Extension:BounceHandler
Extension:BreadCrumbs
Extension:BreadCrumbs2
Extension:Buggy
Extension:CSS
Extension:Capiunto
Extension:CategoryTree
Extension:CentralAuth
Extension:CentralNotice
Extension:ChangeAuthor
Extension:Cite
Extension:Citoid
Extension:CleanChanges
Extension:Cognate
Extension:Comments
Extension:ContactPage
Extension:ContentTranslation
Extension:CreateAPage
Extension:CreatePage
Extension:DebugMode
Extension:DebugTemplates
Extension:DeleteOwn
Extension:DeleteUserPages
Extension:Description2
Extension:Disambiguator
Extension:DiscussionTools
Extension:DismissableSiteNotice
Extension:Drafts
Extension:DynamicPageList
Extension:Echo
Extension:EditSimilar
Extension:ElectronPdfService
Extension:EmailCapture
Extension:EmailDiff
Extension:EnhanceContactForm
Extension:EntitySchema
Extension:ErrorHandler
Extension:EtherpadLite
Extension:EventLogging
Extension:ExternalGuidance
Extension:FanBoxes
Extension:Farmer
Extension:FileAnnotations
Extension:FileExporter
Extension:FileImporter
Extension:FilterListUsers
Extension:Flow
Extension:FlvHandler
Extension:ForcePreview
Extension:FormWizard
Extension:GWToolset
Extension:Gadgets
Extension:GlobalBlocking
Extension:GlobalNotice
Extension:GlobalPreferences
Extension:GlobalUserGroups
Extension:GlobalUserrights
Extension:GoogleAdSense
Extension:GoogleAppEngine
Extension:GoogleDocs4MW
Extension:Graph
Extension:GraphQL
Extension:HAWelcome
Extension:HTMLets
Extension:HashTables
Extension:HelpCommons
Extension:HelpPages
Extension:HitCounters
Extension:Html2Wiki
Extension:I18nTags
Extension:IfTemplates
Extension:ImageTweaks
Extension:ImportArticles
Extension:ImportFreeImages
Extension:ImportUsers
Extension:InlineCategorizer
Extension:InputBox
Extension:InteractiveBlockMessage
Extension:InterwikiSorting
Extension:InviteSignup
Extension:Jade
Extension:JsonConfig
Extension:JsonData
Extension:Kartographer
Extension:LabeledSectionTransclusion
Extension:LanguageSelector
Extension:LifeWeb
Extension:Lingo
Extension:LinkSuggest
Extension:LinkTarget
Extension:Link_Attributes
Extension:LinkedWiki
Extension:LiquidThreads
Extension:LiveTranslate
Extension:LocalisationUpdate
Extension:LockDownEnglishPages
Extension:Lockdown
Extension:LogEntry
Extension:LoopFunctions
Extension:MagicNoCache
Extension:MagicNumberedHeadings
Extension:Mailgun
Extension:MaintenanceShell
Extension:MapSources
Extension:MassEditRegex
Extension:MassMessage
Extension:MassMessageEmail
Extension:Math
Extension:MathSearch
Extension:MediaFunctions
Extension:MediaWikiFarm
Extension:MessageCommons
Extension:MixedNamespaceSearchSuggestions
Extension:MultiMaps
Extension:MultiUpload
Extension:MultimediaPlayer
Extension:MyVariables
Extension:NamespaceHTML
Extension:NamespacePaths
Extension:NavigationTiming
Extension:Negref
Extension:NewSignupPage
Extension:NewUserMessage
Extension:NewUserNotif
Extension:NewestPages
Extension:NewsBox
Extension:NewsTicker
Extension:Newsletter
Extension:NoBogusUserpages
Extension:NoTitle
Extension:NumberFormat
Extension:NumberOfWikis
Extension:Numbertext
Extension:NumerAlpha
Extension:OAuth
Extension:ORES
Extension:OfflineImportLexicon
Extension:OnlineStatus
Extension:OnlineStatusBar
Extension:OnlyRecentRecentChanges
Extension:OpenGraphMeta
Extension:OpenID
Extension:OpenStackManager
Extension:PCRGUIInserts
Extension:PGFTikZ
Extension:PageCreationNotif
Extension:PageForms
Extension:PageImages
Extension:PageNotice
Extension:PageSchemas
Extension:PageTools
Extension:PageTriage
Extension:PagesList
Extension:PaginateText
Extension:ParserFun
Extension:Patroller
Extension:PhabTaskGraph
Extension:PhpHighlight
Extension:PhpTagsFunctions
Extension:PhpTagsMaps
Extension:PhpTagsSMW
Extension:PhpTagsSPARQL
Extension:PictureGame
Extension:PipeEscape
Extension:Poem
Extension:Poll
Extension:PrivateDomains
Extension:ProofreadPage
Extension:PropertySuggester
Extension:ProtectSite
Extension:Push
Extension:PushToWatch
Extension:Quantcast
Extension:QuickResponse
Extension:QuizGame
Extension:RT
Extension:RandomGameUnit
Extension:RandomImage
Extension:RandomImageByCategory
Extension:RandomInCategory
Extension:ReassignEdits
Extension:RefreshSpecial
Extension:RegexBlock
Extension:RegexFun
Extension:RegexFunctions
Extension:ReplaceSet
Extension:ReplaceText
Extension:RevisionSlider
Extension:RightFunctions
Extension:SandboxLink
Extension:Sarcasm
Extension:Score
Extension:Scribunto
Extension:SearchStats
Extension:SecureSessions
Extension:SemanticACL
Extension:SemanticBundle
Extension:SemanticGenealogy
Extension:SemanticWebBrowser
Extension:SendGrid
Extension:ShortDescription
Extension:ShortUrl
Extension:ShoutWikiAPI
Extension:ShoutWikiAds
Extension:SidebarDonateBox
Extension:SignWritingMediaWikiPlugin
Extension:SimpleChanges
Extension:SimpleFarm
Extension:SimpleSecurity
Extension:SiteMetrics
Extension:SlimboxThumbs
Extension:SocialProfile
Extension:SoftRedirector
Extension:SoftwareVersion
Extension:Solarium
Extension:SoundManager2Button
Extension:SpamDiffTool
Extension:SpecialNamespaces
Extension:SpellingApi
Extension:SpellingDictionary
Extension:StaffEdits
Extension:StaffPowers
Extension:StalkerLog
Extension:StarterWiki
Extension:StickToThatLanguage
Extension:SubpageFun
Extension:SubpageSortkey
Extension:Sudo
Extension:SwiftMailer
Extension:SyntaxHighlight_GeSHi
Extension:TEI
Extension:THICC
Extension:Tabber
Extension:TemplateStyles
Extension:TestLanguageNameGrammar
Extension:TextExtracts
Extension:Thanks
Extension:TheWikipediaLibrary
Extension:Theme
Extension:ThrottleOverride
Extension:TimedMediaHandler
Extension:TimelineTable
Extension:TinyMCE
Extension:TitleBlacklist
Extension:TocTree
Extension:TorBlock
Extension:Translate
Extension:TranslateSvg
Extension:TranslationNotifications
Extension:TweetANew
Extension:TwitterCards
Extension:TwitterLogin
Extension:TwnMainPage
Extension:TwoColConflict
Extension:UIFeedback
Extension:UILangCode
Extension:UniversalLanguageSelector
Extension:UpdateMediaWiki
Extension:UploadWizard
Extension:UploadsLink
Extension:UrlGetParameters
Extension:UrlShortener
Extension:UserFunctions
Extension:UserGroups
Extension:UserOptionStats
Extension:UserPageEditProtection
Extension:VirtualKeyboard
Extension:VisualEditor
Extension:VoteNY
Extension:WebChat
Extension:WebDAV
Extension:WhitelistPages
Extension:WhosOnline
Extension:WikiArticleFeeds
Extension:WikiLexicalData
Extension:WikiLovesMonuments
Extension:WikiTextLoggedInOut
Extension:Wikibase
Extension:WikibaseCirrusSearch
Extension:WikibaseLexeme
Extension:WikibaseLexemeCirrusSearch
Extension:WikibaseMediaInfo
Extension:WikibaseQualityConstraints
Extension:Wikidata.org
Extension:WikidataPageBanner
Extension:WikimediaBadges
Extension:WikimediaEvents
Extension:WikimediaIncubator
Extension:Wikisource
Extension:Wikispeech
Extension:XSL
Extension:YetAnotherKeywords
Extension:cldr
Extension:examples
Fannon/SimpleTooltip
Hutchy68/Purge
HydraWiki/ImageSizeInfoFunctions
HydraWiki/LuaCache
HydraWiki/SpriteSheet
HydraWiki/Streamer
JeroenDeDauw/Maps
MediaWiki core
Nikerabbit/mediawiki-extensions-Ainut
Nikerabbit/mediawiki-extensions-FileSystemImageServer
Nikerabbit/mediawiki-extensions-FinnFrameNet
Nikerabbit/mediawiki-extensions-Lud
Nikerabbit/mediawiki-extensions-Nimiarkisto
Nikerabbit/mediawiki-extensions-Sanat
Nikerabbit/mediawiki-extensions-Termbank
Nikerabbit/mediawiki-extensions-WordNet
SemanticMediaWiki/Mermaid
SemanticMediaWiki/SemanticApprovedRevs
SemanticMediaWiki/SemanticBreadcrumbLinks
SemanticMediaWiki/SemanticCite
SemanticMediaWiki/SemanticCompoundQueries
SemanticMediaWiki/SemanticExternalQueryLookup
SemanticMediaWiki/SemanticExtraSpecialProperties
SemanticMediaWiki/SemanticFormsSelect
SemanticMediaWiki/SemanticGlossary
SemanticMediaWiki/SemanticInterlanguageLinks
SemanticMediaWiki/SemanticMediaWiki
SemanticMediaWiki/SemanticMetaTags
SemanticMediaWiki/SemanticNotifications
SemanticMediaWiki/SemanticResultFormats
SemanticMediaWiki/SemanticScribunto
SemanticMediaWiki/SemanticSignup
SemanticMediaWiki/SemanticTasks
SemanticMediaWiki/SemanticWatchlist
SemanticMediaWiki/SummaryCards
SemanticMediaWiki/WhatsNearby
Skin:Daddio
Skin:DeskMessMirrored
Skin:Nimbus
Skin:Schulenburg
Skin:Truglass
Skin:p2wiki
VisualEditor core
WikibaseDataModel
WikibaseDataModelSerialization
WikibaseDataModelServices
WikibaseInternalSerialization
Wikifab/AutoSetPageLang
Wikifab/mediawiki-extension-ImageAnnotator
Wikimedia MediaWiki config
Wikimedia Puppet
cmln/chameleon
cmln/mw-font-awesome
cmln/mw-scss
enterprisemediawiki/WatchAnalytics
hexmode/mediawiki-MagicNumberedHeadings
hydrawiki/extensions/EmbedVideo
hydrawiki/extensions/PDFEmbed
hydrawiki/extensions/Tabber
jeblad/BCmath
jeblad/Expect
jeblad/Pickle
lingua-libre/RecordWizard
miraheze/MirahezeMagic
oetterer/BootstrapComponents
s7eph4n/PurgePage
s7eph4n/SimpleBatchUpload
s7eph4n/mediawiki-extensions-Bootstrap
thingles/foreground
tinymighty/wiki-seo
translatewiki.net
wiki-chan/ModernSkylight

Prior art:

Event Timeline

For Vector I see it in 3 files currently:

  • COPYING
  • ResourceLoaderLessModule.php
  • SkinVector.php

IANAL, nonetheless I'd say, sure, go for consolidation, if you feel that's worth it.

IANAL but here's my $0.02 on this: I greatly value the importance of free and open source software, but I, too, find the overly verbose GPL license headers plain obnoxious and useless; they all no value if and when the entire project is already under the GPL. Should the license of a particular file or library embedded into the project differ from the main license, it should of course be clearly indicated, but when the entire project is under the same license, embedding the main license boilerplate text into each file serves no purpose.

For whatever reason, this issue is somewhat of a controversial topic (see e.g. this TextExtracts patch, which was stalled essentially for over a month due to nothing but GPL headers related concerns).

cc'ing @thiemowmde @MaxSem @Isarra @Jdlrobson for thoughts on this.

I like the idea, as well as the similar idea of shortening the header to one line something like

/* SPDX-License-Identifier: GPL-2.0-or-later */

or

/** @license GNU General Public License version 2 or later; see LICENSE */

or whatever.

On the other hand, T28280 and T44472 express a contrary viewpoint. CCing people who were active on those tasks. Overall, this probably needs to be an RFC.

For the GPL in particular, removing the notice from all files currently containing it might be disallowed by the clause that says "keep intact all the notices that refer to this License and to the absence of any warranty". But that's a question for WMF-Legal, I hope they tell us I'm wrong.

Legoktm added a subscriber: Legoktm.

It is crucial that each individual file include licensing information - just keeping it in the repository root isn't sufficient. The main reason is that we generally tend to mix differently licensed code in the same repository, so each file should be explicit in its licensing status.

https://lu.is/blog/2012/03/17/on-the-importance-of-per-file-license-information/ from our former lawyer explains this well. I'll quote the summary: "...if you want people to find your licensing information, and to use your code, per-file headers are the way to go. They may not be ideal but they really are worth the effort."

And yes, sometimes people will copy just a single file out of a project, drop it into their project with a different license, and suddenly your code is being distributed under the wrong license without attribution.

https://salsa.debian.org/mediawiki-team/mediawiki/blob/master/debian/copyright should give you an idea of how mixed up all of our licenses are - that's OK as long as they're documented for distributors. In the past, lack of individual documentation allowed for some non-GPL compatible code to get into our repositories.

The one-line machine-readable license info would satisfy these purposes.

The one-line machine-readable license info would satisfy these purposes.

Most likely, yes. But that's not what this task is about ("Consolidate source code license in repository root").

Niedzielski renamed this task from Consolidate source code license in repository root to Consolidate source code licenses to single line per file.Feb 9 2020, 3:33 AM
Niedzielski reopened this task as Open.
Niedzielski updated the task description. (Show Details)
Restricted Application added subscribers: RhinosF1, jeblad. · View Herald Transcript

Thanks for the notification, I’ve filed an issue for MirahezeMagic @ https://phabricator.miraheze.org/T5216.

Thanks for the notification, I’ve filed an issue for MirahezeMagic @ https://phabricator.miraheze.org/T5216.

Pretty sure there’s nothing for you to do. It was just a suggestion that you’re doing something in a particular way to show there’s a pattern...

Thanks for the notification, I’ve filed an issue for MirahezeMagic @ https://phabricator.miraheze.org/T5216.

Pretty sure there’s nothing for you to do. It was just a suggestion that you’re doing something in a particular way to show there’s a pattern...

Kk

If I remember correctly the WMDE Wikidata team settled this back in 2014 or 2015, with the help of actual lawyers we thrust. The arguments from back then go like this:

The only license that's really critical is the one in the COPYING file (or whatever the name of that file is, there are a few common file names). Repeating the license per file is – legally – not required.

  1. It's not like a file is out of a sudden public domain just because it does not mention a license. The license for these files is the one in COPYING. No lawyer or judge will question this.
  2. Even if a file is copied and used in another codebase, this does not change the original license, and does not require the license to be repeated per file.

However, we believe it's helpful to repeat the license per file. Not for us – we know how we licensed our code –, but for all others. If somebody looks at our code, they typically look at individual files, and don't start by checking if there is a COPYING file. Seeing the license at the top of each file is not only convenient, it actually makes it easier to copy code when it's so easy to see if it's license is compatible. However, for all that a single line is all that's needed. It really should not be more than that. Please stop cluttering code with cargo-cult'ish repetition.

The Wikibase codebase even enforces @license tags via a custom sniff.

I understand the underlying problem but, in addition to the things already explained, IMHO I don't like the idea of omitting also this line:

This program is free software; you can redistribute it and/or modify it

That value would be lost behind a single line, even more totally ignored because, sadly, nobody reads the full license. I don't think we can find much consensus on this.

That value would be lost behind a single line, even more totally ignored because, sadly, nobody reads the full license.

And you think people don't just skip reading 20+ lines of boilerplate comments? ;-)

I don't think we can find much consensus on this.

Agreed.