Системы управления версиями

индекс
161,00

Gource — визуализируем историю работы над проектом

Спешу рассказать хабрасообществу о, относительно новом, дьявольски завораживающем проекте Gource которое еще не упоминалось. Это приложение позволяет визуализировать историю изменений в системе контроля версии. Отрисовывает невероятно красиво при помощи OpenGL.




Скриншоты, еще видео.



Git поддерживается нативно. Для CVS, SVN, Mercurial существуют скрипты позволяющие привести логи в нужный формат.

Имея необходимые кодеки и конвертер ffmpeg можно рендерить в видео-файл:
gource --output-ppm-stream - | ffmpeg -y -b 3000K -r 60 -f image2pipe -vcodec ppm -i - gource.h264

Управление просмотром:
  • Клик правой кнопкой — переводим в режим автоматической «наводки» на активных пользователей
  • Q — информация о рендеринге
  • ↑↓ — зум
  • Пробел — пауза
  • с остальными еще не разобрался :)


Приложение open-source, доступна бинарная версия под win и .deb пакет.
http://code.google.com/p/gource/downloads/list

ps. Я использовал следующие ключи для запуска gource -1280x1024 -f --highlight-all-users --multi-sampling для того чтобы запустить на полный экран в максимальном (для монитора) разрешении и постоянно видеть логины пользователей.



_________
Текст подготовлен в ХабраРедакторе
+57
19 ноября 2009, 17:56
108

комментарии (49)

+1
web4_0 #
Очень напоминает программку, которая рисовала дерево в зависимости от html-тэгов страницы — получалось почти то же, что и на видео.

Ну и в любом случае, получается душевнее, чем revision graph у того же CVS.
0
Razunter #
А что за программка?
+2
Wolverine #
–1
pxx #
Классная штука. Затягивает…
+1
el777 #
А музыку оно само накладывает?
Или вы ее руками в ролик вставили?
+1
zhekanax #
Ролик с официального сайта. Приложение само по себе беззвучное :)
0
Swanky #
Историю версий лучше бы таймлайном реализовать ) интереснее было бы )
0
zhekanax #
Здесь изменения отображаются именно в хронологическом порядке.
0
NYV #
для VSS реально использовать?
0
zhekanax #
Если имеется возможность вывести логи изменений и привести их к виду:
1258533954|user|M|/trunk/abc.ru/www/js/jquery.js|
1258533954|user|D|/trunk/abc.ru/www/js/jquery.old.js|
то ответ — «да, можно»

нативно работает только git, стальное конвертируется скриптами
0
NYV #
ну как вариант поискать возможность порта на git или svn и т.д. =)
0
NYV #
кому интересно vvs2svn — ___http://vacula2.blogspot.com/2008/01/vss-svn.html
0
zabr #
Unsupported log format.
+1
Mezomish #
Берите пример с соседнего топика:

