вторник, 29 апреля 2014 г.

How to по git. Для склеротиков.

Настройка Git клиента для идентификации пользователя:
git config --global user.name "Your Name"
git config --global user.email "your@email.address"
git config --global core.editor "your editor"
Инициализация репозитория в текущем каталоге:
git init
Создает репозиторий в указанном каталоге:
git init <directory>
Клонирование репозитория на локальную машину:
git clone <repo>
Добавить файл для идексации и следить за всеми изменениями в нем ( можно задавать по маске ):
git add <file>
Добавить каталог для индексации:
git add <directory>
Удалить файл из индексации ( можно задавать по маске ):
git rm <file>
Перенести или переименовать файл / каталог:
git mv <source> <destination>
Сделать "снапшот" всех выполненных изменений:
git commit -a -m "message"
Статус репозитория ( добавление, удаление, изменение файлов ):
git status
Показать историю коммитов:
git log
Показать только определенное количество коммитов:
git log -n <limit>
Показать историю коммитов по конкретному файлу:
git log <file>
Посмотреть различия между последним коммитом и текущими изменениями:
git diff
Просмотр всех различий между коммитами:
git diff <commit> <commit>
Посмотреть различия между коммитом и текущими изменениями:
git diff <commit> <file>
Посмотреть различия между коммитами для файла:
git diff <commit> <commit> <file>
Показать список всех файлов в основной ветке:
git ls-tree master -r --name-only
Работа с ветками

Список веток:
git branch
Создание ветки:
git branch <new_branch_name>
Безопастное удаление ветки, если не были сделаны изменения:
git branch -d <branch_name>
Удаление ветки, даже если были сделаны изменения:
git branch -D <branch_name>
Переименование текущей ветки:
git branch -m <rename_current_branch>
Переход к существующей ветке:
git checkout <branch_name>
Создание и переход к ветке:
git checkout -b <new_branch_name>
Слияние текущей ветки с указанной:
git merge <branch>
Откат изменений

Перейти на последний коммит ветки "master":
git checkout master
Откатить изменения во всех файлах до указанного коммита:
git checkout <commit>
Откатить изменения для конкретного файла до указанного коммита:
git checkout <commit> <file>
Сделать откат всех изменений выполненных в коммите, при этом создается новый коммит указывающий на откат изменений:
git revert <commit>
Отмена изменений до последнего коммита, а также сбрасывает индексацию для конкретного файла:
git reset HEAD <file>
Отмена изменений до последнего коммита и сбрасывает индексацию:
git reset --soft
Отмена изменений до последнего коммита, сбрасывает индексацию, а так же отменить любые изменения в рабочей директории:
git reset --hard
programming Удаляет файлы которые не были добавлены в репозиторий:
git clean -f
Удаляет файлы которые не были добавлены в репозиторий по указанному пути:
git clean -f <path>
Удаляет файлы и каталоги которые не были добавлены в репозиторий:
git clean -df
Только показывает, что будет удаленно:
git clean -n
Работа с удаленными репозиториями

Список соединений с удаленными репозиториями:
git remote
Добавить соединение:
git remote add <name> <url>
Удалить соединение:
git remote rm <name>
Переименовать соединение:
git remote rename <old_name> <new_name>
Получить изменения из репозитория со списком всех веток ( при этом стираются любые локальные изменения ):
git fetch <remote>
Получить изменения из репозитория для конкретной ветки ( при этом стираются любые локальные изменения ):
git fetch <remote> <branch>
Получить копию текущей ветки с удаленного репозитория и слить ее с локальной копией:
git pull <remote>
Залить указанную ветку на удаленный репозиторий:
git push <remote> <branch>


