Как написать простую систему управления версиями? - PullRequest
22 голосов
/ 10 июня 2009

Я хочу создать простую систему управления версиями, но у меня нет идей, как структурировать мои данные и мой код.

Вот краткий пример:

  1. Пользователь входит в систему
  2. У пользователя есть два варианта при загрузке файла:
    • Отправить новый файл
    • Отправить новую версию файла

Пользователи должны иметь возможность видеть дерево. (другая версия) Дерево может быть только до 2 уровней:

|
|--File_A_0
 \--File_A_1
 \--File_A_2
 \--File_A_3
 \--File_A_4

Существует также 2 типа файлов: окончательный (последняя утвержденная версия) и черновая версия (последний загруженный файл). Файл будет физически храниться на сервере. Каждый файл принадлежит пользователю (или нескольким) и только одной группе.

Редактировать: Группы представляют собой группу документов, документ может принадлежать только ОДНОЙ группе одновременно. Пользователи НЕ зависят от групп.

Начало редактирования:

Вот что я сделал, но это не очень эффективно!

id_article | relative_group_id | id_group | title | submited | date | abstract | reference | draft_version | count | status

id_draft | id_file | version | date

Но сложно управлять, расширять. Я думаю, что это потому, что групповой параметр ...

Конец редактирования

Итак, вопросы:

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

(Приложение разработано с использованием PHP и Zend Framework, база данных должна быть mysql или postgresql)

Ответы [ 13 ]

49 голосов
/ 15 июня 2009

Ради Бога, не . Вы действительно не хотите идти по этому пути.

Остановитесь и задумайтесь на минуту над картиной. Вы хотите сохранить более ранние версии документов, а это значит, что в какой-то момент кто-то захочет увидеть некоторые из этих более ранних версий, верно? И затем они спросят: «В чем разница между версией 3 и версией 7?» И затем они скажут: «Я хочу откатиться к версии 3, но оставлю некоторые из изменений, которые я положил в версии 5, ммм, хорошо? "

Контроль версий нетривиален, и изобретать колесо не нужно - существует множество жизнеспособных систем контроля версий, некоторые из которых бесплатны, даже.

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

Вы бы не написали текстовый редактор для своих пользователей?

18 голосов
/ 10 июня 2009

Вы можете получить вдохновение от там .


По поводу вашего комментария:

Что касается структуры базы данных, вы можете попробовать такую ​​структуру (MySQL sql):

CREATE TABLE `Users` (
       `UserID` INT NOT NULL AUTO_INCREMENT
     , `UserName` CHAR(50) NOT NULL
     , `UserLogin` CHAR(20) NOT NULL
     , PRIMARY KEY (`UserID`)
);

CREATE TABLE `Groups` (
       `GroupID` INT NOT NULL AUTO_INCREMENT
     , `GroupName` CHAR(20) NOT NULL
     , PRIMARY KEY (`GroupID`)
);

CREATE TABLE `Documents` (
       `DocID` INT NOT NULL AUTO_INCREMENT
     , `GroupID` INT NOT NULL
     , `DocName` CHAR(50) NOT NULL
     , `DocDateCreated` DATETIME NOT NULL
     , PRIMARY KEY (`DocID`)
     , INDEX (`GroupID`)
     , CONSTRAINT `FK_Documents_1` FOREIGN KEY (`GroupID`)
                  REFERENCES `Groups` (`GroupID`)
);

CREATE TABLE `Revisions` (
       `RevID` INT NOT NULL AUTO_INCREMENT
     , `DocID` INT
     , `RevUserFileName` CHAR(30) NOT NULL
     , `RevServerFilePath` CHAR(255) NOT NULL
     , `RevDateUpload` DATETIME NOT NULL
     , `RevAccepted` BOOLEAN NOT NULL
     , PRIMARY KEY (`RevID`)
     , INDEX (`DocID`)
     , CONSTRAINT `FK_Revisions_1` FOREIGN KEY (`DocID`)
                  REFERENCES `Documents` (`DocID`)
);

CREATE TABLE `M2M_UserRev` (
       `UserID` INT NOT NULL
     , `RevID` INT NOT NULL
     , INDEX (`UserID`)
     , CONSTRAINT `FK_M2M_UserRev_1` FOREIGN KEY (`UserID`)
                  REFERENCES `Users` (`UserID`)
     , INDEX (`RevID`)
     , CONSTRAINT `FK_M2M_UserRev_2` FOREIGN KEY (`RevID`)
                  REFERENCES `Revisions` (`RevID`)
);

