Автоматична версія при зміні файлу (зміна / створення / видалення)


16

Я шукаю реалізацію (в Linux) механізму, який автоматично і прозоро версії будь-яких змін у каталозі (рекурсивно). Це призначено для доповнення (можливо, заміною, якщо всі запитувані функції доступні) до стандартної версії (SVN, git, ...)

Продукт на MS Windows, який робить це, є AutoVer (щоб краще уявити вимоги). Я хотів би мати щось подібне, але спрямоване на Linux у не графічному середовищі.

Я бачив, що є декілька спроб отримати цю функціональність у Linux, найбільш близькою, яку я знайшов, є автоперетворення на Subversion, але це не очевидно для реалізації на існуючих середовищах (серверах, де, наприклад, файли конфігурації є локальними).

Може, щось працює з inotify?

Заздалегідь дякую за будь-які покажчики! WoJ


пов'язані: flashbake
Dan D.


Чи є особлива вимога щодо того, яке програмне забезпечення ви використовуєте? Тому що якщо ви хочете лише відстежувати зміни, які ви робите вручну (редагуючи файли), Eclipse має вбудовану функцію, її називають "локальною історією".
Стефан Зайдель

@StefanSeidel Я не є початковою темою, але я вважаю за краще рішення без IDE.
Михайло Паньков

Відповіді:


6

1. Метод загального призначення за допомогою базару та інновації

Мене це не перевіряє, але я знайшов цей запис, який використовує bzr(bazaar) & inotifywaitдля моніторингу каталогу та версій, керування файлами в ньому за допомогою базару.

Цей скрипт виконує всю роботу по перегляду каталогу для змін:

#!/bin/bash

# go to checkout repository folder you want to watch
cd path/to/www/parent/www
# start watching the directory for changes recusively, ignoring .bzr dir
# comment is made out of dir/filename
# no output is shown from this, but wrinting a filename instead of /dev/null 
# would allow logging
inotifywait –exclude \.bzr -r -q -m -e CLOSE_WRITE \
    –format=”bzr commit -m ‘autocommit for %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
# disown the pid, so the inotify thread will get free from parent process
# and will not be terminated with it
PID=`ps aux | grep inotify | grep CLOSE_WRITE | grep -v grep | awk ‘{print $2}’`
disown $PID

# this is for new files, not modifications, optional
inotifywait –exclude \.bzr -r -q -m -e CREATE \
    –format=”bzr add *; bzr commit -m ‘new file added %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
PID=`ps aux | grep inotify | grep CREATE | grep -v grep | awk ‘{print $2}’`
disown $PID

exit 0;

2. Керування / тощо

Для особливого випадку управління /etcкаталогом вашої системи ви можете скористатися додатком etckeeper .

etckeeper - це набір інструментів, які дозволяють / тощо зберігатись у сховищі git, mercurial, darcs або bzr. Він підключається до apt (та інших менеджерів пакетів, включаючи yum та pacman-g2), щоб автоматично здійснювати зміни, внесені в / etc під час оновлення пакету. Він відслідковує метадані файлів, які системи керування переглядом зазвичай не підтримують, але це важливо для / і т.д., наприклад, дозволи / etc / shadow. Він досить модульний і настроюється, а також простий у використанні, якщо ви розумієте основи роботи з контролем редагування.

Ось хороший підручник для початку роботи з ним.

3. Використання git та інкрон

Ця методика використовує gitта incron. Для цього методу потрібно зробити наступне:

А. Зробіть репо

% mkdir $HOME/git
% cd $HOME/git
% git init

B. Створіть $HOME/bin/git-autocommitсценарій

#!/bin/bash

REP_DIR="$HOME/git"       # repository directory
NOTIFY_DIR="$HOME/srv"    # directory to version

cd $REP_DIR
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git add .
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git commit -a -m "auto"

C. Додайте запис до inrontab

% sudo incrontab -e $HOME/srv IN_MODIFY,IN_CREATE,IN_MOVED_FROM,IN_MOVED_TO $HOME/bin/git-autocommit

4. Використання Flashbake

Інший варіант - використовувати такий інструмент, як Flashbake . Flashbake - це система контролю версій, яку Cory Doctorow (слава BoingBoing) використовує для написання своїх книг.

Flashbake використовує git під капотом для відстеження змін, але десь між тим, як робити автоматичні резервні копії та використовувати звичайну систему контролю версій самостійно.

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

Ресурси


