Source

hgbook-ru / ru / ch06-collab.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
 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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->

<chapter id="cha:collab">
  <?dbhtml filename="collaborating-with-other-people.html"?>
  <title>Взаимодействие с людьми</title>

  <para id="x_44a">Mercurial, как полностью децентрализованный инструмент, не навязывает никакой политики взаимодействия людей друг с другом. Однако, если вы новичок в работе с распределенным контролем версий, будет полезно иметь некоторые инструменты и примеры в голове, обдумывая возможные модели рабочего процесса.</para>

  <sect1>
    <title>Веб-интерфейс Mercurial</title>

    <para id="x_44b">Mercurial имеет мощный веб-интерфейс, обеспечивающий несколько полезных возможностей.</para>

    <para id="x_44c">В плане интерактивного использования интерфейс позволяет просматривать один или несколько репозиториев. Вы можете просматривать историю репозитория, изменения (комментарии и различия), а также содержимое каждого каталога и файла. Можно даже посмотреть на историю в графическом виде, который позволяет проследить зависимости  между отдельными ревизиями и слияниями.</para>

    <para id="x_44d">Также для использования человеком web-интерфейс обеспечивает RSS-канал для изменений в репозитарии. Это позволяет вам <quote>подписаться</quote> на репозитарий, используя вашу любимую программу для чтения новостей, и автоматически получать сообщения об активности в данном репозитарии, как только что-то произойдет.  Я считаю эту возможность гораздо более удобной, чем модель подписки на почтовый список рассылки, с помощью которого будут рассылаться сообщения, поскольку это не требует дополнительной настройки со стороны владельца репозитария.</para>

    <para id="x_44e">Web-интерфейс также позволяет удаленным пользователям клонировать репозиторий, получать с него изменения и в случае, если сервер настроен для внесения изменений, возвращать изменения обратно. Тунельный HTTP протокол Mercurial хорошо сжимает данные и это позволяет работать  даже на низкоскоростных сетевых соединенияx.</para>

    <para id="x_44f">Простейший способ начать использовать Web-интерфейс &emdash; использовать ваш web-браузер для посещения существующего репозитария, например, такого, как основной репозитарий Mercurial, расположенный по адресу <ulink url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para>

    <para id="x_450">Если вы заинтересованы обеспечить Web-интерфейс к своему собственному репозитарию, есть несколько хороших путей.</para>

    <para id="x_69d">Самый простой и быстрый способ, чтобы начать работу в неформальной обстановке является использование команды <command role="hg-cmd">hg serve</command>, которая лучше всего подходит для кратковременных <quote>лёгких</quote> серверов. Смотрите <xref linkend="sec:collab:serve"/> чтобы узнать, как использовать эту команду.</para>

    <para id="x_69e">Для долгоживущих репозитариев, которые вы хотели бы иметь постоянно доступным, есть несколько общественных хостинг сервисов. Некоторые из них бесплатны для проектов с открытым кодом, а другие платные коммерческие хостинги. Актуальный список доступен в <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</ulink>.</para>

    <para id="x_6a0">Если вы предпочитаете использовать ваш собственный компьютер для репозитариев, Mercurial имеет встроенную поддержку нескольких популярных хостинг технологий, в первую очередь cgi (common gateway interface), а также wsgi (web services gateway interface). Смотрите <xref linkend="sec:collab:cgi"/> для более подробной информации о конфигурации CGI и WCGI.</para>
  </sect1>

  <sect1>
    <title>Модели сотрудничества</title>

    <para id="x_451">Если есть достаточно гибкий инструмент, принятие решений по поводу рабочего процесса становится задачей скорее социальной инженерии, чем технической. Mercurial накладывает немного ограничений на то, как Вы можете структурировать работу над проектом, таким образом, Вам и Вашей группе возможно создать модель, удовлетворяющую Вашим особым нуждам, и жить по этой модели.</para>

    <sect2>
      <title>Факторы, которые необходимо иметь в виду</title>

      <para id="x_452">Наиболее важным аспектом любой модели, который Вы должны иметь в виду, является то, как эта модель соответствует потребностям и возможностям людей, которые будут ее использовать. Это может показаться самоочевидным, но даже если это так, вы все равно не можете себе позволить забыть об этом хотябы на время.</para>

      <para id="x_453">Я как-то создал модель рабочего процесса, которая казалась, была идеальной для меня, но которая вызвала значительные потрясения и беспорядки в моей команде разработчиков. Несмотря на мои попытки объяснить, почему нам необходим набор  различных ветвей репозитария, и каким образом изменения должны проходить между ними, несколько членов команды восстали. Несмотря на то, что они были умные люди, они не хотели обращать внимание на ограничения,  в соответствии с которыми мы действовали, или столкнуться с последствиями таких ограничений в деталях той модели, которую я защищал.</para>

      <para id="x_454">Не заметайте поддающиеся предвидению социальные или технические проблемы под ковер. Какую бы схему Вы ни внедряли, вы должны планировать ошибки и проблемные сценарии. Рассмотрите добавление автоматизированных механизмов для предотвращения или быстрого восстановления после проблем, которые Вы можете предвидеть. Например, если Вы хотите иметь ветвь, в которой хранятся изменения не-для-релиза, Вы должны заранее хорошо подумать над тем, что кто-то может случайно добавить эти изменения в релиз. Вы могли бы избежать этой конкретной проблемы, написав перехватчик, который будет  мешать изменениям, вносимым в неподходящую ветвь кода.</para>
    </sect2>

    <sect2>
      <title>Неформальный подход</title>

      <para id="x_455">Я не стал бы рекомендовать этот подход, как универсальный, однако он крайне прост и отлично работает в некоторых нестандартных ситуациях.</para>

      <para id="x_456">К примеру, множество проектов представляет собой группу слабо взаимодействующих между собой участников, которые крайне редко встречаются лично. Некоторые группы стараются преодолеть возникающую в результате удаленной работы изоляцию, устраивая <quote>спринты</quote>. Во время <quote>спринта</quote>, участники собираются вместе в назначенном месте &emdash; конференц-зале компании или отеля &emdash; и проводят несколько дней в неотрывной разработке, разбираясь со сложными местами проектов.</para>

      <para id="x_457"><quote>Спринт</quote> или хакерский сбор в кафе &emdash; отличное место для применения команды <command role="hg-cmd">hg serve</command>, поскольку эта команда не требует никакой сложной серверной инфраструктуры. Вы можете приступить к использованию <command role="hg-cmd">hg serve</command> моментально, прочитав <xref linkend="sec:collab:serve"/>. Вы можете просто сообщить соседу, что Вы запустили сервер, передать ему ссылку любым удобным способом, и у вас уже есть отличное средство для совместной работы. Ваш сосед может открыть полученный URL своим браузером и ознакомиться с внесенными Вами изменениями, он может воспользоваться сделанными Вами исправлениями, а может клонировать ветвь, содержащую новые возможности, и опробовать ее.</para>

      <para id="x_458">Одновременно положительной и отрицательной стороной такого варианта взаимодействия является то, что только те люди, которые знают о внесенных вами изменениях, могут их увидеть. Неформальный подход просто невозможно использовать в больших коллективах, поскольку каждый участник должен отслеживать изменения в <emphasis>n</emphasis> репозиториях, чтобы получить их.</para>
    </sect2>

    <sect2>
      <title>Единый центральный репозиторий</title>

      <para id="x_459">Для маленьких проектов, мигрирующих с централизованных систем контроля версий, возможно самым легким путем будет использование одного центрального репозитория. Это наиболее частый <quote>кирпич</quote> для создания более сложных структур.</para>

      <para id="x_45a">Каждый участник разработки начинает работу с создания локальной копии центрального репозитория. Он может получать изменения из него тогда, когда ему понадобится. В то же время некоторые (а возможно и все) разработчики имеют привилегии на добавление в репозиторий готовых к публикации изменений.</para>

      <para id="x_45b">В рамках этого подхода также остается возможным обмен изменениями напрямую между разработчиками, без добавления их в центральный репозиторий. К примеру, я исправил ошибку, однако я не могу гарантировать, что будучи опубликованным в центральном репозитории, мое исправление не нарушит работу кода других разработчиков, которые получат это исправление. Чтобы снизить риск возможного вреда, я могу попросить вас клонировать мой репозиторий в ваш собственный временный репозиторий, и проверить работоспособность. Это позволит нам избежать публикации потенциально небезопасных изменений до тех пор, пока они не пройдут небольшого тестирования.</para>

      <para id="x_45c">Если команда хостит собственные репозитории по такому типу работы, разработчики обычно используют протокол <command>ssh</command> для безопасного добавления изменений в центральный репозиторий, как это описано в разделе <xref linkend="sec:collab:ssh"/>. Также, часто используется возможность публикации доступной только для чтения копии репозитория с помощью HTTP-сервера, используя CGI, как показано в <xref linkend="sec:collab:cgi"/>. Публикация с помощью HTTP удовлетворяет потребностям людей, которые не имеют доступа на запись, и которые хотят использовать web-браузеры для просмотра истории репозитория.</para>
    </sect2>

    <sect2>
      <title>Хостинг центрального репозитория</title>

      <para id="x_6a1">Преимуществом общественных услуг хостинга, таких как <ulink url="http://bitbucket.org/">Bitbucket</ulink> является то, что они не только поддерживают неудобные детали конфигурации, такие как учетные записи пользователей, проверки подлинности и защищенные протоколы передачи, они обеспечивают дополнительную инфраструктуру, чтобы эта модель хорошо работала.</para>

      <para id="x_6a2">Например, хорошо организованный хостинг позволяет людям клонировать собственные копии репозитория за один клик. Это позволяет людям работать в разных местах и делиться своим изменениями, когда они готовы.</para>

      <para id="x_6a3">Кроме того, хороший сервис хостинга позволяет людям общаться друг с другом, например, говорить <quote>Есть изменения готовые для просмотра в этом дереве</quote>.</para>
    </sect2>

    <sect2>
      <title>Работа с несколькими ветвями</title>

      <para id="x_45d">Работа над проектами более-менее значительного размера, как правило, идет сразу на нескольких фронтах. В течение жизненного цикла, проект переживает периодические официальные релизы. После этого релиз может на некоторое время после выпуска перейти в <quote>режим поддержки</quote> &emdash; когда в программное обеспечение вносятся только исправления ошибок, не добавляя новых возможностей. Параллельно с этими релизами, один или несколько будущих релизов находятся в разработке. Для обозначения подобных направлений в разработке, используется термин <quote>ветвь</quote>.</para>

      <para id="x_45e">Mercurial исключительно хорошо подходит для ведения нескольких похожих, но не одинаковых ветвей. Каждое <quote>направление разработки</quote> может храниться в своем собственном центральном репозитории, и вы можете добавлять изменения из одного в другой, когда появляется такая необходимость. Поскольку репозитории являются независимыми, нестабильные изменения в разрабатываемой ветви не повлияют на стабильную ветвь, покуда кто-нибудь не захочет объединить их.</para>

      <para id="x_45f">Вот как это работает на практике: Допустим, у вас есть одна <quote>главная ветвь</quote> на центральном сервере.</para>

      &interaction.branching.init;

      <para id="x_460">Остальные участники клонируют его, делают изменения, проверяют их, и добавляют в репозиторий.</para>

      <para id="x_461">Когда главная ветвь достигает состояния релиза, вы можете использовать команду <command role="hg-cmd">hg tag</command>, чтобы дать постоянное имя этой ревизии.</para>

	&interaction.branching.tag;

      <para id="x_462">Теперь, скажем, произошли изменения в главной ветви.</para>

      &interaction.branching.main;

      <para id="x_463">Используя тег для пометки релиза, участник, клонирующий репозиторий, в любое время в последующем может воспользоваться командой <command role="hg-cmd">hg update</command> для получения точной копии рабочей папки по состоянию на момент релиза.</para>

      &interaction.branching.update;

      <para id="x_464">В дополнение к этому, сразу же после того, как основная ветка будет тегирована, кто-либо может клонировать основную ветку на сервере в новую <quote>стабильную</quote> ветку, также находящуюся на сервере.</para>

      &interaction.branching.clone;

      <para id="x_465">Любой, кому нужно сделать изменения в стабильной ветке, может клонировать <emphasis>этот</emphasis> репозиторий, вполнить изменения, сделать коммит и передать изменения сюда.</para>

      &interaction.branching.stable;

      <para id="x_466">Поскольку репозитории Mercurial независимы, и поскольку Mercurial не осуществляет автоматически изменения, стабильная и основная ветки <emphasis>изолированы</emphasis> друг от друга. Изменения, сделанные вами в основной ветке не <quote>просачиваются</quote> в стабильную ветку, и обратно.</para>

      <para id="x_467">Часто у вас будет возникать желание, что бы багфиксы из стабильной ветки применялись и к основной. Вместо простого переписывания исправления в основную ветку, вы можете просто выполнить pull и merge измениний стабильной ветки в основную. И Mercurial перенесет вам эти багфиксы.</para>

      &interaction.branching.merge;

      <para id="x_468">Основная ветка все так же содержит изменения, которых нет в стабильной ветке, но она еще и содержит все исправления из стабильной ветки. А стабильная ветка продолжает оставаться незатронутой этими изменениями, так как изменения перемещаются только из стабильной ветви в остальные, а не иначе.</para>
    </sect2>

    <sect2>
      <title>Ветви для новых функций</title>

      <para id="x_469">Для больших проектов эффективным способом управлять изменениями будет разбиение команды на несколько меньших групп. Каждая из которых будет использовать свою собственную ветку клонированную из единой <quote>главной</quote> ветки, используемой для всего  проекта. Люди работающие над отдельными ветками обычно хорошо изолированны от изменений в других ветках.</para>

      <figure id="fig:collab:feature-branches">
	<title>Ветви для новых функций</title>
	<mediaobject>
	  <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject>
	  <textobject><phrase>XXX add text</phrase></textobject>
	</mediaobject>
      </figure>

      <para id="x_46b">Когда отдельная функция приобретает удобоваримую форму, кто-то из команды, работавшей над данной функцией затягивает изменения из главной ветки в ветку функции и выполняет слияние, а затем заливает изменения назад в  главную ветку.</para>
    </sect2>

    <sect2>
      <title>Релиз по расписанию</title>

      <para id="x_46c">Некоторые проекты организованы по принципу <quote>поезда</quote>: выпуск новой версии планируется каждые несколько месяцев, и все функции, которые завершены к <quote>отправлению поезда</quote>, включаются в релиз.</para>

      <para id="x_46d">Эта модель имеет много общего с моделью <quote>ветви для новых функций</quote>. Отличие следующее: в случае, если функция не вошла в релиз (опоздала на поезд),  один из членов команды-разработчика функции вытягивает вошедшие в релиз изменения в ветку функции и производит слияние, после чего команда продолжает работать <quote>поверх</quote> нового релиза и, таким образом, сможет включить функцию в новый релиз.</para>
    </sect2>

    <sect2>
      <title>Модель ядра Linux</title>

      <para id="x_46e">В разработке ядра Linux есть неглубокая иерархическая структура, окруженная очевидным облаком хаоса. Поскольку большинство разработчиков Linux используют <command>git</command>, распределенный инструмент управления версиями, подобный Mercurial, полезно описать рабочий процесс в этом окружении. Если вам понравятся идеи, подход легко переносится на другие инструменты.</para>

      <para id="x_46f">В центре сообщества сидит Линус Торвальдс (Linus Torvalds), создатель Linux. Он публикует единственный исходный архив, который считается <quote>авторитетным</quote> текущим деревом всего сообщества разработчиков. Любой может клонировать дерево Линуса, но он очень разборчив в выборе деревьев с которых можно вливать изменения.</para>

      <para id="x_470">У Линуса есть несколько <quote>доверенных лейтенантов</quote>. Как правило он помещает любые изменения, которые они издают, в большинстве случае даже не рассматривая их изменения. Некоторые из лейтенантов вообще являются <quote>мейнтейнерами</quote>, отвечающими за отдельные подсистемы в пределах ядра. Если случайный разработчик ядра хочет сделать изменения в подсистему, которые они хотят внести в дерево Линуса, они должны узнать кто является мейнтейнером подсистемы и попросить его внести изменения. Если мейнтейнер рассмотрит их изменения и согласиться их взять, то он передаст их Линусу должны образом.</para>

      <para id="x_471">У индивидуальных лейтенантов имеются свои собственные подходы к рассмотрению, принятию и публикации изменений, и для того чтобы решить когда передать их Линусу. В дополнение, существует несколько хорошо известных веток которые люди используют для различных целей. Например, некоторые люди обслуживают <quote>stable</quote>  (<quote>стабильную ветку</quote>) репозитория с несколько устаревшей версией ядра, внося критические исправления если они необходимы. Некоторые мейнтейнеры публикуют несколько деревьев: одно для экспериментальных изменений, одно для изменений которые они собираются внести в стабильные и так далее. Другие просто публикуют отдельные деревья.</para>

      <para id="x_472">У этой модели есть две важные особенности. Первая это <quote>только внесение</quote>. Вы должны спросить, убедить или попросить другого разработчика сделать изменения за вас, потому что практически нет веток, куда может помещать код одна персона, и не существует способа помещать код в ветки, контролируемые кем-то еще.</para>

      <para id="x_473">Вторая базируется на репутации и доверии. Если вы никому не известны, Линус вероятно проигнорирует ваши изменения и даже оставит вас без ответа. Но майнтейнер подсистемы вероятно рассмотрит их, если они пройдут его критерии пригодности. Чем более <quote>хорошие</quote> изменения вы вносите, тем более вероятно что они будут доверять вашему суждению и принимать ваши изменения. Если вы  хорошо известны и поддерживаете долгое время какую-либо возможность в ветке, которые Линус еще не принял, люди с похожими интересами могут вносить ваши изменения регулярно, для того чтобы не отставать от вашей работы.</para>

      <para id="x_474">Репутация и признание не  распространяется на другие подсистемы или людей. Если вы будете уважаемым, но специализированным разработчиком по файловым хранилищам, и попытаетесь исправить баг в сетевой подсистеме, это скорее всего, будет рассматриваться майнтейнером этой подсистемы как исправление от незнакомца.</para>

      <para id="x_475">Людям, пришедшим с более строгих проектов, и сравнивающих процесс разработки ядра Linux с места откуда они пришли, процесс разработки кажется полностью безумным. Разработка подчиняется прихотям людей; люди делают большие изменения всякий раз, как считают это нужным; и темп эволюционирования потрясает. Но все же Linux &emdash; это успешная и хорошо оцениваемая часть программного обеспечения.</para>
    </sect2>

    <sect2>
      <title>Втягивающее против совместно-вносимого сотрудничества</title>

      <para id="x_476">Постоянным источником жара в open source сообществе является вопрос, которая из двух моделей разработки лучше: та, в которой люди всегда берут изменения у других, или та, в которой множество людей вносят изменения в общий репозиторий.</para>

      <para id="x_477">Обычно, покровители модели совместного вноса используют инструменты принуждающие использовать этот метод. Если вы используете инструмент централизованного контроля версий вроде Subversion, нет возможности выбрать модель: инструмент даёт вам только совместный внос, и если вы захотите что-то ещё, вам придётся прикрутить свой собственный метод сверху (как например наложение патча вручную).</para>

      <para id="x_478">Хорошая распределенная версионная система, такая как Mercurial, поддерживает обе модели. И вы и ваши коллеги можете организовывать совместную работу, основываясь на ваших нуждах и предпочтениях, а не так, как принуждают вас ваши инструменты.</para>
    </sect2>
    <sect2>
      <title>Когда разработка сталкивается с управлением ветвлениями</title>

      <para id="x_479">Единожды создав несколько распределенных репозиториев и начав распространять изменения между локальным и общим репозиториями, вы с вашей командой начнете становиться связанными, но столкнетесь с немного другой проблемой: управлением направлениями, в которых ваша команда может разом двинуться. Хотя эта тема тесно связана с тем, как ваша команда взаимодействует, она довольно глубока, чтобы заслужить собственное рассмотрение в <xref linkend="chap:branch"/>.</para>
    </sect2>
  </sect1>

  <sect1>
    <title>Техническая сторона совместного использования</title>

    <para id="x_47a">Остаток от этой главы посвящен вопросу обмена данными с вашими сотрудниками.</para>
  </sect1>

  <sect1 id="sec:collab:serve">
    <title>Неофициальный обмен с помощью <command role="hg-cmd">hg serve</command></title>

    <para id="x_47b">Команда <command role="hg-cmd">hg serve</command> чудесно подходит для маленьких, тесно связанных и быстро продвигающихся групп (разработчиков). Она также предоставляет отличную возможность пощупать использование команд Mercurial через сеть.</para>

    <para id="x_47c">Запустите <command role="hg-cmd">hg serve</command> внутри репозитория, и через секунду она (команда) поднимет специальный HTTP сервер, принимающий подключения от любого клиента и предоставляющий данные этого репозитория, пока вы не отключите его. Любой, кто знает URL только что запущенного сервера, и способный подключиться к вашему компьютеру через сеть, может использовать браузер или Mercurial для чтения дынных этого репозитория. URL запущенного экземпляра <command role="hg-cmd">hg serve</command> на ноутбуке вероятно будет выглядеть приблизительно как <literal>http://my-laptop.local:8000/</literal>.</para>

    <para id="x_47d">Команда <command role="hg-cmd">hg serve</command> это <emphasis>не</emphasis> полноценный web сервер. Вы можете делать с ним только две вещи:</para>
    <itemizedlist>
      <listitem><para id="x_47e">Разрешать людям просматривать репозиторий через обычный web браузер</para>
      </listitem>
      <listitem><para id="x_47f">Использовать родной протокол Mercurial, так что люди смогут сделать <command role="hg-cmd">hg clone</command> или <command role="hg-cmd">hg pull</command> с вашего репозитория.</para>
      </listitem></itemizedlist>
    <para id="x_480">На практике команда <command role="hg-cmd">hg serve</command> не позволяет удаленным пользователям <emphasis>модифицировать</emphasis> ваш репозиторий. Она предназначена для использования в рамках <quote>только чтение</quote>.</para>

    <para id="x_481">Если вы начинаете знакомство с Mercurial, нет ничего чтобы препядствовало вам сделать <command role="hg-cmd">hg serve</command> чтобы дать общий доступ к вашему локальному репозиторию и  использовать команды вроде <command role="hg-cmd">hg clone</command>, <command role="hg-cmd">hg incoming</command> и так далее, так, будто репозиторий находится удаленно. Это может помочь вам быстро ознакомиться с использованием команд для репозиториев, расположеных в сети.</para>

    <sect2>
      <title>Несколько деталей к размышлению</title>

      <para id="x_482">Поскольку <command role="hg-cmd">hg serve</command> предоставляет доступ на чтение всем клиентам без идентификации, эту команду следует использовать только в окружении, где вы либо не имеете причин для беспокойства, либо имеете возможность определять, кто может подключиться к вашему хранилищу и получить из него данные.</para>

      <para id="x_483">Команда <command role="hg-cmd">hg serve</command> ничего не знает о брандмауэрах, которые могут быть установлены в вашей системе или сети. Она не обнаруживает и не управляет вашими брандмауэрами. Если сторонний человек не может обратиться к запущенному экземпляру <command role="hg-cmd">hg serve</command>, второе, что нужно проверить (<emphasis>после</emphasis> того, как убедитесь, что он использует правильный URL) — это конфигурация брандмауэра.</para>

      <para id="x_484">По умолчанию, <command role="hg-cmd">hg serve</command> принимает входящие соединения на 8000 порт. Если другой процесс уже прослушивает порт, который вы хотите использовать, вы можете указать другой порт с помощью ключа <option role="hg-opt-serve">-p</option>.</para>

      <para id="x_485">Обычно, когда <command role="hg-cmd">hg serve</command> запущен, он ничего не выводит, что может быть немного странным. Если вы хотите убедиться, что он действительно работает и вы можете передать URL своим сотрудникам, запускайте его с ключом <option role="hg-opt-global">-v</option>.</para>
    </sect2>
  </sect1>

  <sect1 id="sec:collab:ssh">
    <title>Использование протокола Secure Shell (ssh)</title>

    <para id="x_486">Используя протокол Secure Shell (<literal>ssh</literal>), Вы можете безопасно получать и записывать изменения через сетевое соединение. Для того, что бы воспользоваться этим, Вы должны немного изменить конфигурацию на стороне клиента или сервера.</para>

    <para id="x_487">Если Вы не знакомы с ssh, то это протокол, который позволяет Вам безопасно осуществлять соединение с другим компьютером. Чтобы использовать его с Mercurial, Вам нужно настроить одну или несколько пользовательских учетных записей на сервере так, чтобы удаленные пользователи могли входить в систему и исполнять команды.</para>

    <para id="x_488">(Если Вы знакомы с ssh, приведенный ниже материал наверняка покажется Вам элементарным.)</para>

    <sect2>
      <title>Как читать и записывать, используя ssh URL-ы</title>

      <para id="x_489">Обычно, ssh URL выглядит подобным образом:</para>
      <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting>
      <orderedlist>
	<listitem><para id="x_48a">Часть <quote><literal>ssh://</literal></quote> указывает Mercurial, что нужно использовать ssh протокол.</para>
	</listitem>
	<listitem><para id="x_48b">Часть bos представляет собой имя пользователя для подключения к серверу. Вы можете не указывать эту часть, если имя пользователя на удалённом сервере совпадает с Вашим локальным именем пользователя.</para>
	</listitem>
	<listitem><para id="x_48c"><quote><literal>hg.serpentine.com</literal></quote> представляет собой имя хоста для подключения.</para>
	</listitem>
	<listitem><para id="x_48d"><quote><literal>:22</literal></quote> указывает номер порта для подключения к серверу. По умолчанию используется порт 22, поэтому Вам нужно  указывать эту часть только если используется <emphasis>не</emphasis> стандартный 22 порт.</para>
	</listitem>
	<listitem><para id="x_48e">Остальная часть URL представляет собой локальный путь к хранилищу на серевере.</para>
	</listitem></orderedlist>

      <para id="x_48f">Существует множество неразберихи по прочтению ssh-URL, так как не существует стандарта его интерпретации. Некоторые программы ведут себя одним образом, другие &emdash; иначе, когда речь идет о таких путях. Это не идеальная ситуация, и она вряд ли изменится. Пожалуйста, прочтите внимательно следующие абзацы.</para>

      <para id="x_490">Mercurial рассматривает путь к хранилищу на сервере относительно домашней директории удаленного пользователя. Например, если домашняя директория пользователя <literal>foo</literal> на сервере <filename class="directory">/home/foo</filename>, тогда ssh-URL, который содержит компонент пути <filename class="directory">bar</filename> (<literal>ssh://foo@myserver/bar</literal>), в <emphasis>действительности</emphasis> ссылается на директорию <filename class="directory">/home/foo/bar</filename>.</para>

      <para id="x_491">Если Вы хотите указать путь относительно домашней директории другого пользователя, можете использовать путь, который начинается с тильды, за которой следует имя пользователя(назовем его <literal>otheruser</literal>), к примеру.</para>
      <programlisting>ssh://server/~otheruser/hg/repo</programlisting>

      <para id="x_492">Если Вы действительно хотите указать <emphasis>абсолютный</emphasis> путь на сервере, укажите в начале два слэша, как в примере.</para>
      <programlisting>ssh://server//absolute/path</programlisting>
    </sect2>

    <sect2>
      <title>Выбор ssh-клиента для Вашей системы</title>

      <para id="x_493">Почти все Unix-подобные системы поставляются с предустановленным OpenSSH. Если Вы используете такую систему, запустите <literal>which ssh</literal>, что бы узнать, установлен ли <command>ssh</command> (он, как правило, находится в <filename class="directory">/usr/bin</filename>). В маловероятном случае, если его нету, обратитесь к документации на вашу систему, чтобы выяснить как его установить.</para>

      <para id="x_494">В windows, пакета tortoisehg поставляется в комплекте с версией отличной команде <command>plink</command> Симона Татама, и вам не нужно делать какой-либо дополнительной конфигурации.</para>
    </sect2>

    <sect2>
      <title>Генерация криптографической пары (открытого и секретного ключей)</title>

      <para id="x_499">Чтобы не вводить пароли каждый раз при использовании ssh-клиента, рекомендую сгенерировать криптографическую пару.</para>

      <tip>
	<title>Криптографической ключи не являются обязательными</title>

	<para id="x_6a4">Mercurial ничего не знает об аутентификации или SSH-ключах. Вы можете, если хотите, проигнорировать этот раздел и следующий, пока не устанете от многократно ввода пароля SSH.</para>
      </tip>

      <itemizedlist>
	<listitem>
	  <para id="x_6a5">На Unix-подобной операционной системы, можно сделать командой <command>ssh-keygen</command>.</para>
	  <para id="x_6a6">В windows, если вы используете TortoiseHg, вам, возможно, потребуется скачать команду с <command>puttygen</command> с <ulink url="http://www.chiark.greenend.org.uk/~sgtatham/putty">веб-сайта PuTTY</ulink> для генерации пары ключей. Смотрите <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">документацию</ulink> к <command>puttygen</command> об использовании этой команды.</para>
	</listitem>
      </itemizedlist>

      <para id="x_49a">При генерации  криптографической пары <emphasis>весьма</emphasis> целесообразно защитить секретный ключ с помощью парольной фразы (единственный случай, когда Вам не захочется этого делать &emdash; это когда вы используете ssh протокол для автоматизации задач в защищённой сети)</para>

      <para id="x_49b">Одной только генерации пары ключей не достаточно. Вам также необходимо добавить открытый ключ к множеству авторизованных ключей пользователя, который подключается удаленно. Для серверов, которые используют OpenSSH (подавляющее большинство), это означает, что нужно добавить публичный ключ к списку в файле под названием <filename role="special">authorized_keys</filename> в директории <filename role="special" class="directory">.ssh</filename> пользователя.</para>

      <para id="x_49c">На Unix-подобных системах, Ваш открытый ключ будет иметь расширение <filename>.pub</filename>. Если Вы используете <command>puttygen</command> на Windows, то Вы можете сохранить открытый ключ в файл или вставить из окна puttygen в файл <filename role="special">authorized_keys</filename>.</para>
    </sect2>
    <sect2>
      <title>Использование агента аутентификации</title>

      <para id="x_49d">Аутентификационный агент &emdash; демон, который хранит парольную фразу в памяти (и она будет утеряна, когда Вы выйдете из системы). Ключевая фраза передаётся ssh-клиенту, если он запущен и опрашивает агента для получения парольной фразы. Если агент аутентификации не запущен, или не хранит необходимой парольной фразы, то пароль будет запрашиваться вский раз, когда Mercurial попробует установить соединение с сервером от Вашего имени (при отправке или получении Вами изменений).</para>

      <para id="x_49e">Недостатком хранения парольных фраз в агенте является возможность их восстановления хорошо подготовленными злоумышленниками. Вам решать, насколько это приемлемый для Вас риск. С другой стороны, это избавляет от многократного повторного ввода.</para>

      <itemizedlist>
	<listitem>
	  <para id="x_49f">На Unix-подобных системах агент называется <command>ssh-agent</command>, который запускается автоматически когда вы входите в систему. Для того, что бы агент запомнил парольную фразу в хранилище, нужно использовать команду <command>ssh-add</command>.</para>
	</listitem>
	<listitem>
	  <para id="x_6a7">На Windows, если вы используете TortoiseHg, команда <command>pageant</command> выступает в качестве агента. Как и <command>puttygen</command>, вам необходимо <ulink url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">скачать <command>pageant</command></ulink> с веб-сайта PuTTY  и прочесть <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">его документацию</ulink>. Команда <command>pageant</command>  добавляет иконку в системный трей, с помощью которой, вы можете управлять сохраненными парольными фразами.</para>
	</listitem>
      </itemizedlist>
    </sect2>

    <sect2>
      <title>Правильная настройка сервера.</title>

      <para id="x_4a0">Настройка ssh кропотливая, и если Вы новичек, то есть ряд вещей, которые могут пойти не так. Добавим сверху ещё и Mercurial, и появится ещё больше причин почесать затылок. Большинство потенциальных проблем возникают не на стороне клиента, а на  стороне сервера. Хорошая новость заключается в том, что как только Вы получили рабочую конфигурацию, то, как правило, она будет работать неограниченное время.</para>

      <para id="x_4a1">Перед тем, как пытаться использовать Mercurial с доступом через ssh сервер, лучше для начала убедиться в том, что вы можете нормально использовать <command>ssh</command> или команду <command>putty</command> для доступа к серверу. Если вы столкнетесь с проблемами непосредственно при использовании этих команд, то наверняка Mercurial также не будет работать. Более того, он будет скрывать проблему. Когда Вы захотите настроить работу Mercurial по ssh, то сначала убедитесь, что подключения клиента по ssh работают, и только <emphasis>потом</emphasis> беспокойтесь о том, что это проблема Mercurial.</para>

      <para id="x_4a2">Первое, что нужно сделать, что бы убедиться в работоспособности серверной стороны &emdash; попробовать войти в систему с другой машины. Если вы не можете войти с помощью <command>ssh</command> или <command>putty</command>, полученное Вами сообщение об ошибке может дать несколько подсказок, что именно идет не так. Наиболее распространенными проблемами являются следующие:</para>
      <itemizedlist>
	<listitem><para id="x_4a3">Если получаете сообщение <quote>connection refused</quote> &emdash; либо не запущен демон SSH на стороне сервера, либо он не доступен из-за конфигурации межсетевого экрана.</para>
	</listitem>
	<listitem><para id="x_4a4">Если Вы получаете сообщение об ошибке <quote>no route to host</quote> &emdash; Вы ввели неправильный адрес сервера или серьёзно заблокированы межсетевым экраном, который вообще не признаёт существование этого сервера.</para>
	</listitem>
	<listitem><para id="x_4a5">Если Вы получаете ошибку <quote>permission denied</quote> &emdash; Вы ошиблись при вводе логина на сервере, опечатались в ключевой фразе или пароле пользователя.</para>
	</listitem></itemizedlist>
      <para id="x_4a6">В итоге, если у Вас возникают проблемы подключения к даемону ssh сервера, первое в чем нужно убедиться &emdash; запущен ли он вообще. На многих системах он установлен, но по-умолчанию отключен. После того, как закончили этот шаг, Вы должны убедиться в том, что брандмауэр на стороне сервера разрешает входящие соединения к порту, на котором  слушает ssh даемон (обычно 22). Не беспокойтесь о других возможных ошибках, пока не проверите эти две.</para>

      <para id="x_4a7">Если Вы используете агента аутентификации на клиентской стороне для хранения Ваших парольных фраз ключей, Вы можете подключаться к серверу без ввода парольной фразы или пароля.  Если Вас спрашивают парольную фразу, есть несколько возможных причин:</para>
      <itemizedlist>
	<listitem><para id="x_4a8">Возможно, Вы забыли использовать <command>ssh-add</command> или <command>pageant</command> для сохранения парольной фразы.</para>
	</listitem>
	<listitem><para id="x_4a9">Возможно, Вы ввели парольную фразу не для того ключа.</para>
	</listitem></itemizedlist>
      <para id="x_4aa">Если вас спрашивают пароль для аккаунта на сервере, есть несколько возможных причин:</para>
      <itemizedlist>
	<listitem><para id="x_4ab">Права доступа к пользовательской домашней директории или поддиректории <filename role="special" class="directory">.ssh</filename> имеет лишние разрешения. В результате этого ssh даемон не доверяет такому <filename role="special">authorized_keys</filename> файлу. Например, право на запись для группы в домашнюю или <filename role="special" class="directory">.ssh</filename>  директорию часто является причиной такого поведения.</para>
	</listitem>
	<listitem><para id="x_4ac">Файл <filename role="special">authorized_keys</filename> пользователя тоже может быть причиной проблем. Если кроме пользователя ещё кто-либо может в него писать, то ssh даемон не станет доверять такому файлу и не будет его использовать.</para>
	</listitem></itemizedlist>

      <para id="x_4ad">В идеальном случае, Вы должны успешно выполнить следующую команду и получить её вывод: текущую дату и время на сервере.</para>
      <programlisting>ssh myserver date</programlisting>

      <para id="x_4ae">Если на Вашем сервере при входе выполняются скрипты, выводящие баннеры и прочий мусор, даже при запуске неинтерактивных сессий, вроде приведённой выше &emdash; Вы должны избавиться от них или настроить сервер, чтобы это безобразие появлялось только при интерактивном входе. Иначе этот мусор будет, по-крайней мере, загромождать вывод Mercurial. Также он создаёт потенциальные проблемы для удалённого выполнения команд Mercurial. Mercurial пытается определять и игнорировать баннеры в неинтерактивных <command>ssh</command> сессиях, но не всегда успешно. (Если Вы изменяли логин-скрипты на сервере, то чтобы убедититься в их работоспособности в интерактивной сессии &emdash; проверьте код, возвращаемый командой <literal>tty -s</literal>.)</para>

      <para id="x_4af">Как только Вы проверите простой ssh-доступ на сервер, следующим шагом к победе будет проверка выполнения Mercurial на сервере. Следующая команда должна успешно исполниться:</para>

      <programlisting>ssh myserver hg version</programlisting>

      <para id="x_4b0">Если вы получили ошибку вместо нормального вывода команды <command role="hg-cmd">hg version</command>, то это, как правило, из-за неустановленного Mercurial в <filename class="directory">/usr/bin</filename>. Не беспокойтесь, если это так, то вам не нужно этого делать. Но Вы должны проверить несколько возможных проблем.</para>
      <itemizedlist>
	<listitem><para id="x_4b1">Mercurial вообще действительно установлен на сервере? Я знаю, что звучит банально, но это стоит проверить!</para>
	</listitem>
	<listitem><para id="x_4b2">Возможно в вашей командной оболочке неверно указаны пути поиска исполняемых файлов (как правило определяются переменной окружения <envar>PATH</envar>).</para>
	</listitem>
	<listitem><para id="x_4b3">Может быть переменная окружения <envar>PATH</envar> у вас правильно устанавливается только при интерактивном входе в систему. Это может случиться, если вы установили путь в неверном скрипте входа. Смотрите документацию по своей командной оболочке для подробностей.</para>
	</listitem>
	<listitem><para id="x_4b4">Переменная среды <envar>PYTHONPATH</envar> может потребоваться для определения пути к модулям Mercurial. Может быть она вообще не установлена; содержит неверное значение; или устанавливается только при интерактивной сессии оболочки.</para>
	</listitem></itemizedlist>

      <para id="x_4b5">Если Вы успешно выполнили <command role="hg-cmd">hg version</command> по ssh соединению, то всё готово. Ваш сервер и клиент настроены. Вы можете начинать использовать Mercurial для доступа к хранилищам этого пользователя на этом сервере. При возникновении проблем на этом этапе, попробуйте использовать опцию <option role="hg-opt-global">--debug</option> для более полного представления о происходящем.</para>
    </sect2>
    <sect2>
      <title>Использование сжатия по ssh</title>

      <para id="x_4b6">Mercurial не сжимает данные, передаваемые по ssh, поскольку ssh протокол сам может прозрачно это делать. Однако, по-умолчанию, ssh-клиенты <emphasis>не</emphasis> используют компрессию передаваемых данных.</para>

      <para id="x_4b7">При работе по сети, отличной от  высокоскоростной LAN, (даже по беспроводной сети), использование сжатия значительно ускоряет выполнение сетевых операций Mercurial'а. Например, кто-то измерил, что сжатие уменьшило время на клонирование через WAN достаточно большого хранилища с 51 минуты до 17 минут.</para>

      <para id="x_4b8">Оба клиента, и <command>ssh</command>, и <command>plink</command>, понимают опцию <option role="cmd-opt-ssh">-C</option>, которая включает сжатие передаваемых данных. Вы легко можете разрешить компрессию по ssh для Mercurial, отредактировав ваш файл <filename role="special">~/.hgrc</filename>. Вот как сделать это в обычном <command>ssh</command> на unix-подобных операционных системах, для примера.</para>
      <programlisting>[ui]
ssh = ssh -C</programlisting>

      <para id="x_4b9">Если Вы используете <command>ssh</command>, то можете настроить постоянное использование сжатия при работе с Вашим сервером. Для этого поправьте файл <filename role="special">.ssh/config</filename> (может не существовать), как приведено ниже.</para>

      <programlisting>Host hg
  Compression yes
  HostName hg.example.com</programlisting>

      <para id="x_4ba">Здесь определён синоним, <literal>hg</literal>. При его использовании в командной строке <command>ssh</command> или в <literal>ssh</literal>-URL Mercurial'а, выполняется подключение к хосту <literal>hg.example.com</literal> с использованием сжатия. Это даёт Вам сразу и короткое имя для ввода, и включает компрессию, что хорошо и по-отдельности, и вместе.</para>
    </sect2>
  </sect1>

  <sect1 id="sec:collab:cgi">
    <title>Работа по HTTP с использованием CGI</title>

    <para id="x_6a8">Самый простой способ раздавать один или более репозиториев на постоянной основе, это использовать веб-сервер и встроенную реализацию CGI в Mercurial.</para>

    <para id="x_4bb">В зависимости от ваших целей, конфигурирование  интерфейса CGI системы Mercurial может занять от нескольких мгновений до нескольких часов.</para>

    <para id="x_4bc">Мы начнем с самого простого примера и далее перейдем к более сложной конфигурации. Даже в обычных случаях вам непременно потребуется умение понимать и изменять конфигурацию вашего веб-сервера.</para>

    <note>
      <title>Требуется высокая надёжность</title>

      <para id="x_4bd">Конфигурирование веб-сервера это сложная, кропотливая деятельность, сильно зависящая от всей системы. Я не могу дать указания для всех случаев, с которыми вы столкнетесь. Пожалуйста, будьте внимательны и рассудительны в следующей части работы. Будьте готовы совершить множество ошибок и провести бессоные ночи, читая логи ошибок сервера.</para>

      <para id="x_6a9">Если у вас нет сильного желания настраивать конфигурацию, снова и снова, или насущной необходимости размещать собственные услуги, вы можете попробовать одну из публичных услуг хостинга, которые я упоминал ранее.</para>
    </note>

    <sect2>
      <title>Список проверок конфигурации веб-сервера</title>

      <para id="x_4be">Прежде чем вы продолжите, обязательно уделите пару минут для проверки некоторых настроек вашей системы.</para>

      <orderedlist>
	<listitem><para id="x_4bf">Имеется ли в вашей системе установленный web-сервер? Mac OS X и разные дистрибутивы Linux поставляются с Apache, но во многих других операционных системах веб-серверы могут быть не установлены.</para>
	</listitem>
	<listitem><para id="x_4c0">Если web-сервер установлен, запущен ли он? В большинстве систем, даже если он есть, он может быть отключен по умолчанию.</para>
	</listitem>
	<listitem><para id="x_4c1">Позволяет ли конфигурация вашего сервера выполнять  программы CGI в директории, где вы планируете это делать? Большинство серверов по умолчанию явно запрещают запуск CGI программ.</para>
	</listitem></orderedlist>

      <para id="x_4c2">Если ваш web-сервер не установлен или у вас нет достаточного опыта конфигурирования Apache, вам следует использовать web-сервер <literal>lighttpd</literal> вместо Apache. Apache известен за причудливость и запутаность конфигурации. Хотя <literal>lighttpd</literal> менее функционален, чем Apache, большинство из его недостатков не относятся к обслуживанию хранилищ Mercurial. И с <literal>lighttpd</literal> несомненно <emphasis>намного</emphasis> легче начать работу, чем c Apache.</para>
    </sect2>

    <sect2>
      <title>Базовая конфигурация  CGI</title>

      <para id="x_4c3">Обычно в Unix-системах поддиректория web-контента пользователя имеет имя <filename class="directory">public_html</filename> и расположена в домашней директории. Файл с именем <filename>foo</filename> в этой директории будет доступен по ссылке <literal>http://www.example.com/username/foo</literal>.</para>

      <para id="x_4c4">Для начала работы найдите скрипт <filename role="special">hgweb.cgi</filename>, который должен быть в вашей копии Mercurial. Если вы не можете быстро найти его локальную копию в вашей системе, просто скачайте его из основного хранилища Mercurial <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para>

      <para id="x_4c5">Вам следует скопировать данный скрипт в вашу директорию <filename class="directory">public_html</filename> и задать ему права на исполнение.</para>
      <programlisting>cp .../hgweb.cgi ~/public_html
chmod 755 ~/public_html/hgweb.cgi</programlisting>
      <para id="x_4c6">Аргумент <literal>755</literal> команды <command>chmod</command> &emdash; установка прав на выполнение скрипта; он описывает, что скрипт может читаться и выполняться всеми пользователями, а права на запись у <quote>группы</quote> и <quote>других</quote> пользователей <emphasis>не</emphasis> установлены. Если бы Вы оставили всем права на запись, то модуль <literal>suexec</literal> сервера Apache скорее всего отказался бы выполнять скрипт. <literal>suexec</literal> так же требует, чтобы <emphasis>директория</emphasis>, в которой находится скрипт, не была доступна для записи другим пользователям.</para>
      <programlisting>chmod 755 ~/public_html</programlisting>

      <sect3 id="sec:collab:wtf">
	<title>Где могут возникнуть проблемы?</title>

	<para id="x_4c7">Как только вы скопировали CGI скрипт, попробуйте перейти браузером по адресу <literal>http://myhostname/~myuser/hgweb.cgi</literal>, <emphasis>но</emphasis> не падайте духом перед неудачными попытками. Вероятней всего вы не сможете открыть ссылку, и на это есть множество причин. На самом деле вы спотыкаетесь на одной из ошибок, приведенных ниже, поэтому, пожалуйста, прочтите внимательно. Это те ошибки, с которыми я сталкивался в Fedora 7 с только что установленным Apache и пользовательским аккаунтом, который я специально создал для этого.</para>

	<para id="x_4c8">Ваш веб-сервер может иметь настройки, запрещающие пользовательский веб-контент. При использовании Apache найдите в его конфигурационном файле директиву <literal>UserDir</literal>. Если она отсутствует, то отображение пользовательских директорий запрещено. В противном случае следующее за <literal>UserDir</literal> строковое значение определяет имя директории в домашнем каталоге пользователя, контент из которой будет отдаваться Apache'м. Например, <filename class="directory">public_html</filename>.</para>

	<para id="x_4c9">Ваши настройки безопасности могут быть слишком ограничивающими. Web сервер должен иметь возможность доступа к вашей домашней директории и вложенные в <filename class="directory">public_html</filename> директории, а также файлам в них. Вот рецепт, чтобы помочь вам сделать соотвествующие настройки безопасности.</para>
	<programlisting>chmod 755 ~
find ~/public_html -type d -print0 | xargs -0r chmod 755
find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting>

	<para id="x_4ca">Другая возможная проблема с правами состоит в том, что вы можете получить пустое окно, когда пытаетесь загрузить скрипт. В этом случае очень похоже что ваши настройки безопасности также <emphasis>слишком ограничивают</emphasis> выполнение подсистемой запуска скриптов Apache скриптов у которых, к примеру, стоят права записи для группы или всех пользователей.</para>

	<para id="x_4cb">Ваш web сервер может быть сконфигурирован с отключенными опциями выполнения CGI программ. Вот файл пользовательской конфигурации по умолчанию из моей ОС Fedora:</para>

	&ch06-apache-config.lst;

	<para id="x_4cc">Если вы обнаружите похожую на эту группу <literal>Directory</literal> в вашей конфигурации Apache, добавьте <literal>ExecCGI</literal> в конец директивы <literal>Options</literal>, если она отсуствует и перезапустите web сервер.</para>

	<para id="x_4cd">Если при открытии через web браузер Ваш Apache выдаёт исходный текст CGI скрипта, вместо результатов его выполнения, то Вам надо добавить или раскомментировать (если уже есть) такую директиву:</para>
	<programlisting>AddHandler cgi-script .cgi</programlisting>

	<para id="x_4ce">Следующая возможная проблема, которую вам придется решить, может быть красочный вывод трассировки Python, который будет говорить о том что он не может импортировать связанный с <literal>mercurial</literal> модуль. Это уже прогресс! Теперь сервер пытается выполнить CGI программу. Это ошибка вероятно произойдет, если вы проведете инсталяцию Mercurial для себя, вместо версии установки в систему.Помните что ваш web сервер запускает ваши CGI программы без каких-либо переменных среды, которые присуствуют в интерактивном сеансе. Если случилась такая ошибка, отредактируйте ваш <filename role="special">hgweb.cgi</filename>  файл и следйуте указаниям как установить внутри него правильную переменную среды <envar>PYTHONPATH</envar>.</para>

	<para id="x_4cf">В конце-концов вы увидите другую трассировку Python, которая будет жаловаться что не может найти <filename class="directory">/path/to/repository</filename>. Отредактируйте ваш <filename role="special">hgweb.cgi</filename> скрипт и замените в нем строку <filename class="directory">/path/to/repository</filename> на полный путь к репозиторию, который вы хотите отобразить в web сервере.</para>

	<para id="x_4d0">В этом месте, когда вы попробуете перезагрузить web страничку, вы должны увидеть простой HTML интерфейс истории вашего репозитория. Фуф!</para>
      </sect3>

      <sect3>
	<title>Настройка lighttpd</title>

	<para id="x_4d1">Чтобы быть исчерпывающим в моих экспериментах, я попробовал настроить всё более популярный <literal>lighttpd</literal> веб сервер для обслуживания того же репозитория, который я выше описывал с Apache. Я уже преодолел все проблемы выделенные с Apache, многие из которых не связаны с сервером. В результате я справедливо убедился в правильности разрешений на мои файлы и директории, и в том, что мой скрипт <filename role="special">hgweb.cgi</filename> был надлежаще исправлен.</para>

	<para id="x_4d2">Раз у меня работал Apache, я смог быстро заставить <literal>lighttpd</literal> обслуживать репозиторий (другими словами, даже если вы попробуете использовать <literal>lighttpd</literal>, вам придётся читать раздел про Apache). Для начала я отредактировал секцию <literal>mod_access</literal> в его конфигурационном файле, чтобы включить <literal>mod_cgi</literal> и <literal>mod_userdir</literal>, которые по умолчанию были отключены в моей системе. Затем я добавил несколько строк в конце конфигурационного файла, чтобы настроить эти модули.</para>
	<programlisting>userdir.path = "public_html"
cgi.assign = (".cgi" =&gt; "" )</programlisting>
	<para id="x_4d3">После этого <literal>lighttpd</literal> отлично запустился. Если бы я настраивал <literal>lighttpd</literal> до Apache, то почти наверняка столкнулся бы с теми же проблемами конфигурации системы, что и в Apache. Однако, я нашел, что <literal>lighttpd</literal> заметно проще конфигурировать чем Apache, несмотря на то, что я уже использовал Apache больше десяти лет, и это был мой первый опыт работы с <literal>lighttpd</literal>.</para>
      </sect3>
    </sect2>

    <sect2>
      <title>Настройка доступа к нескольким хранилищам с помощью одного CGI-скрипта</title>

      <para id="x_4d4">Скрипт <filename role="special">hgweb.cgi</filename> позволяет Вам опубликовать одно хранилище, что является досадным ограничением. Если Вы хотите опубликовать больше одного, использовав несколько копий этого скрипта с разными именами без раздражения себя, лучшим выбором будет использовать скрипт <filename role="special">hgwebdir.cgi</filename>.</para>

      <para id="x_4d5">Процедура настройки <filename role="special">hgwebdir.cgi</filename> несколько сложнее чем <filename role="special">hgweb.cgi</filename>. Для начала, Вы должны получить копию скрипта. Если у Вас его нет под рукой, можете загрузить из хранилища Mercurial по ссылке <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para>

      <para id="x_4d6">Вы должны скопировать этот скрипт в каталог <filename class="directory">public_html</filename> и убедиться в том, что он исполняемый.</para>

      <programlisting>cp .../hgwebdir.cgi ~/public_html
chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting>

      <para id="x_4d7">После базовой настроки попробуйте открыть <literal>http://myhostname/~myuser/hgwebdir.cgi</literal> в Вашем браузере. Должен отображаться пустой список хранилищ. Если Вы получаете пустое окно или сообщение об ошибке, попробуйте просмотреть список потенциальных проблем в <xref linkend="sec:collab:wtf"/>.</para>

      <para id="x_4d8">Скрипт <filename role="special">hgwebdir.cgi</filename> зависит от внешнего файла конфигурации. По-умолчанию он ищет файл <filename role="special">hgweb.config</filename> в этом же каталоге. Вы должны создать его и сделать общедоступным. Формат этого файла похож на формат <quote>ini</quote> файлов в Windows, который распознается в Python  модулем <literal>ConfigParser</literal> <citation>web:configparser</citation>.</para>

      <para id="x_4d9">Самый простой способ настроить <filename role="special">hgwebdir.cgi</filename> &emdash; использовать раздел, который называется <literal>collections</literal>. Это позволит автоматически опубликовать <emphasis>все</emphasis> хранилища в каталоге, который Вы укажите. Этот раздел должен выглядеть следующим образом:</para>
      <programlisting>[collections]
/my/root = /my/root</programlisting>
      <para id="x_4da">Mercurial воспринимает это так: смотрит имя директории с <emphasis>правой</emphasis> стороны от знака <quote><literal>=</literal></quote>; ищет репозитории внутри этой директории; и использует текст с <emphasis>левой</emphasis> стороны чтобы обрезать совпадающий текст в именах, фактически отображающихся в веб интерфейсе. Оставшаяся часть после обрезания пути называется <quote>виртуальный путь</quote>.</para>

      <para id="x_4db">В упомянутом выше примере, если мы имеем репозиторий, чей локальный путь <filename class="directory">/my/root/this/repo</filename>, CGI скрипт обрежет начальную часть <filename class="directory">/my/root</filename> в имени и опубликует репозиторий с виртуальным путём <filename class="directory">this/repo</filename>. Если базовый URL нашего CGI скрипта <literal>http://myhostname/~myuser/hgwebdir.cgi</literal>, тогда полный путь для этого репозитория будет <literal>http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para>

      <para id="x_4dc">Если мы заменим <filename class="directory">/my/root</filename>  с левой стороны этого примера на <filename class="directory">/my</filename>, тогда <filename role="special">hgwebdir.cgi</filename>  будет просто обрезать <filename class="directory">/my</filename> из имени репозитория и будет предоставлять виртуальный путь <filename class="directory">root/this/repo</filename> вместо <filename class="directory">this/repo</filename>.</para>

      <para id="x_4dd">Скрипт <filename role="special">hgwebdir.cgi</filename> будет рекурсивно искать в каждой из перечисленных в секции <literal>collections</literal> конфигурационного файла директории, но <literal>не</literal> будет рекурсивно искать в найденых репозиториях.</para>

      <para id="x_4de">Механизм <literal>collections</literal> позволяет легко публиковать множество репозиториев в манере <quote>выстрелил и забыл</quote>. Вам нужно только один раз установить CGI скрипт и конфигурационный файл. Впоследствии вы можете публиковать и прятать репозиторий в любое время, просто помещая внутрь или убирая из дерктории, за которой наблюдает <filename role="special">hgwebdir.cgi</filename>.</para>

      <sect3>
	<title>Явное определение публикуемых репозиториев</title>

	<para id="x_4df">В дополнение в механизму <literal>collections</literal>, скрипт <filename role="special">hgwebdir.cgi</filename> позволяет вам публиковать специфичный лист репозиториев. Для того сделать это создайте секцию <literal>paths</literal> с содержимым подобным этому:</para>
	<programlisting>[paths]
repo1 = /my/path/to/some/repo
repo2 = /some/path/to/another</programlisting>
	<para id="x_4e0">В этом случае, виртуальный путь (показывающаяся в URL часть) расположен слева в каждом определении, тогда как путь к репозиторию находиться справа. Обратите внимание, что нет никакой зависимости между выбранным вами виртуальным путём и положением ропозитория в вашей файловой системе.</para>

	<para id="x_4e1">Если вы хотите, то можете использовать <literal>collections</literal> и механизм <literal>paths</literal> одновременно в одном конфигурационном файле.</para>

	<note>
	  <title>Остерегайтесь дублирования виртуальных путей</title>

	  <para id="x_4e2">Если несколько репозиториев будут иметь один и тот же виртуальный путь, <filename role="special">hgwebdir.cgi</filename>  не будет сообщать об ошибке. Вместо этого он будет вести себя непредсказуемо.</para>
	</note>
      </sect3>
    </sect2>

    <sect2>
      <title>Загрузка исходных архивов</title>

      <para id="x_4e3">Web интерфейс Mercurial позволяет пользователям скачивать архив любой ревизии. Этот архив будет содержать снимок рабочей директории, но не будет содержать копию данных репозитория.</para>

      <para id="x_4e4">По умолчанию эта возможность отключена. Если вы хотите включить её, вам нужно будет добавить элемент <envar role="rc-item-web">allow_archive</envar> в секцию <literal role="rc-web">web</literal> вашего <filename role="special">~/.hgrc</filename> файла.</para>
    </sect2>
    <sect2>
      <title>Опции настройки веб интерфейса</title>

      <para id="x_4e5">Web интерфейс Mercurial (команда <command role="hg-cmd">hg serve</command>, <filename role="special">hgweb.cgi</filename> и скрипты <filename role="special">hgwebdir.cgi</filename>) имеют несколько опций, которые вы можете настроить. Они располагаются в секции <literal role="rc-web">web</literal>.</para>
      <itemizedlist>
	<listitem><para id="x_4e6"><envar role="rc-item-web">allow_archive</envar> Определяет который (если нужно) из методов загрузки архивов поддерживает Mercurial. Если вы включите эту опцию, пользователи веб интерфейса смогут скачать архив любой версии репозитория, который они просматривают. Чтобы включить возможность загрузки архивов, этот элемент должен содержать последовательность слов, перечисленных ниже.</para>
	  <itemizedlist>
	    <listitem><para id="x_4e7"><literal>bz2</literal>: Архив <command>tar</command>, сжатый по алгоритму <literal>bzip2</literal>. Имеет наилучшую степень сжатия, но использует больше процессорного времени на сервере.</para>
	    </listitem>
	    <listitem><para id="x_4e8"><literal>gz</literal>:  Архив <command>tar</command>, сжатый по алгоритму <literal>gzip</literal>.</para>
	    </listitem>
	    <listitem><para id="x_4e9"><literal>zip</literal>: Архив <command>zip</command>, сжатый используя алгоритм LZW. Этот формат имеет наихудшее сжатие, но широко используется в мире Windows.</para>
	    </listitem>
	  </itemizedlist>
	  <para id="x_4ea">Если у вас будет пустой список или не будет записи <envar role="rc-item-web">allow_archive</envar> вообще, то эта возможность будет отключена. Ниже дан пример как включить все три поддерживаемых формата.</para>
	  <programlisting>[web]
allow_archive = bz2 gz zip</programlisting>
	</listitem>
	<listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>: Boolean. Определяет позволяет ли web интерфейс удаленным пользователям использовать команды <command role="hg-cmd">hg pull</command> и <command role="hg-cmd">hg clone</command> через HTTP. Если эта опция установлена в <literal>no</literal> или <literal>false</literal>, то только <quote>пользовательская</quote> часть web интерфейса доступна.</para>
	</listitem>
	<listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>: String. Строка свободного формата (но предпочтительно короткая) отождествляющая человека или группу создавшую репозиторий. Она обычно  содежит имя и email адрес человека или листа почтовой рассылки. Эту запись обычно располагают в собственном <filename role="special">.hg/hgrc</filename> репозитория, но так же можно расположить в глобальном <filename role="special">~/.hgrc</filename>, если каждый репозиторий имеет единственного мейнтейнера.</para>
	</listitem>
	<listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>: Integer. Максимальное количество наборов изменений отображаемое на одной странице по умолчанию.</para>
	</listitem>
	<listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>: Integer. Максимальное количество модифицированных файлов отображаемое на одной странице по умолчанию.</para>
	</listitem>
	<listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>: Integer. Если web интерфейс отображает разноцветные <quote>полосы</quote>, облегчающие визуальное восприятие выводимых строк, то значение этого параметра будет означать количество строк текста в каждой цветной строке.</para>
	</listitem>
	<listitem><para id="x_4f0"><envar role="rc-item-web">style</envar>: Управляет шаблоном Mercurial, использующимся для отображения web интерфейса. Mercurial поставляется с несколькими веб-шаблонами.</para>
	  <itemizedlist>
	    <listitem>
	      <para id="x_6aa"><literal>coal</literal> &emdash; чёрнобелый.</para>
	    </listitem>
	    <listitem>
	      <para id="x_6ab"><literal>gitweb</literal> &emdash; эмулирует веб-интерфейс git-а</para>
	    </listitem>
	    <listitem>
	      <para id="x_6ac"><literal>monoblue</literal> &emdash; используются синие и серый цвета.</para>
	    </listitem>
	    <listitem>
	      <para id="x_6ad"><literal>paper</literal> &emdash; используется по умолчанию.</para>
	    </listitem>
	    <listitem>
	      <para id="x_6ae"><literal>spartan</literal> &emdash; ранее использовался по умолчанию.</para>
	    </listitem>
	  </itemizedlist>
	  <para id="x_6af">Вы можете также определить свой шаблон; более детально эта возможность обсуждается в <xref linkend="chap:template"/>. Ниже вы можете видеть как включить стиль <literal>gitweb</literal>.</para>
	  <programlisting>[web]
style = gitweb</programlisting>
	</listitem>
	<listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>: Path. Path содержит имя каталога в котором ищутся файлы шаблонов. По умолчанию Mercurial ищет их в директории где установлен.</para>
	</listitem></itemizedlist>
      <para id="x_4f2">Если вы используете <filename role="special">hgwebdir.cgi</filename>, вы можете поместить для удобства некоторые элементы конфигурации в секцию <literal role="rc-web">web</literal> файла <filename role="special">hgweb.config</filename>, вместо файла <filename role="special">~/.hgrc</filename>. Это элементы &emdash; <envar role="rc-item-web">motd</envar> и <envar role="rc-item-web">style</envar>.</para>

      <sect3>
	<title>Опции, специфичные для индивидуального репозитория</title>

	<para id="x_4f3">Некоторые элементы раздела <literal role="rc-web">web</literal> должны быть помещены в локальный файл <filename role="special">.hg/hgrc</filename>, вместо помещения их в глобальный <filename role="special">~/.hgrc</filename> для пользователя.</para>
	<itemizedlist>
	  <listitem><para id="x_4f4"><envar role="rc-item-web">description</envar>: String. Строка в свободной форме (предпочтительно небольшая), которая описывает сущьность репозитория или его содержимое.</para>
	  </listitem>
	  <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>: String. Строка с именем репозитория для использования в web интерфейсе. Она имеет больший приоритет (переопределяет) нежели имя по умолчанию, которое является последним компонентом пути репозитория.</para>
	  </listitem></itemizedlist>
      </sect3>

      <sect3>
	<title>Опции, специфичные для команды <command role="hg-cmd">hg serve</command></title>

	<para id="x_4f6">Некоторые элементы секции <literal role="rc-web">web</literal> файла <filename role="special">~/.hgrc</filename> используются только с командой <command role="hg-cmd">hg serve</command>.</para>
	<itemizedlist>
	  <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>: Path. Имя файла для аудита доступа. По умолчанию команда <command role="hg-cmd">hg serve</command> пишет свою информацию в stdout,  а не в файл. Элементы лог файла пишутся в стандартном <quote>объединенном</quote> формате файлов, который используется почти всеми web серверами.</para>
	  </listitem>
	  <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>: String. Локальный адрес, который должен слушать web сервер в ожидании подключений к нему. По умолчанию сервер слушает все адреса.</para>
	  </listitem>
	  <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>: Path. Имя файла в который будут выводиться сообщения об ошибках. По умолчанию команда <command role="hg-cmd">hg serve</command> записывает эту информацию в stdout, а не в файл.</para>
	  </listitem>
	  <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>: Boolean. Определяет использовать или нет IPv6 протокол при работе сервера. По умолчанию IPv6 не используется.</para>
	  </listitem>
	  <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>: Integer. Определяет номер порта (число) который будет слушать web сервер. По умолчанию значение равно 8000.</para>
	  </listitem></itemizedlist>
      </sect3>

      <sect3>
	<title>Выбор правильного файла <filename role="special">~/.hgrc</filename> для добавления элементов в секцию <literal role="rc-web">web</literal>.</title>

	<para id="x_4fc">Важно помнить, что веб сервера вроде Apache или <literal>lighttpd</literal> запускаются под пользовательским аккаунтом (UID-ом), который отличается от того, под которым работаете вы. Скрипты CGI, запускаемые вашим сервером, такие как <filename role="special">hgweb.cgi</filename>, обычно запускаются под тем же пользователем (UID-ом).</para>

	<para id="x_4fd">Если вы добавляете элементы в секцию <literal role="rc-web">web</literal> вашего персонального <filename role="special">~/.hgrc</filename>, то CGI скрипты не станут читать этот файл. Произведенные там настройки влияют только на поведение команды <command role="hg-cmd">hg serve</command>, когда вы ее используете. Чтобы заставить CGI скрипты видеть ваши параметры настроек создайте файл <filename role="special">~/.hgrc</filename> в домашнем каталоге пользователя под кем запускается web сервис, или добавьте эти параметры к основному системному файлу <filename role="special">hgrc</filename>.</para>
      </sect3>
    </sect2>
  </sect1>

  <sect1>
    <title>Системный файл конфигурации</title>

    <para id="x_6b0">На Unix-подобных операционных системах совместного использования несколькими пользователями (например, сервер, на котором люди публикуют изменения), часто имеет смысл создавать некое глобальное поведение по умолчанию, например, какие темы использовать в веб-интерфейсах.</para>

    <para id="x_6b1">Если файл с именем <filename>/etc/mercurial/hgrc</filename> существует, Mercurial будет читать во время запуска и применять параметры конфигурации, которые  находит в этом файле. Он также будет искать файлы с расширением <literal>.rc</literal> в каталоге <filename>/etc/mercurial/hgrc.d</filename>, и применять параметры конфигурации, которые  находит в этих файлах.</para>

    <sect2>
      <title>Делаем Mercurial более доверенным.</title>

      <para id="x_6b2">Один из ситуации, в котором глобальный <filename>hgrc</filename> может быть полезен, если пользователи вытягивают изменения, принадлежащие другим пользователям. По умолчанию Mercurial не будет доверять большинству параметров конфигурации из файла <filename role="special">.hg/hgrc</filename> в репозитории, который принадлежит другому пользователю. Если мы клонируем или вытягиваем изменения такого хранилища, Mercurial выведет предупреждение о том, что он не доверяет параметрам из <filename role="special">.hg/hgrc</filename>.</para>

      <para id="x_6b3">Если все участники команды находятся в той или иной группе Unix  и <emphasis>доверяют</emphasis> конфигурации друг друга, или мы хотим доверять конкретным пользователям, мы можем переопределить в Mercurial скептическое отношение по-умолчанию путем создания общесистемного  файла <filename>hgrc</filename>, такого как:</para>

    <programlisting># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc
[trusted]
# Trust all entries in any hgrc file owned by the "editors" or
# "www-data" groups.
groups = editors, www-data

# Trust entries in hgrc files owned by the following users.
users = apache, bobo
</programlisting>
    </sect2>
  </sect1>
</chapter>

<!--
local variables: 
sgml-parent-document: ("00book.xml" "book" "chapter")
end:
-->