Вот такая вот сказочка. Собственно задача такова: создать родительский проект maven содержащий историю всех подпроектов, находившихся ранее в отдельных репозиториях. В принципе это очень просто делается по этой инструкции. Но если следовать данной инструкции у репозитория получится несколько хвостов (как на рисунке ниже).
1 2 3 4 5 6 7 8 9 10 |
|
Мне бы хотелось видеть историю в виде примерно такого графа:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Перфекционист во мне не удовлетворился таким положением дел, и в итоге, после пары часов консольной магии, было найдено следующее решение.
Сделаем ход конем и изменим историю так что бы было похоже на то что изначально разработка велась в подпапках основного репозитория. Это необходимо для того, что бы исключить конфликты файлов при последующем слиянии. Что бы провернуть это, экспортируем патч и изменим пути файлов. (Здесь и далее я буду считать что все репозитории находятся на одном уровне в файловой системе)
1 2 3 4 5 6 7 8 9 10 |
|
Для каждого из проектов делаем тоже самое (достаточно поменять только переменную PROJECT
в начале скрипта)
Если вместо того что бы плодить безымянные ветки вы захотите разнести историю отдельных проетов по именованым веткам, то достаточно для всех проектов кроме первого выполнить следующие команды, для добавления информации об имени ветки в патч:
1 2 |
|
После того как мы создали патчи для каждого из проектов, сольем их в один. В первую очередь инициализируем новый репозиторий агрегирующий историю всех проектов.
1 2 |
|
Для всех остальных проектов делаем следующие махинации:
--import-branch
)Этот подход проиллюстрирован ниже. Для способа без использования именованых веток действий нужно сделать немного меньше и в принципе можно легко автоматизировать процесс:
1 2 3 |
|
Если же использовались именованые ветки то стоит делать так:
1 2 3 4 5 6 7 |
|
По мотивам данной статьи был создан скрипт:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Буду рад если кому нибудь поможет эта статья. Замечания приветствуются.
]]>Хочу поделиться с сообществом небольшим велосипедом - расширением для мавена позволяющим получать доступ к репозиториям с кастомной структурой.
Для начала расскажу как я до такого докатился. В процессе работы над проектом пришла мысль о том зависимости JavaScript типа JQuery ничем не управляются, и при обновлении приходится качать библиотеки вручную, что совершенно не впечатляет. И вот так появилось дикое желание найти какой-нибудь менеджер зависимостей но для javascript. В первую очередь в своих поисках я наткнулся на Bower но необходимость введения дополнительного шага в процессе сборки отпугивало как node.js в зависимостях. Тут я вспомнил про CDN с коих можно невозбранно тянуть js-библиотеки (например jquery на Google CDN: http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js). Поскольку в проекте используется maven для сборки то логичной мыслью было натравить его на эти залежи библиотек… Но все оказалось не так просто. Дело в том что структура файловой системы CDN отличается от стандартной для для maven. После 2 часов поиска решения на просторах интернетов найдено не было,и решил я написать свой велосипед. Если я еще не утомил вас то прошу под кат.
В процессе поиска готовых решений было замечено что можно написать расширение для maven обрабатывающее кастомный тип репозиториев. Правда не смотря на то что везде писалось что сделать можно, как это сделать нигде написано не было. Только однажды промелькнуло то что для этой цели служит интерфейс RepositoryConnectorFactory. На скорую руку был набросан простенький класс реализующий данный интерфейс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Однако после подключения расширения к проекту, чуда не случилось - расширение не вызывалось, а мавен продолжал ругаться на не поддерживаемый тип репозитория. Как в оказалось дальнейшем для правильной работы расширения необходимо сгенерировать описание компонента в файле META-INF/plexus/components.xml. Для создания которого, можно воспользоваться плагином plexus-component-metadata, который распарсит аннотации к классам и создаст этот волшебный файлик.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
После включения генерации components.xml и установки плагина в локальный репозиторий все заработало.
Теперь расскажу как использовать это безобразие. В первую очередь подключаем репозиторий с плагином (пока что я выложил в своем репозитории, в дальнейшем буду думать как поместить в Maven Central):
1 2 3 4 5 6 |
|
И включаем расширение в секции build pom.xml:
1 2 3 4 5 6 7 8 9 |
|
Подключаем необходимые репозитории, например так:
1 2 3 4 5 |
|
В URL репозитория указываются подстановочные символы которые будут заменены на соответствующие параметры для закачиваемого артифакта. Привожу список всех поддерживаемых подстановочных символов:
Для параметров значение которых может быть пустым доступен альтернативный синтаксис: ${classifier(prefix:.)}
. Это сделано для того что бы не дублировать разделители в URL в случае пустого значения параметра.
После подключения репозитория подключаем зависомости например так:
1 2 3 4 5 6 7 8 9 |
|
Для копирования загруженных библиотек в папку веб приложения используем maven-dependency-plugin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Собственно все. Проблема решена - мы добились возможности рулить JS зависимостями с помощью maven.
Исходные коды плагина можно найти здесь: https://bitbucket.org/eburtsev/maven-custom-repository-layout Сам плагин можно использовать напрямую из моего репозитория maven: http://maven.burtsev.net/ Пример проекта с использованием описываемого расширения https://bitbucket.org/eburtsev/test-javascript-dependencies
]]>В первую очередь необходимо добавить в зависимости проекта артефакт org.springframework:spring-web:
1 2 3 4 5 |
|
Остальные необходимые зависимости maven подтянет сам.
Чтобы все заработало нужно настроить слушателей в web.xml, как показано в примере ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Так же необходимо установить el-resolver из Spring взамен стандартного, чтобы дать возможность спрингу рулить бинами. Для этого меняем faces-config.xml:
1 2 3 4 5 6 7 8 9 |
|
Теперь настроим spring-context.xml. Собственно тут все сводится к изменению значения base-package для context:component-scan:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Ну а теперь после того как все необходимые настройки сделаны - попробуем написать код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Здесь нужно отметить использование аннотации @Controller вместо @ManagedBean и @Scope для указания времени жизни бина. Список всех возможных scope можно посмотреть тут: Spring Framework Reference. Так же стоит отметить отсутствие view scope по дефолту. Но эту проблему можно обойти, например, как описано в этой статье или в этой
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Запускаем, переходим по адресу: http://localhost:8080/jsf2-spring-example/index.jsf и видим что все работает :)
P.S. Полный проект можно взять здесь: github repository
]]>В поиске было найдено несколько репозиториев, но во всех из них лежат только старые версии библиотеки.
Так же был найден замечательный скрипт для создания локального maven-репозитория.
Поскольку не у всех есть время и возможность создать свой репозиторий (под Windows например у меня этот скрипт запустить так и не получилось), то я решил выложить результаты работы у себя на сервере - вдруг кому-то и сгодится.
Подробности под катом
Как пользоваться:
Во-первых подключить репозиторий в вашем pom.xml
, например как в примере ниже:
1 2 3 4 5 6 7 |
|
Или можно воспользоваться зеркалом на github’e:
1 2 3 4 5 6 7 |
|
И во-вторых подключить необходимые зависимости. Например подключим Calendar API версии 2.0:
1 2 3 4 5 |
|
Собственно все :) Надеюсь кому то это пригодится :)
P.S. Модифицированную версию скрипта можно взять здесь
Upd. 2012-04-24: Репозиторий обновлен, добавлены библиотеки версии v1.47.0
Upd. 2012-08-14: Репозиторий обновлен, добавлены библиотеки версии v1.47.1
Upd. 2012-12-23: В репозиторий добавлены исходники и javadoc’и
1 2 3 4 |
|
Но вот беда - класс org.apache.ibatis.session.SqlSession из MyBatis 3.0.6 использующегося в проекте не реализует интерфейс AutoCloseable необходимый для того что бы эта конструкция заработала. Надеюсь что в следующей версии поддержку добавят, а пока предлагаю небольшой workaround.
В первую очередь реализуем обертку для класса SqlSession реализующую интерфейс AutoCloseable:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
|
Также нам понадобится обертка для SqlSessionFactory умеющая работать с нашим классом SqlSession.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
Ну а теперь - магия: конфигурируем iBatis как обычно. Ну почти как обычно, за исключением строки 18, где мы инициализируем нашу обертку.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
Это все, теперь мы можем радоваться фишками java7 в проекте :)
]]>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Для решения этой проблемы нужно установить свойства poolPingQuery и poolPingEnabled в конфиге iBatis. Например, как это сделано в примере ниже в строках 17 и 18.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Наверное каждый кто начинал пользоваться библиотекой задавался вопросом “Почему компоненты выглядят такими огромными, хотя в демо они смотрятся гораздо приличнее?”. Для решения этой проблемы достаточно добавить внутри тега <h:head></h:head>
следующий CSS код:
1 2 3 4 5 6 |
|
При использовании данной библиотеки в IE могут возникать проблемы с рендерингом, для избавления от которых рекомендуется устанавливать заголовок X-UA-Compatible. В старых версиях библиотеки (до 3.0) это делалось установкой тега meta в начале <h:head></h:head>
. Однако начиная с версии 3.0 библиотека сначала вставляет свой код в тег head, а уже следом за ним пользовательский. Для того что бы обойти эту проблему в третьей версии был определен facet “first”, содержимое которого вставляется в самое начало тега head:
1 2 3 4 5 6 7 8 9 |
|
Поскольку компоненты библиотеки основаны на jQueryUI, то для создания вертикальных табов можно использовать решение из этого демо. Во первых необходимо добавить CSS код:
1 2 3 4 5 6 7 8 |
|
А во вторых подключить класс к нужному tabView
1
|
|
Данное решение было найдено по мотивам данных вопросов на StackOverflow: * Make tabs appear vertically on the side when using PrimeFaces TabView * Vertical Tabs with JQuery?
Пока что это все :) При появлении еще каких нибудь заметок, обязуюсь выложить их на всеобщее обозрение.
]]>Все нижеописанные действия производятся из под рута. Итак, приступим :)
В первую очередь поставим Python.
apt-get install python
Так же для удобства добавления сторонних PPA можно поставить python-software-properties:
apt-get install python-software-properties
После этого PPA можно добавлять командой
add-apt-repository ppa:xxx/yyy
Поскольку в репозитории Lucid Lynx находится версия mercurial’а, древняя как говно мамона, то подключаем PPA с новыми версиями:
add-apt-repository ppa:mercurial-ppa/stable-snapshots
apt-get update
apt-get install mercurial
В основном репозитории nginx отсутствует поэтому подключаем PPA и устанавливаем.
add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx
В качестве сервера python-приложений установим uwsgi-python.
add-apt-repository ppa:uwsgi/release
apt-get update
apt-get install uwsgi-python
Теперь после установки софта начинается самое сложное - настройка. Во первых, рассмотрим структуру директорий, которая будет использоваться.
/var/www/hosts/hg.server.net/conf здесь будут расположены конфиги
/var/www/hosts/hg.server.net/logs директория для логов
/var/www/hosts/hg.server.net/repos директория, содержащая репозитории
Создадим файл описания UWSGI-приложения /etc/uwsgi-python/apps-available/hgweb.xml
примерно такого содержания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Параметр socket задает адрес который будет прослушивать сервер. workers количество запущенных воркеров. Обратите внимание что в 14-ой строке необходимо указать правильный путь к конфигу hgweb, созданием которого мы сейчас и займемся.
Для этого создаем файл /var/www/hosts/hg.server.net/conf/hgweb.config
:
1 2 3 4 5 6 7 8 |
|
Во второй строке мы разрешаем проталкивать изменения только по SSL.
В третьей можно перечислить через запятую пользователей которым разрешено проталкивать изменения на сервер.
В четвертой выбирается стиль интерфейса. Мне больше всего нравится gitweb.
в последней строке необходимо установить корректные пути до репозиториев.
Теперь, для проверки корректности настроек временно поменяем строку <socket>/var/run/uwsgi.hgweb.sock</socket>
в файле hgweb.xml на <socket>127.0.0.1:3031</socket>
и запустим следующую команду:
uwsgi-python -x /etc/uwsgi-python/apps-available/hgweb.xml
Если все настроено верно то никаких ошибок выведено не будет. И если зайти браузером по адресу http://127.0.0.1:3031/
то отобразится список репозиториев. Если все нормально то меняем файл hgweb.xml обратно и создаем симлинк в /etc/uwsgi-python/apps-enabled
:
ln -s /etc/uwsgi-python/apps-{available,enabled}/hgweb.xml
Теперь можно переходить к следующему этапу.
Создадим файл паролей при помощи утилиты htpasswd
htpasswd -c /var/www/auth/.htpasswd <username>
Создаем конфиг /etc/nginx/sites-available/hg.server.net
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
Делаем симлинк для нашего конфига в /etc/nginx/sites-enabled
:
ln -s /etc/nginx/sites-{available,enabled}/hg.server.net
Запускаем сервисы
service uwsgi-python start
service nginx start
Если все хорошо то зайдя по адресу http://hg.server.net/
увидим список репозиториев.
Если это так то сделаем что бы все запускалось автоматически при старте системы и забудем о настройке.
Во первых убедитесь что сделали симлинки на конфиги. Во вторых следует настроить сервисы для автоматического запуска:
update-rc.d uwsgi-python defaults
update-rc.d nginx defaults
Все - настройка завершена, можно перезагрузиться и еще раз проверить работу.
]]>