Почему системы контроля версий по-прежнему в основном защищены файлами?


22

Похоже, что все больше систем контроля версий все еще используют файлы как средство хранения данных версий. Vault и TFS используют Sql Server в качестве хранилища данных, что, я думаю, было бы лучше как для согласованности данных, так и для скорости.

Так почему же SVN, я полагаю, что GIT, CVS и т. Д. Все еще используют файловую систему как базу данных (я задаю этот вопрос, поскольку наш сервер SVN просто повредил себя во время обычной фиксации) вместо использования реального программного обеспечения базы данных ( MSSQL, Oracle, Postgre и т. Д.)?

РЕДАКТИРОВАТЬ: я думаю, еще один способ задать мой вопрос: «Почему разработчики VCS катят свою собственную систему структурированного хранения данных вместо того, чтобы использовать существующую?»


29
Как вы думаете, что большинство баз данных используют в качестве своей основной поддержки? Большинство используют файлы (однако некоторые используют прямой доступ к жестким дискам). Вы можете использовать все возможности базы данных, используя «просто файлы».
Йоахим Зауэр

2
@JoachimSauer Справедливо, хотя, конечно, вам придется создавать базу данных самостоятельно. Что глупо, если ваш желаемый набор функций близок к существующим решениям и у вас нет очень веских причин не использовать ни один из них.

1
@JoachimSauer Да, я это понимаю, но системы DBM имеют способы гарантировать, что в базу данных не попадет ничего непоследовательного. Если в этих файловых репозиториях не используется что-то вроде транзакционного NTSF, существует вероятность повреждения. И я доверяю реальной базе данных больше, чем группе разработчиков, по сути, заново изобретающей колесо, так как я думаю, что мы можем согласиться с тем, что системы контроля версий требуют целостности данных.
Энди

2
@delnan Транзакционная поддержка и внутренняя согласованность. Сейчас мы восстанавливаем наш репозиторий SVN с ленты, поскольку сервер SVN неправильно записывал все файлы, которые он должен был. Также поиск огромных объемов данных. Моя точка зрения, зачем пытаться заново изобрести колесо.
Энди

7
Каждая основная операционная система поставляется со встроенной файловой системой. Все эти файловые системы имеют одинаковую базовую функциональность (файлы, папки, постоянство одинаковы). По сути, база данных - это еще одна зависимость, которую конечный пользователь должен установить и постоянно обновлять. Контроль над исходным кодом не является основной задачей большинства людей (если вы не являетесь sourceforge или github). VC часто устанавливается на серверы через командную строку новым членом команды. Простота установки и настройки важна.
ГленПетерсон

Ответы:


23

TL; DR: Немногие системы контроля версий используют базу данных, потому что в этом нет необходимости.

В качестве вопроса для ответа на вопрос, почему бы не они? Какие преимущества дают «реальные» системы баз данных по сравнению с файловой системой в этом контексте?

Учтите, что контроль версий в основном отслеживает небольшие метаданные и множество различий в тексте. Текст не хранится в базах данных более эффективно, и индексируемость содержимого не будет фактором.

Предположим, что Git (для аргумента) использовал BDB или SQLite DB для своей базы данных для хранения данных. Что может быть более надежным в этом? Все, что может повредить простые файлы, также может повредить базу данных (поскольку это также простой файл с более сложной кодировкой).

От парадигмы программиста не оптимизировать, если это не необходимо, если система контроля версий достаточно быстра и работает достаточно надежно, зачем менять всю конструкцию, чтобы использовать более сложную систему?


2
TLDR? Ваш ответ был вдвое длиннее, и вопрос был очень коротким, как есть!
Брэд

25
@Brad Три слова, следующие за, TL;DRявляются сокращенной версией ответов, а не утверждением, что вопрос слишком длинный, и он не прочитал его, прежде чем ответить.

6
У @Andy Mercurial также есть «grep in history», и, вероятно, у git. Это также молниеносно уже. Что касается доведения до эксперта: люди, которые разрабатывают VCSs, являются экспертами.