Отдельно про git stash.
Удобно, занимаясь одним делом, «отложить» текущую работу в сторону и отвлечься, скажем, на срочное исправление бага, даже если он находится в другом бранче. После исправления и коммита можно преспокойно вернуться к начатому.
i. hack-hack-hack
ii. git stash
iii. fix-fix-fix
iv. git commit -a -m 'bugfix #31337'
v. git stash pop
Те же, кто знает про git stash, посмотрите на последнюю строку — её отличие от apply в том, что откладываемые результаты не остаются во временном хранилище (посмотрите git stash list после нескольких примений stash!)
Если изменение было фактически законченным, можно оформить коммит не отходят от кассы — git stash save 'commit msg' (взято с http://habrahabr.ru/post/75728/http://habrahabr.ru/post/137408/)
Отдельно про git bisect.
git bisect -  возможность бинарного поиска по коммитам. Для примера приведу следующую ситуацию. В нашем проекте поломался какой-то функционал, в чем конкретно проблема мы понять не можем, но точно знаем, что в прошлом релизе этот функционал точно работал. Так вот команда bisect позволяет нам легко откатить проект на заданное число коммитов и найти тот коммит, в котором неуловимый баг проявляется в первый раз.
Во-первых, запускаем механизм поиска и устанавливаем значение, что текущее состояние проекта нерабочее
git bisect start 
git bisect bad
Далее откатываемся на рабочее состояние проекта — на 10 коммитов назад по истории
git bisect good HEAD~10
Смотрим, проявляется ли этот баг в текущем состоянии. Допустим, сейчас с проектом все хорошо, поэтому продолжаем поиск дальше
git bisect good
Эта команда перематывает состояние проекта в середину, между хорошим коммитом и плохим, т. е. Сейчас мы находимся в пяти коммитах назад по истории. Если баг проявляется, то он находится до текущего коммита, если нет — то после. С каждой такой итерацией расстояние уменьшается в два раза, пока мы не находим плохой коммит (а главное — его автора, к сожалению, это его опять сделали мы).
После завершения поиска сбрасываем репозиторий в исходное состояние
git bisect reset )

пятница, 11 апреля 2014 г.

Используем Apache HttpClient или POST и GET для самых маленьких

Это будет небольшой пост в примерах с минимальным числом комментариев.

Задача: используя httpclient, отправить post - запрос с логином и паролем на некоторый адрес.
Решение: 
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(SESSIONS_URL); //SESSIONS_URL - наш адрес
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair(StaticInformation.LOGIN,
LOGIN));
nameValuePairs.add(new BasicNameValuePair(
StaticInformation.PASSWORD, PASSWORD));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httpPost, localContext);
int code = response.getStatusLine().getStatusCode(); //code - используем для проверки, прошел ли наш запрос
Пояснение: создаем клиент, создаем запрос, с помощью nameValuePairs забиваем необходимые параметры, делаем запрос, получаем код.

Задача: используя httpclient, отправить пост - запрос с логином и паролем на некоторый адрес при этом сохранить куку для дальнейших post(get) - запросов.
Решение: 
HttpClient httpclient = new DefaultHttpClient();
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpPost httpPost = new HttpPost(StaticInformation.SESSIONS_URL);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair(StaticInformation.LOGIN,
LOGIN));
nameValuePairs.add(new BasicNameValuePair(
StaticInformation.PASSWORD, PASSWORD));

httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httpPost, localContext);
//делаем запрос номер два
HttpPost httpPostOffer = new HttpPost(StaticInformation.NEW_URL);
httpPostOffer.setEntity(<Сюда запишем новую сущность>);
response = httpclient.execute(httpPostOffer, localContext);
code = response.getStatusLine().getStatusCode();
Пояснение: по-сути то же самое, но тут мы должны создать cookieStore - хранилище для наших кук. Создаем и сразу же делаем привязку к контексту(localContext), после этого можно совершать запросы, передавая туда созданный localContext.

Задача: совершить запрос multipart/form-data. Отправить на сервер картинку, закодированную в Base64. Этим же запросом отослать остальную информацию.
Решение:
httpPostOffer.setEntity(complectEntityToPost(offer));