Documents является логическим контейнером, а Revisions содержит фактические ссылки на файлы. Всякий раз, когда человек обновляет новый файл, создайте запись в каждой из этих таблиц, которая в редакции содержит ссылку на файл, вставленный в документы.

Таблица M2M_UserRev позволяет ассоциировать несколько пользователей с каждой редакцией документа.

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

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

13 голосов
/ 13 июня 2009

Схема базы данных


Для простоты я бы выбрал следующий дизайн базы данных. Я отделяю концепцию " file " (такую ​​же, как файл файловой системы) от концепции " document " (георадрическая группа документов).

Пользователь Сущность:

  • * идентификатор пользователя 1016 *
  • имя_пользователя

Группа Сущность:

  • идентификатор_группа
  • Groupname

Файл Сущность:

  • fileId (последовательность)
  • fileName (имя, которое пользователь дает файлу)
  • filesystemFullPath
  • uploadTime
  • uploaderId (идентификатор пользователя, добавившего видео)
  • ownerGroupId

Документ сущность:

  • documentId
  • parentDocumentId
  • FILEID
  • VersionNumber
  • CreationTime
  • isApproved

Каждый раз при загрузке нового файла создается запись «Файл», а также новый «Документ». Если этот файл загружается впервые, parentDocumentId для этого документа будет иметь значение NULL. В противном случае новая запись документа будет указывать на первую версию.

Поле isApproved (логическое) будет обрабатывать документ как черновик или утвержденную ревизию.
Вы получаете последний черновик документа, упорядочив его по убыванию по номеру версии или времени загрузки.

Подсказка


Исходя из того, как вы описываете проблему, вы должны лучше проанализировать эти аспекты, прежде чем переходить к разработке схемы базы данных:

  • Какова роль "группового" объекта?
  • как связаны группы / пользователи / файлы?
  • что если два пользователя из разных групп попытаются загрузить один и тот же документ?
  • понадобятся ли вам папки? (вероятно, вы согласитесь; мое решение все еще действует, давая тип, «папка» или «документ» сущности «документ»)

Надеюсь, это поможет.

9 голосов
/ 13 июня 2009

Может ли существующее решение по управлению версиями работать лучше, чем ваше собственное? Subversion можно сделать для того, чтобы делать то, что вы хотите, и он тут же.

6 голосов
/ 15 июня 2009

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

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

Быстрый пример. Если у нас есть хранилище, в котором есть каталог и три файла. Глядя на него спереди, он будет выглядеть так:

/repo
  /folder
    code.php
  file.txt
  image.jpg

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

/repo
  */.folderdata*
  /code
    */.folderdata*
    code.php
  file.txt
  image.jpg

Каждая папка .folderdata может содержать свою собственную структуру, которую мы можем использовать для правильной организации данных папки. Каждая папка .folderdata может быть сжата для экономии места на диске. Если мы посмотрим на папку .folderdata внутри каталога / code:

*/.folderdata*
  /revisions
    code.php.r1
    code.php.r2
    code.php.r3
  folderstructure.json
  filerevisions.json

Структура папок определяет структуру нашей папки, где файлы и папки связаны друг с другом и т. Д. Это может выглядеть примерно так:

{
  '.':        'code',
  '..':       'repo',
  'code.php': {
    'author_id': 11543,
    'author_name': 'Jamie Rumbelow',
    'file_hash': 'a26hb3vpq22'
    'access': 'public'
  }
}

Это позволяет нам связывать метаданные об этом файле, проверять подлинность и целостность, сохранять постоянные данные, задавать атрибуты файла и делать многое другое. Затем мы можем сохранить информацию о конкретных ревизиях в файле filerevisions.json:

{
  'code.php': [
    1: {
      'commit': 'ah32mncnj654oidfd',
      'commit_author_id': 11543,
      'commit_author_name': 'Jamie Rumbelow',
      'commit_message': 'Made some changes to code.php',
      'additions': 2,
      'subtractions': 4
    },
    2: {
      'commit': 'ljk4klj34khn5nkk5',
      'commit_author_id': 18676,
      'commit_author_name': 'Jo Johnson',
      'commit_message': 'Fixed Jamie\'s bad code!',
      'additions': 2,
      'subtractions': 0
    },
    3: {
      'commit': '77sdnjhhh4ife943r',
      'commit_author_id': 11543,
      'commit_author_name': 'Jamie Rumbelow',
      'commit_message': 'Whoah, showstopper found and fixed',
      'additions': 8,
      'subtractions': 5
    },
  ]
}

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