«Спешу рассказать хабрасообществу о относительно новом крышесносящем проекте Gource о котором еще не было упоминания» :)
0
zhekanax #
не смог подобрать синонимов, поэтому немног оперефразировал :)
«Спешу рассказать хабрасообществу о, относительно новом, дьявольски завораживающем проекте Gource»
0
developer #
кружочки — это файлы или изменения?
0
zhekanax #
кружочки это ноды, ноды могут файлами или директориями.
лучи которые испускают пользователи бывают трех цветов:
* зеленый — добавление
* оранжевы — модификация
* красный — удаление
0
Terror #
Всегда поражают подобные проекты, завидую белой завистью. Каждый раз задаюсь вопросом — что они курят где они берут такие идеи? :)
+5
andrew_b #
Очень забавно смотреть за пользователями, они прям как пчелы, опыляющие цветок
0
slatvick #
Точно, очень на пчел похоже!
Интересно попробовать на своем тоже.
0
darkstar #
музыка! чей трек в этом ролике?
0
Tar #
Нет ли у кого cvs-exp (для конвертации cvs лога в нужный формат)?
Все ссылки ведут на www.cs.rice.edu/~ssiyer/code/cvs-exp/ где 404
0
zhekanax #
А можно взглянуть на формат? Я не поленюсь написать парсер. (Не раньше чем утром)
Было бы хорошо пример на почту me [at] zhekanax.ru
0
zhekanax #
Хотя могу и сам получить лог из общедоступного проекта — не за чем приватную информацию слать :))
+2
zhekanax #
gource.googlecode.com/files/cvs-exp.pl вернули пропавший скрипт
+2
Honeyman #
Ве-ли-ко-лепно.
Больше часа на максимальной скорости смотрел на развитие нашего проекта. Завораживает.
0
gAmUssA #
а какая там максимальная скорость и как её установить?
0
Honeyman #
Ну, я пользовался -s 1 --max-file-lag 10. Правда, что-то не уверен, что вторая опция помогла.
+1
Sveolon #
Супер-вещь! Посмотрел не отрываясь. Поставил на ночь виде конвертироваться. Наложу звук и устроим завтра всем отделом просмотр :)
0
Tar #
Не травите душу (
cvs-exp.pl нигде в инете нет, выдрать cvs-log в нормальном виде не получается, попытка реинжениринга сорцов для написания парсера взрывает мозг
0
zhekanax #
gource.googlecode.com/files/cvs-exp.pl вернули пропавший скрипт
0
slatvick #
Граждане, помогите установить на MacOSX. "./configure" в конце выдает: «configure: error: *** SDL version 1.2.0 not found!»
А SDL не знаю, как установить, там нормального гида нет. Тупо копирование в "..../Frameworks" не помогает. SDL беру из www.libsdl.org/release/SDL-1.2.14.dmg
Кто понимает в этом лучшее моего?
+1
Woof #
поставьте macports, через них необходимые зависимости устанавливайте
0
slatvick #
Да, это стало откровением. Дело пошло. Столько либ всяких для SDL устанавливается, капец.
0
slatvick #
Все понятно. Это того просто не стоит.
За пару часов смог сделать configure без ошибок. Теперь выскочили ерроры при билде. С этим уже точно разбираться нет охоты.
Всем спасибо.
0
DoctorDemon #
Ух ты, вот это круто!
0
Aquary #
Это просто праздник какой-то… Класс!
0
Baofy #
Чем то похоже на игру Eufloria.
0
zabr #
Как получить логи TFS:

1. качаем Visual Studio SDK.
2. В Reference добавить: Microsoft.TeamFoundation.Client, Microsoft.TeamFoundation.VersionControl.Client
3. заюзать примерно такой код на C# ), правила сами замените если нужно )

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace GourceTFS
{
  class Program
  {
    private const string outFile = "output_log.txt";
    const string tfsServerURL = "http://server:8080";

    /* If you want to use Gource with something other than the supported systems, there is a pipe delimited custom log format:  
     * timestamp - A unix timestamp of when the update occured.  
     * username - The name of the user who made the update.  
     * type   - Single character for the update type - (A)dded, (M)odified or (D)eleted.  
     * file   - Path of the file updated.  
     * colour  - A colour for the file in hex (FFFFFF) format. Optional.    
     */

    /// <summary>
    /// method for converting a System.DateTime value to a UNIX Timestamp
    /// </summary>
    /// <param name="value">date to convert</param>
    /// <returns></returns>
    private static double ConvertToTimestamp(DateTime value)
    {
      //create Timespan by subtracting the value provided from
      //the Unix Epoch
      TimeSpan span = (value - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime());

      //return the total seconds (which is a UNIX timestamp)
      return span.TotalSeconds;
    }

    [Serializable]
    class ChangeItem
    {
      public double timestamp { get; set;}
      public string username { get; set; }
      public char type { get; set; }
      public string file { get; set; }

      /// <summary>
      /// Converts the specified type.
      /// </summary>
      /// <param name="type">The type.</param>
      /// <returns></returns>
      public static char Convert(ChangeType type)
      {
        char _out = '\0';
       
        if (type == (ChangeType.Add | ChangeType.Edit | ChangeType.Encoding))
        {
          _out = 'A';
          return _out;
        }

        if (type == (ChangeType.Encoding | ChangeType.Delete | ChangeType.Branch))
        {
          _out = 'D';
          return _out;
        }

        switch (type)
        {
          case ChangeType.Add:
            _out = 'A';
            break;
          case ChangeType.Merge:
            _out = 'M';
            break;
          case ChangeType.Edit:
            _out = 'M';
            break;
          case ChangeType.Delete:
            _out = 'D';
            break;
        }

        if (_out == '\0')
        {
          throw new ArgumentException("fff");
        }

        return _out;
      }
    }

    static void Main()
    {
      var TFSLogs = TFSLogsList();

      using (var sw = new StreamWriter(outFile, false, Encoding.UTF8))
      {
        foreach (var item in TFSLogs)
        {
          sw.WriteLine("{0}|{1}|{2}|{3}", Math.Floor(item.timestamp), item.username, item.type, item.file);
        }
      }

      var pi = new ProcessStartInfo
             {
               FileName = Application.StartupPath + @"\Gource\gource.exe",
               Arguments = outFile + "--log-format custom -1280x1024 -f --highlight-all-users --multi-sampling ",
               UseShellExecute = true
             };

      var p = new Process {StartInfo = pi};
      p.Start();

      Console.Read();
    }

    static List<ChangeItem> TFSLogsList()
    {
      const string _tfsPath = "$/SomePlace";

      var tfs = TeamFoundationServerFactory.GetServer(tfsServerURL);
      var vcs = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));  // Null means All  
      const VersionSpec versionFrom = null;

      var history = vcs.QueryHistory(_tfsPath,
                      VersionSpec.Latest,
                      0,
                      RecursionType.Full,
                      "",
                      versionFrom,
                      VersionSpec.Latest,
                      Int32.MaxValue,
                      true,
                      false);

      var GourceList = new List<ChangeItem>();
      var changesets = new List<Changeset>();
      foreach (var _item in history)
      {
        changesets.Add((Changeset)_item);
      }

      var o = new Comparison<Changeset>((p, y) => p.ChangesetId.CompareTo(y.ChangesetId));
      changesets.Sort(o);

      foreach (var changeset in changesets)
      {
        foreach (var change in changeset.Changes)
        {
          if (change.Item.ItemType == ItemType.Folder) continue;
          var item = new ChangeItem
          {
            username = changeset.Committer,
            type = ChangeItem.Convert(change.ChangeType),
            file = change.Item.ServerItem,
            timestamp = ConvertToTimestamp(change.Item.CheckinDate)
          };

          GourceList.Add(item);
        }

        Console.WriteLine("Adding changeset: " + changeset.ChangesetId);
      }

      return GourceList;
    }
  }
}