3
Просто хочу добавить, что я вижу вашу точку зрения; если VCS записывает неверные данные, не имеет значения, записывает ли эти данные в файл или базу данных. С другой стороны, репозитории на основе файлов, вероятно, записывают более одного файла за раз, и, как правило, для этого не поддерживается транзакция, поэтому, если один файл записывает, а другой выходит из строя, ваша VCS теперь повреждена, в отличие от записи нескольких таблиц в базе данных. транзакция будет зафиксирована для сбоя как единое целое. Мне кажется, что группа разработчиков программного обеспечения для создания баз данных имеет больше опыта в этом, чем люди, пишущие SVN ... но, возможно, я ошибаюсь.
Энди

6
Важным моментом здесь является выбор git «для аргументации»: git имеет очень хорошую модель для написания своих объектов, но многие инструменты этого не делают. С git, если компьютер выключен во время коммита, вы записали некоторые объекты в файловую систему, и они просто будут недоступны. С другими VCS вы, возможно, добавили изменения к половине файлов (и возникла путаница). Вы можете утверждать, что другие инструменты контроля версий плохо спроектированы (и вы были бы правы), но когда вы пишете VCS, это намного проще просто использовать транзакцию SQL и позволить ей делать правильные вещи.
Эдвард Томсон

25

Похоже, вы делаете много предположений, возможно, исходя из вашего опыта работы с SVN и CVS.

Git и Mercurial в основном похожи на SVN и CVS

Сравнение git и CVS похоже на сравнение iPad и Atari. CVS был создан еще тогда, когда динозавры бродили по Земле . Subversion - это улучшенная версия CVS. Предполагать, что современные системы контроля версий, такие как git и Mercurial, работают как они, имеют мало смысла.

Реляционная база данных более эффективна, чем специализированная база данных

Зачем? Реляционные базы данных действительно сложны и могут быть не такими эффективными, как специализированные базы данных. Некоторые отличия от макушки головы:

  • Системы контроля версий не нуждаются в сложной блокировке, так как вы все равно не можете выполнять несколько коммитов одновременно.
  • Распределенные системы контроля версий должны быть очень чрезвычайно компактными, поскольку локальная база данных является полной копией репозитория.
  • Системы контроля версий должны искать данные только несколькими конкретными способами (по автору, по идентификатору ревизии, иногда полнотекстовый поиск). Создание вашей собственной базы данных, которая может обрабатывать поиск по идентификатору автора / ревизии, тривиально, а полнотекстовый поиск не очень быстрый в любой реляционной базе данных, которую я пробовал.
  • Системы контроля версий должны работать на нескольких платформах. Это затрудняет использование базы данных, которую необходимо установить и запустить в качестве службы (например, MySQL или PostgreSQL).
  • Системы контроля версий на вашем локальном компьютере должны работать только тогда, когда вы что-то делаете (например, коммит). Оставлять сервис, подобный MySQL, постоянно работающим на тот случай, если вы захотите сделать коммит, расточительно.
  • По большей части системы контроля версий никогда не хотят удалять историю, а просто добавляют ее. Это может привести к разной оптимизации и разным методам защиты целостности.

Реляционные базы данных безопаснее

Опять же почему? Вы, кажется, предполагаете, что поскольку данные хранятся в файлах, системы контроля версий, такие как git и Mercurial, не имеют атомарных фиксаций , но они имеют. Реляционные базы данных также хранят свои базы данных в виде файлов. Здесь примечательно, что CVS не выполняет атомарные коммиты, но, скорее всего, это из-за незапамятных времен, а не потому, что они не используют реляционные базы данных.

Существует также проблема защиты данных от повреждения, когда они находятся в базе данных, и опять же ответ тот же. Если файловая система повреждена, то не имеет значения, какую базу данных вы используете. Если файловая система не повреждена, то ваша база данных может быть повреждена. Я не понимаю, почему база данных контроля версий была бы более склонна к этому, чем реляционная база данных.

Я бы сказал, что распределенные системы контроля версий (такие как git и Mercurial) лучше защищают вашу базу данных, чем централизованный контроль версий, поскольку вы можете восстановить весь репозиторий из любого клона. Таким образом, если ваш центральный сервер самопроизвольно сгорает вместе со всеми вашими резервными копиями, вы можете восстановить его, запустив его git initна новом сервере, а затем git pushс компьютера любого разработчика .

Изобретать колесо плохо