Надеюсь, это дало вам некоторое представление, и, надеюсь, оно даст пищу для размышлений и сообществу!

2 голосов
/ 19 июня 2009

Недавно я создал простую систему управления версиями для некоторых статических объектов данных. Требовалось иметь «активную» версию и 0 или 1 «ожидающие» версии.

В конце концов, моя версионная сущность имела следующие атрибуты, относящиеся к версионированию.

VersionNumber (int / long) ActiveVersionFlag (булево)

Где: -

  • Только 1 объект может быть ActiveVersionFlag = 'Y'
  • Только 1 объект может быть номером версии> «активной» версией (то есть «ожидающей» версией)

Разрешенные мной операции:

Клон текущей версии.

  • Ошибка, если версия уже существует> номер версии 'активной' версии
  • Скопировать все данные в новую версию
  • увеличить номер версии на один

Активировать ожидающую версию

  • Ошибка, если указанная версия не является «Активной» версией + 1
  • найдите «Активную» версию и установите для ее ActiveVersionFlag значение «N»
  • установить ActiveVersionFlag 'ожидающей' версии на 'Y'

Удалить ожидающую версию

  • Удалить ожидающую сущность

Это было достаточно успешно, и теперь мои пользователи все время клонируют и активируют:)

Michael

2 голосов
/ 10 июня 2009

Для схемы базы данных вам, вероятно, понадобятся два набора информации, файлы и версии файлов. При сохранении нового файла также создается начальная версия. Последняя утвержденная версия должна храниться в явном виде, в то время как самая последняя версия может быть выбрана из таблицы версий (либо путем поиска самой высокой версии, связанной с файлом, либо самой новой даты, если вы сохраняете их при создании)

files(id,name,approved_version)
file_versions(id,fileId)

версии файлов могут быть сохранены с использованием их идентификаторов (например, '/ fileId / versionId' или '/ fileId / versionId_fileName') на сервере с их исходным именем, сохраненным в базе данных.

1 голос
/ 19 июня 2009

В качестве альтернативы моему предыдущему посту, если вы считаете, что иерархическая структура будет наилучшей, вы можете использовать хранилище плоских файлов и предоставлять API через веб-сервис.

Сервер будет иметь свой корневой каталог данных, и вы можете хранить группы (файлов) в папках с корневой записью метаданных в каждой папке. (XML возможно?)

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

Мигрировать серверы? Почтовый индекс и копия. Кроссплатформенный? Почтовый индекс и копия. Резервное копирование? Zip и скопировать.

Мне нравится, например, бэкэнд с плоскими файлами в Mercurial DVCS.

Конечно, в этом небольшом примере файлы .rev могут иметь даты, время, сжатие и т. Д. И т. Д., Определенные в файле revisions.xml. Когда вы хотите получить доступ к одной из этих ревизий, вы предоставляете метод AccessFile (), который ваше серверное приложение будет просматривать по адресу revisions.xml, и определяет, как открыть этот файл, предоставлен ли доступ и т. Д.

Итак, у вас есть

DATA
| + ROOT
| | . metadata.xml
| | |
| | + REVISIONS
| | | . revisionsdata.xml
| | | . documenta.doc.00.rev
| | | . documenta.doc.01.rev
| | | . documentb.ppt.00.rev
| | | . documentb.ppt.03.rev
| | |___
| | |
| | . documenta.doc
| | . documentb.ppt
| | |
| | + GROUP_A
| | | . metadata.xml
| | | |
| | | + REVISIONS
| | | | . revisionsdata.xml
| | | | . documentc.doc.00.rev
| | | | . documentc.doc.01.rev
| | | | . documentd.ppt.00.rev
| | | | . documentd.ppt.03.rev
| | | |___
| | |
| | | . documentc.doc
| | | . documentd.ppt
| | |___
| | |
| | + GROUP_B
| | | . metadata.xml
| | |___
| |
| |___
|
|___
1 голос
/ 17 июня 2009

Начните с существующей системы управления контентом , выполненной на PHP и MySQL, если это соответствует вашим требованиям, например eZ Publish или Knowledgetree . Для быстрого тестирования этих приложений Bitnami также предоставляет возможность быстрой установки стеков"(стеки WAMP на стероидах).

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

0 голосов
/ 06 июля 2009

Я думаю, что это описывает идеальную систему для управления версиями

http://tom.preston -werner.com / 2009/05/19 / заместитель ГИТ-parable.html

...