3
inotifywait + "git local" = gitwatch.sh, дивіться тут: github.com/nevik/gitwatch/blob/master/gitwatch.sh
diyism

4

Зразу на думку приходить ZFS . Він може створювати знімки - і є деякі проекти для автоматичного створення знімків .


Я читав про ZFS, але, схоже, це не стабільне рішення для базових файлових систем (принаймні в Linux)
WoJ

Мені б дуже хотілося, щоб рішення перехрестилося на існуючі ФС.
Михайло Паньков

Можливо, це? ext3cow.com
Zac B

3

Я думаю, що ти на правильному шляху inotify. У цій статті детально описано її основне використання у випадку, подібному до вашого. Я б запропонував використовувати його безпосередньо або компілювати утиліту рівня ядра, наприклад fschange . Це щось непотрібне, але ви можете прив’язати виявлення змін до git commitподібного чи подібного.

Ці рішення мають і те, що покладаються на дещо недосконалі сторонні рішення. Якщо ви не заперечуєте брудними руками, NodeJS пропонує чудову платформу для всіх платформ ( fs.watch ) саме для цієї мети. Основний посібник щодо перегляду файлів щодо змін у NodeJS можна знайти тут . Через кілька десятків рядків або менше ви можете написати щось, що дивиться каталог файлів, а потім викреслити (через child_process ) і запустити git commitподібний (або навіть вручну збільшувати індекс файлу версії, якщо вам подобається roll-your- власний підхід).

fs.watchпідтримується inotifyна Linux, але це набагато інтуїтивніше у використанні. Є й інші проекти NodeJS, які забезпечують функціональність перегляду файлів у різних рівнях зручності, як цей, чи цей .


Все ще не готове рішення, і, ну, я, мабуть, пішов би з Python's inotify. Але спасибі
Михайло Паньков

3

inotify (2) в Linux не зможе дивитися велике дерево, але файлова система запобіжників (змонтована в окремому місці), ймовірно, може обробити це, переклавши запити файлової системи на svn або git виклики, або безпосередньо змінивши метадані svn / git.

Це дуже цікава ідея, але я не чув про жодні існуючі реалізації.


Скажімо, у мене є лише пара файлів.
Михайло Паньков

0

Такий сценарій не важко написати.

Мій улюблений контроль версій - git.

наступний сценарій повинен зробити це:

#!/bin/sh
git add .
git commit -am "my automatic commit"

або періодично перевіряйте вашу папку - або після редагування виклику редактора звертаються до сценарію.

Але якщо ви робите це так, можливо, має сенс виключати великі файли та, можливо, деякі "непотрібні", наприклад, автоматичні збереження.


Так, я знаю, що рішення на основі хронів легко здійснити. Однак я шукаю те, що могло б зробити версію для збереження, незалежно від механізму збереження. Це також, чому я згадував autoversionninf на svn, а також ініціював у своєму запитанні.
WoJ

0