То, что вы можете использовать реляционную базу данных для решения любых проблем хранения, не означает, что вы должны это делать . Почему вы используете файлы конфигурации вместо реляционной базы данных? Зачем хранить изображения в файловой системе, если вы можете хранить данные в реляционной базе данных? Зачем хранить свой код в файловой системе, если вы можете хранить все это в реляционной базе данных?

«Если все, что у вас есть, это молоток, все выглядит как гвоздь».

Существует также тот факт, что проекты с открытым исходным кодом могут позволить себе заново изобретать колесо, когда это удобно, поскольку у вас нет тех же ограничений на ресурсы, что и в коммерческих проектах. Если у вас есть волонтер, который является экспертом в написании баз данных, то почему бы не использовать их?

Что касается того, почему мы могли бы доверять авторам систем контроля версий знать, что они делают ... Я не могу говорить о других VCS, но я довольно уверен, что Линус Торвальдс понимает файловые системы .

Почему некоторые коммерческие системы контроля версий используют реляционную базу данных?

Скорее всего какая-то комбинация из следующего:

  • Некоторые разработчики не хотят писать базы данных.
  • Разработчики коммерческих систем контроля версий имеют ограничения по времени и ресурсам, поэтому они не могут позволить себе написать базу данных, когда у них уже есть что-то близкое к тому, что они хотят. Кроме того, разработчики стоят дорого, а разработчики баз данных (например, люди, которые пишут базы данных), вероятно, дороже, так как большинство людей не имеют такого опыта.
  • Пользователи коммерческих систем контроля версий с меньшей вероятностью будут заботиться о накладных расходах на настройку и запуск реляционной базы данных, поскольку они уже есть.
  • Пользователи коммерческих систем контроля версий с большей вероятностью захотят, чтобы реляционная база данных поддерживала свои данные ревизий, поскольку это может лучше интегрироваться с их процессами (например, резервными копиями).

1
Одна вещи: SVN фиксации являются атомными. На самом деле, это главный пункт продажи (или, по крайней мере, когда-то, когда они должны были убедить пользователей CSV переключиться).

1
@delnan - обратите внимание, что существует большая разница между теоретической атомарностью, с svnкоторой вы получаете разные каталоги в вашем рабочем каталоге, svnс реальными ревизиями, и истинной атомарностью всего репозитория, которую вы получаете с помощью gitили hg.
Марк Бут

2
@ Andy И я хочу сказать, что вы можете справиться с теми же сценариями без полноценной реляционной базы данных. Если два человека совершают коммит одновременно, сервер может делать один за другим. Это не сложная функция для реализации. Если вы хотите сделать это с локальным пользователем, просто запишите файл блокировки. Когда вы запустите коммит, получите блокировку файла. Когда вы закончите коммит, снимите блокировку. Если вы хотите разрешить фиксацию сразу для нескольких веток, используйте файл блокировки для каждой ветви. Конечно, SQLite сделал бы это для меня, но это не обязательно .
Восстановить Монику

1
Аналогично, реализация базового журнала также не сложна. (1) Запишите новый коммит в файл. (2) Скопируйте старый индексный файл. (3) Написать новый индексный файл. (4) Удалить копию старого индексного файла. Если вы потерпите неудачу на шаге 1, 2 или 4, вам просто нужно очистить новые файлы, которые вы создали. Если вы потерпите неудачу на шаге 3, вам просто нужно скопировать старый индексный файл обратно. Кто-то, кто лучше понимает файловые системы, может сделать эту версию гораздо более эффективной, но вы всегда можете обратиться к исходному коду SQLite, если вам это нужно (это общественное достояние).
Восстановить Монику

1
@BrendanLong Великолепные моменты. Ценю обсуждение. Просто чтобы прояснить, я думаю, что есть преимущества и недостатки для обоих видов бэк-магазинов, я не верю, что есть только один правильный ответ. Однако я был немного удивлен, что, кажется, только три (четыре, если вы считаете Vault и Vercity по отдельности) используют SQL, а подавляющее большинство из них - нет, вот и все.
Энди

18

На самом деле svnиспользуется для использования BDB для хранилищ. Это было в конечном счете избавлено, потому что это было склонно к поломке.

Другой VCS, который в настоящее время использует БД (SQLite) fossil. Он также включает в себя трекер ошибок.