private MultipartEntity complectEntityToPost(Offer offer) {
MultipartEntity entity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
// add data for multiform
for (String asset : offer.getAssets()) {
ByteArrayBody body = new ByteArrayBody(Base64.decode(asset,
Base64.DEFAULT), IMAGE_FORMAT,
Converter.currentDateToString()); //добавим данные как на форме
entity.addPart("offer[assets][]", body);
}
// add other data
for (NameValuePair pair : complectPostValuePairs(offer)) {
try {
entity.addPart(pair.getName(), new StringBody(pair.getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
return entity;
}

private List<NameValuePair> complectPostValuePairs(Offer offer) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

nameValuePairs
.add(new BasicNameValuePair("offer[organizationId]", "1"));
nameValuePairs.add(new BasicNameValuePair("offer[cityId]", "16"));
               ...................
}
Пояснение: для  multipart/form-data запросов используется MultipartEntity. С помощью ByteArrayBody можно делать обертки вокруг конструкций типа 
Content-Disposition: form-data; name="offer[assets][]"; filename="icon.png",
передавая необходимые параметры в конструктор. Entity, используемая в предыдущих примерах, лишь часть MultipartEntity, поэтому добавлять параметры можно с помощью метода addPart, где первый параметр - имя параметра, второй параметр - его значение.

Задача: сделать так, чтобы при отправке  multipart/form-data - запроса на сервере корректно отображался русскоязычный текст. 
Решение: 
entity.addPart(pair.getName(), new StringBody(pair.getValue(),
Charset.forName("UTF-8")));
Пояснение: при помощи  StringBody "превращаем" каждую строку (в Java строки Unicode) в UTF - 8. Прежде чем, совершать какие - либо действия с кодировкой, присмотритесь к форме. В моем случае, она выглядит вот так: <form accept-charset='UTF-8' action='/offers' enctype='multipart/form-data' id='offer' method='post'>  

Задача: сделать так, чтобы при отправке обычного post - запроса на сервере корректно отображался русскоязычный текст.
Решение: 
new  UrlEncodedFormEntity(complectPostValuePairs(offer),"UTF-8"));
Пояснение: в качестве параметра для списка из NameValuePair подадим название кодировки.

Задача: сделать гет - запрос.
Пояснение: ничем не отличается от поста, используем HttpGet httpGET. Если нужно куки, юзаем точно тот же способ как и в посте.

Не забываем активно использовать "Проверить элемент" в Google Chrome(нас интересует вкладка "Network"). Просматриваем отданную и переданную информацию.






среда, 9 апреля 2014 г.

Crashlytics как неплохая альтернатива Bugsense

Bugsense - очень и очень неплохой crash reporter для мобильных устройств, существует он довольно давно, и многие мои знакомые пользуются именно им. Не так давно появилась неплохая альтернатива Bugsense, которая еще находится в режиме тестирования, но многие "фишечки" видны уже сейчас. Это crashlytics. Сейчас немного расскажу и покажу как выглядит crashlytics и что это за "фишечки" такие. Во -  первых, crashlytics - это не только вебсайт, но и плагин для eclipse, x-code, android - studio. Плагин этот ставится "Help -> Install new software"(это в eclipse, ничего удивительного, как видите).  Именно в этом и заключается главная фишка - можно видеть баги прямо из вашей среды разработки :) Все очень просто - вы запускаете crashlytics, с помощью кнопки на панели инструментов: 


Затем отмечаете те приложения, за которыми хотите "следить", crashlytics, в свою очередь, добавляет мета - информацию в Manifest - файл вашего Android - проекта:<meta-data android:name="com.crashlytics.ApiKey" android:value="KEY"/> (где KEY - некоторая строка). 
Чтобы все изменения вступили в силу, вам остается только забилдить и запустить ваш проект, а crashlytics подождет:


Всё!!! Теперь вы видите репорты прямо в eclipse! 


Но это еще не все! Как только к вам "пришла" ошибка, вы можете перейти на сайт(который очень крут - фишка номер два :) ), а там просмотреть не только полную информацию о баге, но и:

1) Увидеть красивую статистику (по устройствам, дням, неделям и т.д)
2) Сделать заметку к ошибке
3) Посмотреть состояние всех потоков устройства, на котором был замечен баг
4) Увидеть еще многое и многое :)    


Очень и очень рекомендую.