SparkleShare ( http://sparkleshare.org ) заснований на git та реалізує функцію Dropbox-Like з керуванням версіями, але ви повинні налаштувати ssh-сервер (може бути localhost).


Ця річ незграбна і вимагає багато налаштувань. Крім того, функція Dropbox не потрібна.
Михайло Паньков


0

Існує також спосіб "бідного чоловіка" зробити це, використовуючи лише rsync та роботу з cron. Ви в основному покладаєтесь на засоби резервного копіювання rsync і використовуєте два окремі шляхи плюс префікс / суфікс для відстеження своїх файлів.

Він більше менш виглядає так: / usr / bin / rsync -a -A -X --backup --suffix =date +".%Y-%m-%d_%H-%M-%S" $ source_path $ backup_path

Кінцевий результат: Якщо змінити файл під назвою test_rsync у вихідному контурі після первинного виконання, у шляху резервного копіювання буде створено файл під назвою test_rsync.2017-02-09_11-00-01.

З цим існує маса проблем (це працює, якщо у вас є лише пристойний обсяг файлів і не вдасться зміни, які відбудуться між двома послідовними запусками rsync (1 хвилина в моєму випадку)), але це може бути достатньо для ваших потреб.

Якщо ми говоримо тут про акції samba, можливо, в списку виключень може бути порядок, я цього ще не обійшов.

Повідомте мене, якщо ви вдосконалите це.


0

Ось сценарій Python3, який VMS любить автоматичну версію файлів, використовуючи часову марку, додану до оригінального імені файлу при збереженні.

Я вклав купу коментарів до сценарію і запустив півтисячі таких сценаріїв на моїй машині ubuntu, причому лише різні каталоги відрізняються у кожній різній версії сценарію, так що я одночасно оновлюю декілька каталогів. Ніякого реального штрафу за продуктивність машин.

! / usr / bin / env python3

print ("ФАЙЛИ ПРОЕКТУ, НАЧАЛЕННЯ ВЕРСІОНІЗА") print ("version_creation.py") #замістіть увесь цей код у скрипті цього імені print ("запустити як .." python3 version_creation.py 'з командного рядка ") print (" ctrl " c "для зупинки") print ("") print ("Для запуску програми у фоновому режимі введіть нижче командного рядка, а потім закрийте вікно.") print ("nohup python3 version_creation.py") print (".... to зупинити процес, перейти в меню / адміністрування / монітор системи ... і вбити python3 ") друкувати (" ") друкувати (" Завжди зберігати файли у каталозі "ProjectFiles" та файли версій ") print (" також буде створено в цьому каталозі . ") друкувати (" ") друкувати (" ") друкувати (" ") друкувати (" ")

імпорт shutil імпорт os час імпорту

--- встановіть інтервал часу, щоб перевірити наявність нових файлів (у секундах) нижче

- цей інтервал повинен бути меншим за інтервал появи нових файлів!

t = 10

--- встановити вихідний каталог (dr1) та цільовий каталог (dr2)

dr1 = "/ шлях / до / source_directory"

dr2 = "/ шлях / до / target_directory"

імпорт глобальний імпорт ос

dr1 = "/ home / michael / ProjectFiles" #both оригінали та версії будуть збережені в цей каталог

dr2 = "/ home / michael / ProjectFileVersions"

істинно:

if os.listdir(dr1) == []:

друк ("Порожня")

    n = 100
else:
    list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
    latest_file_path = max(list_of_files, key=os.path.getctime)

print ("1 Останній_файл_пат =", останній_файл_пут)

    originalname = latest_file_path.split('/')[-1]

print ("2 originalname =", originalname)

    filecreation = (os.path.getmtime(latest_file_path))

print ("filecreation =", розробка файлів)

    now = time.time()
    fivesec_ago = now - 5 # Number of seconds

print ("Fivesec_ago =", Fivesec_ago)

    timedif = fivesec_ago - filecreation #time between file creation

print ("timedif =", timedif)

    if timedif <= 5: #if file created less than 5 seconds ago

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)



        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr1+"/"+newassembledname
        print ("8 target = ", target)

        shutil.copy(source, target)


    time.sleep(t)

поділитися

нижче було поставлено раніше і працює, але мені подобається вищезгаданий сценарій python набагато краще ...... (використовую python близько 3 годин)

#!/usr/bin/env python3

print ("PROJECT FILES VERSIONING STARTED")
print ("projectfileversioning.py")
print ("run as..  'python3 projectfileversioning.py'       from command line")
print ("ctrl 'c'      to stop")
print (" ")
print ("To run program in background type below to command line and then close the window. ")
print ("nohup python3 projectfileversioning.py")
print ("....to stop process go menu/administration/system monitor... and kill python")
print (" ")
print ("Always save files to the 'ProjectFiles' directory and the file ")
print ("   will be redirected to the ProjectFileVersions where")
print ("   time stamped versions will also be created.")
print (" ")
print ("If you like you may then copy/move the versioned and original file from 'ProjectFileVersions' to ")
print ("any other directory you like.")

import shutil
import os
import time

#--- set the time interval to check for new files (in seconds) below 
#-   this interval should be smaller than the interval new files appear!
t = 10

#--- set the source directory (dr1) and target directory (dr2)
#dr1 = "/path/to/source_directory"
#dr2 = "/path/to/target_directory"

import glob
import os

dr1 = "/home/michael/ProjectFiles"
dr2 = "/home/michael/ProjectFileVersions"


while True:

    if os.listdir(dr1) == []:
        n = 100
    else:
        list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
        latest_file_path = max(list_of_files, key=os.path.getctime)
        print ("1 Latest_file_path = ", latest_file_path)

        originalname = latest_file_path.split('/')[-1]
        print ("2 originalname = ", originalname)

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)




        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr2+"/"+originalname
        print ("8 target = ", target)

        shutil.copy(source, target)



        source = dr1+"/"+originalname
        print ("9 source = ", source)

        target = dr2+"/"+newassembledname
        print ("10 target = ", target)

        shutil.move(source, target)
        time.sleep(t)


#share
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.