Я предполагаю, что настоящая причина в том, что VCS работают с большим количеством файлов. Файловые системы - это просто еще один вид базы данных (иерархический, ориентированный на эффективность хранения CLOB / BLOB). Обычные базы данных не справляются с этим хорошо, потому что нет никаких причин - файловые системы уже существуют.


1
BDB точно не будет считаться надежным - как и SQLite, это внутренняя база данных. Тем не менее, я думаю, что надежность Oracle / MSSQL / MySQL / Postgres, в зависимости от того, как вы их настраиваете, мало чем отличается от файловых систем. Основная проблема заключается в том, что СУБД не созданы для иерархических и графических структур, с которыми обычно работают VCS. И в этом случае файловые системы просто выигрывают.
Майк Ларсен

3
@Andy: Fossil был создан создателем SQLite. Это не так уж удивительно :-)
Jörg W Mittag

1
@ Энди: я бы доверял SQLite гораздо больше, чем Oracle или MSSQL. Неудивительно, что это самая используемая база данных SQL, с огромным отрывом. Кроме того, он портирован на самые разные архитектуры, каждая со своим набором задач, что делает общий код невероятно пуленепробиваемым.
Хавьер

1
@ Javier Я бы не стал доверять Sqlite так же, как MSSQL или Oracle; как сказал Майк, внутрипроцессная часть меня пугает, как будто ваше приложение умирает, что может привести к повреждению вашей БД. С базой данных клиент / сервер клиент умирает, прерывает транзакцию. Нельзя сказать, что для БД CS невозможно повредить, но я думаю, что это менее вероятно, чем объединение механизма БД с приложением.
Энди

5
@ Энди, для этого и нужны транзакции. Независимо от того, в какой момент вы убиваете хороший механизм БД, данная транзакция либо фиксируется, либо нет. Реализация атомарных коммитов в SQLite ( sqlite.org/atomiccommit.html ) является особенно сложной.
Хавьер

10
  1. Файловая система - это база данных. Конечно, это не реляционная база данных, но большинство из них являются очень эффективными хранилищами ключей / значений. И если ваши шаблоны доступа хорошо спроектированы для хранилища значений ключей (например, формата репозитория git), то использование базы данных, вероятно, не дает существенных преимуществ по сравнению с использованием файловой системы. (На самом деле, это просто еще один уровень абстракции, чтобы мешать.)

  2. Многие функции базы данных просто дополнительный багаж. Полнотекстовый поиск? Имеет ли смысл полнотекстовый поиск для исходного кода? Или вам нужно по-другому токенизировать? Это также требует, чтобы вы сохраняли полные файлы при каждой ревизии, что необычно. Многие системы контроля версий хранят дельты между ревизиями одного и того же файла для экономии места, например, Subversion и Git (по крайней мере, при использовании файлов пакета).

  3. Кроссплатформенные требования усложняют использование базы данных.

    Большинство инструментов контроля версий созданы для работы на нескольких платформах. Для инструментов централизованного контроля версий это влияет только на серверный компонент, но все еще трудно полагаться на один сервер базы данных, поскольку пользователи Unix не могут установить Microsoft SQL Server, а пользователи Windows могут не захотеть устанавливать PostgreSQL или MySQL. Файловая система является наименее распространенным знаменателем. Однако существует несколько инструментов, в которых сервер должен быть установлен на компьютере с Windows, и, следовательно, требуется SQL Server, например SourceGear Vault и Microsoft Team Foundation Server .

    Распределенные системы контроля версий еще более усложняют эту задачу, поскольку каждый пользователь получает копию хранилища. Это означает, что каждому пользователю нужна база данных для размещения репозитория. Это подразумевает, что программное обеспечение:

    1. Ограничено подмножеством платформ, где существует конкретная база данных
    2. Предназначен для одной кросс-платформенной базы данных (например, SQLite).
    3. Предназначен для подключаемого хранилища, чтобы можно было использовать любую базу данных, которую они пожелают (возможно, включая файловую систему).

    Поэтому большинство распределенных систем контроля версий просто используют файловую систему. Примечательным исключением является SourceGear Veracity , который может хранить в базе данных SQLite (полезной для локальных репозиториев) или реляционной базе данных, такой как SQL Server (возможно, полезной для сервера). Их размещаемое в облаке предложение может использовать нереляционную систему хранения, такую ​​как Amazon SimpleDB. , но я не знаю, чтобы это было правдой.