* This source code was highlighted with Source Code Highlighter.


P.S жаль что формат не распознался проектом Gource. Хотя делал по разному подбирая их custom format. ((
0
zabr #
Math.Floor может необязателен.
+1
zabr #
а [Serializable] по привычке )
+1
zhekanax #
> "{0}|{1}|{2}|{3}"
а если добавить еще один | в конце? как в их формате
0
zabr #
пробовал. по всякому не работает.
если подберешь поделись )
0
zhekanax #
$ file tmp.log
tmp.log: ASCII text
$ cat tmp.log
1142233434|zhe|A|/trunk|
1142233494|barba|A|/trunk/index.php|
1142233434|zhe|M|/trunk|
1142233434|zhe|D|/trunk/index.php|
$ gource --log-format custom tmp.log

Насколько я вижу кодировка utf8, думаю стоит использовать однобайтовую или хотя бы попробовать убрать BOM
0
zabr #
а кстати возможный вариант )
0
zabr #
Все Гуд, счас буду пытаться видео записать )))

Формат: {0}|{1}|{2}|{3}
Нужно делать в ASCII.

var pi = new ProcessStartInfo
{
FileName = Application.StartupPath + @"\Gource\gource.exe",
Arguments = outFile + "--log-format custom -1280x1024 -f --highlight-all-users --multi-sampling ",
UseShellExecute = true
};

Поменять на:

var pi = new ProcessStartInfo
{
FileName = Application.StartupPath + @"\Gource\gource.exe",
Arguments = " --log-format custom " + outFile + " -1280x1024 -f --highlight-all-users --multi-sampling ",
UseShellExecute = true
};
0
zhekanax #
заодно можешь рассказать хабрапользователю pasha_golub (комменатрий ниже) как в win записать видео. Насколько я понимаю, вы на одной платформе :)
0
pasha_golub #
Чумовая штука. Я уже все репы свои из SVN трансформировал.

Друзья, а под Windows возможно видео записать? Я попробовал и не вышло. Если можно, покажите точно как должна выглядеть коммандная строка.

Спасибо заранее
0
catcher #

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.