Возможно, так же, как и адвокатский комментарий дьявола, большинство людей, которые задают такие вопросы «почему бы не использовать базу данных», по-видимому, означают «почему бы не использовать RDBMS?» со всем соответствием ACID и другими проблемами. Тот факт, что все файловые системы уже являются базами данных своего рода, уже отброшен.
mikebabcock

6

Насколько я видел во многих предложениях, кажется, что файлы "достаточно хороши" для работы, что-то разумное, учитывая, что в конце дня выходные данные VCSes также являются файлами.

Есть много компаний, которые предлагают СУРБД с интерфейсом svn / git / etc, так что то, о чем вы просите, в основном уже существует.


5

Я бы сказал, это потому, что основной структурой данных системы контроля версий является группа обеспечения доступности баз данных, которая очень плохо отображает базы данных. Большая часть данных также является адресно-зависимой, что очень плохо отображает базы данных.

Целостность данных - не единственная забота VCS, они также касаются целостности истории версий , в которой базы данных не очень хороши. Другими словами, когда вы извлекаете версию, вам нужно не только убедиться, что версия не имеет текущих недостатков, но также и то, что ничего за всю ее историю не было тайно изменено.

VCS также является потребительским продуктом в дополнение к корпоративному продукту. Люди используют их в небольших проектах для одного человека. Если вы добавите хлопоты по установке и настройке сервера базы данных, вы собираетесь оттолкнуть большую часть этой части рынка. Я предполагаю, что вы не видите много установок Vault и TFS дома. По той же причине электронные таблицы и текстовые процессоры не используют базы данных.

Кроме того, это еще одна причина для DVCS, но не использование базы данных делает ее чрезвычайно портативной. Я могу скопировать исходное дерево на флэш-накопитель и использовать его на любом компьютере без необходимости настройки процесса сервера базы данных.

Что касается развращает во фиксациях, VCS использует те же методы , как базы данных для предотвращения одновременного доступа, совершать сделки атомных и т.д. искаженные оба они очень редки, но они действительно случаются . Для всех целей хранилище данных VCS является базой данных.


1
«очень плохо сопоставляется с базами данных» Тем не менее Vault и TFS делают именно это. «Целостность данных - не единственная проблема VCS, они также связаны с целостностью истории версий, в которой базы данных не очень хороши». Я не вижу, как хранение истории версий может быть использовано в файлах в базе данных, тем более что я назвал продукты, которые так и делают. «Коррупции в обоих случаях очень редки, но они случаются». Ни на одном из этих результатов на первой странице не говорится о повреждении базы данных сервера Vault. Одна ссылка, которая даже говорит о программном обеспечении Vault, о том, что WC был поврежден.
Энди

«Для всех целей хранилище данных VCS является базой данных». Ну ... это моя точка зрения. Почему бы просто не вставить данные в реальную систему баз данных, а не скатать свои собственные?
Энди

2
@ Andy Да, это база данных, но не все базы данных могут заменять друг друга. Каждая база данных имеет определенный взгляд на мир (например, базы данных SQL в основном реализуют реляционную модель). Поскольку этот ответ детализирует, данные, которые хранит VCS, и способ, которым эти данные используются, не соответствуют реляционной модели. Я не уверен, что некоторые базы данных NoSQL работают лучше, но они довольно новы и еще не доказали свое превосходство (я вспоминаю сообщения о серьезных проблемах с целостностью для некоторых). И затем есть все другие проблемы на вершине этого.

Группы обеспечения доступности баз данных используются только в DVCS (если вы не считаете линейную историю исключительно простой группой обеспечения доступности баз данных, но это не очень полезная абстракция.) Когда ваша история является линейной с монотонно растущими наборами изменений, база данных SQL имеет гораздо больший смысл ,
Эдвард Томсон

Монотонно увеличивающиеся номера версий не имеют большого смысла для VCS. Я использовал достаточное их количество, и те, с централизованными номерами версий (CVS & SVN - 2, с которыми я больше всего знаком), как правило, испытывают боль при слиянии. И даже те используют DAG, когда пытаются объединиться. Тот факт, что их хранилище не основано на нем, не означает, что он не используется.
Майк Ларсен

2
  • Лучшее аварийное восстановление (наихудший сценарий: мы разберем его на глаз, как в старые времена)

  • Облегчение отслеживания и отладки таких аварий, возможно, вызванных сбоями в системе VCS.

  • Снижение количества зависимостей. (давайте не будем забывать , один из этих систем обработки на ядро, а другой должен был)

  • Текстовый редактор всегда доступен. (MS SQL Server лицензий ... не так много)


Этот ответ просто плохой. Единственный действительно верный момент - это уменьшение количества зависимостей. Обе системы поддержки должны быть на одном уровне, поскольку вы должны делать правильное резервное копирование, отладка приложений БД не сложнее, чем отладка приложений, которые пишут файлы, а текстовый редактор всегда доступен? Я даже не знаю, в чем ваша точка зрения, так как VCS сама не собирается использовать текстовый редактор, и есть другие серверы БД (Sqlite, Postgre, MySql и т. Д.), Так что если вы хотите Решение на основе БД Отсутствие сервера БД не должно быть фактором.
Энди

1
@ Энди ... программисты собираются использовать текстовый редактор. Вы знаете, редактирование текста по-прежнему доступно в качестве дополнительной функции даже в вашей любимой IDE.
ZJR

1
@ Andy sqlite- единственно возможная альтернатива текстовым файлам, учитывая огромное количество распределенных сценариев, которые обслуживают современные DVCS. (idk, возможно, вы могли пропустить «распределенную» часть DVCS) Все остальное было бы слишком громоздким (конфигурация + межсетевой экран + лицензия) или даже глупым для распространения . С другой стороны, выполнение наихудшего сценария после смерти в sqlite может оказаться затруднительным.
ZJR

1
@ZJR: я не думаю, что оригинальный вопрос когда-либо определял распределенное управление версиями, он спрашивал о системах контроля версий в целом. Кроме того, ваш аргумент текстового редактора немного плоский, так как многие системы не хранят только текстовые файлы. Даже в git есть множество форматов двоичных файлов (свободные объекты, файлы пакетов и т. Д.), Которые делают ваш текстовый редактор бесполезным.
Эдвард Томсон

@ZJR Как редактирование кода в текстовом редакторе доступно для резервного хранилища VCS? Вы предлагаете редактировать вручную, скажем, базу данных SVN? Также мой вопрос не ограничивается DVCS, поэтому я не знаю, почему вы об этом говорите.
Энди

2

Fossil - отличная распределенная система контроля версий (DVCS), которая использует SQLite для хранения, а не текстовые файлы.

Мне очень нравится, что он интегрирован: отслеживание ошибок, Wiki и то, что он действительно распространяется. Я имею в виду, что вы действительно можете работать в автономном режиме и исправлять ошибки.

Fossil использует Sqlite в качестве формата файла приложения. В своем выступлении на PgCon д-р Ричард Хипп объясняет, каковы преимущества использования sqlite в качестве файловой системы приложения, и приводит довольно убедительный аргумент о преимуществах использования базы данных в качестве файловой системы.

Второй основной темой было то, что SQLite следует рассматривать как формат файла приложения - альтернативу изобретению собственных форматов файлов или использованию ZIPped XML. Утверждение «SQLite не является заменой для PostgreSQL. SQLite - это замена гвоздям fopen () »(слайд 21). Наконец, Ричард уделяет большое внимание тому факту, что SQLite заботится о ваших данных ( защита от сбоев , ACID) use-the-index.com

Теперь доктор Хипп обратился к проблемам сохранения кода в базе данных.

  • Почему Fossil основан на SQLite, а не на распределенной базе данных NoSQL?

Ископаемое не основано на SQLite. Текущая реализация Fossil использует SQLite в качестве локального хранилища для содержимого распределенной базы данных и в качестве кеша для мета-информации о распределенной базе данных, которая предварительно вычисляется для быстрого и удобного представления. Но использование SQLite в этой роли является деталью реализации и не является фундаментальным для проектирования. Некоторые будущие версии Fossil могут покончить с SQLite и заменить кучу файлов или базу данных ключ / значение вместо SQLite. (На самом деле, это очень маловероятно, поскольку SQLite прекрасно работает в своей текущей роли, но дело в том, что исключение SQLite из Fossil является теоретической возможностью.)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.