summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex.hs25
-rw-r--r--Annex/Branch/Transitions.hs8
-rw-r--r--Annex/CatFile.hs2
-rw-r--r--Annex/FileMatcher.hs33
-rw-r--r--Annex/MetaData.hs17
-rw-r--r--Annex/MetaData/StandardFields.hs47
-rw-r--r--Annex/Notification.hs81
-rw-r--r--Annex/Ssh.hs9
-rw-r--r--Annex/Transfer.hs131
-rw-r--r--Assistant/Alert/Utility.hs1
-rw-r--r--Assistant/Install.hs31
-rw-r--r--Assistant/Install/Menu.hs2
-rw-r--r--Assistant/Ssh.hs2
-rw-r--r--Assistant/Threads/ConfigMonitor.hs8
-rw-r--r--Assistant/Threads/Watcher.hs7
-rw-r--r--Assistant/Threads/WebApp.hs6
-rw-r--r--Build/NullSoftInstaller.hs2
-rw-r--r--BuildFlags.hs7
-rw-r--r--CmdLine.hs2
-rw-r--r--CmdLine/Option.hs6
-rw-r--r--CmdLine/Seek.hs19
-rw-r--r--CmdLine/Usage.hs2
-rw-r--r--Command/Add.hs22
-rw-r--r--Command/AddUrl.hs36
-rw-r--r--Command/ConfigList.hs20
-rw-r--r--Command/Drop.hs66
-rw-r--r--Command/DropUnused.hs4
-rw-r--r--Command/Fsck.hs3
-rw-r--r--Command/Get.hs20
-rw-r--r--Command/List.hs4
-rw-r--r--Command/Map.hs19
-rw-r--r--Command/MetaData.hs41
-rw-r--r--Command/Move.hs54
-rw-r--r--Command/PreCommit.hs29
-rw-r--r--Command/SendKey.hs2
-rw-r--r--Command/Sync.hs2
-rw-r--r--Command/TransferKey.hs10
-rw-r--r--Command/TransferKeys.hs9
-rw-r--r--Command/Unannex.hs55
-rw-r--r--Command/Uninit.hs2
-rw-r--r--Command/Unused.hs3
-rw-r--r--Command/Vicfg.hs155
-rw-r--r--Common.hs1
-rw-r--r--Git/CatFile.hs2
-rw-r--r--Git/Fsck.hs28
-rw-r--r--Git/Repair.hs101
-rw-r--r--Limit.hs67
-rw-r--r--Locations.hs5
-rw-r--r--Logs.hs16
-rw-r--r--Logs/FsckResults.hs28
-rw-r--r--Logs/MapLog.hs81
-rw-r--r--Logs/MetaData.hs46
-rw-r--r--Logs/PreferredContent.hs117
-rw-r--r--Logs/PreferredContent/Raw.hs41
-rw-r--r--Logs/Transfer.hs102
-rw-r--r--Logs/UUIDBased.hs75
-rw-r--r--Logs/Unused.hs5
-rw-r--r--Makefile2
-rw-r--r--Remote.hs34
-rw-r--r--Remote/External.hs3
-rw-r--r--Remote/Git.hs9
-rw-r--r--Remote/Glacier.hs8
-rw-r--r--Remote/Helper/Hooks.hs3
-rw-r--r--Remote/Rsync.hs22
-rw-r--r--Remote/Rsync/RsyncUrl.hs46
-rw-r--r--Remote/Tahoe.hs2
-rw-r--r--Test.hs27
-rw-r--r--Types/CleanupActions.hs17
-rw-r--r--Types/DesktopNotify.hs27
-rw-r--r--Types/FileMatcher.hs21
-rw-r--r--Types/Limit.hs20
-rw-r--r--Types/MetaData.hs10
-rw-r--r--Types/StandardGroups.hs31
-rw-r--r--Utility/FileMode.hs40
-rw-r--r--Utility/FileSystemEncoding.hs43
-rw-r--r--Utility/Matcher.hs2
-rw-r--r--Utility/QuickCheck.hs4
-rw-r--r--Utility/ThreadScheduler.hs7
-rw-r--r--Utility/Url.hs3
-rw-r--r--Utility/WebApp.hs61
-rw-r--r--debian/changelog71
-rw-r--r--debian/control3
-rw-r--r--doc/Android/oldcomments/comment_1_cc9caa5dd22dd67e5c1d22d697096dd2._comment2
-rw-r--r--doc/assistant/downloadnotification.pngbin0 -> 4513 bytes
-rw-r--r--doc/assistant/nautilusmenu.pngbin0 -> 59867 bytes
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_6_770c4f1802fc40d76bbaf7783bb3b4ac._comment14
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_7_61c1f5b00381b2fa891a8578267881ab._comment8
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_8_35e00cd10e89ae4bcc66af7dadf6bb5c._comment8
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_9_c900e4ef49388826c87cadef4235c073._comment8
-rw-r--r--doc/automatic_conflict_resolution/comment_1_307898855f91a2a189d4fa5eae62cce1._comment2
-rw-r--r--doc/automatic_conflict_resolution/comment_2_0a8ea42764dde1a33d2112197b961c51._comment8
-rw-r--r--doc/automatic_conflict_resolution/comment_3_5c587c6633cae1c8547ca970d55ee97e._comment8
-rw-r--r--doc/automatic_conflict_resolution/comment_4_80539e11e36a0b64cee83b6b373bd843._comment17
-rw-r--r--doc/automatic_conflict_resolution/comment_5_00ac9e4a47ce9a886dbf573480f151bd._comment10
-rw-r--r--doc/bugs/Android_:_handling_DCIM__47__Camera_not_being_configurable.mdwn2
-rw-r--r--doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory.mdwn520
-rw-r--r--doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory/comment_1_ac8c39e362e6c806b9d68befc0199ccd._comment10
-rw-r--r--doc/bugs/Assistant_lost_dbus_connection_spamming_log.mdwn10
-rw-r--r--doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_12_1cfdd76e751ee3726bd80359cfc85c47._comment8
-rw-r--r--doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_13_37aa5274874242861dc128efa1d29486._comment12
-rw-r--r--doc/bugs/Bug_Report_doesn__39__t_work.mdwn20
-rw-r--r--doc/bugs/Can__39__t_access_files_from___39__Removable_drive__39___repo_even_if_set_as_client.mdwn1
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn3
-rw-r--r--doc/bugs/Could_not_read_from_remote_repository/comment_3_95d16045dc238dba19a98808de2eeedf._comment11
-rw-r--r--doc/bugs/Crash_when_disabling_syncing_in_the_webapp.mdwn23
-rw-r--r--doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_1_e25dd80370820782f9c6a877101d8703._comment10
-rw-r--r--doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_2_4031c16362137747717e9595cb5c8a15._comment10
-rw-r--r--doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_3_0667f39f60bdaba6670f5b8304a8a77c._comment12
-rw-r--r--doc/bugs/Disconcerting_warning_from_git-annex.mdwn2
-rw-r--r--doc/bugs/Disconcerting_warning_from_git-annex/comment_3_13999207f4ddac2f9c345415f25f7ada._comment28
-rw-r--r--doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles.mdwn14
-rw-r--r--doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles/comment_1_c258016dd545b0426e75a7c0132154d8._comment8
-rw-r--r--doc/bugs/Fix_to_thaoe_remote_to_work_with_latest_tahoe-lafs___40__v._1.10.0__41__.mdwn62
-rw-r--r--doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.mdwn (renamed from doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.txt)0
-rw-r--r--doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn (renamed from doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn)2
-rw-r--r--doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment (renamed from doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment)0
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn10
-rw-r--r--doc/bugs/Race_condition_between_watch__47__assistant_and_addurl.mdwn195
-rw-r--r--doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_1_8f56b8661a600729d7a9d569e8a0ba70._comment55
-rw-r--r--doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_2_46dc67bdcd174cd50ccc421ec56735ad._comment14
-rw-r--r--doc/bugs/Share_with_friends_crash_in_osx.mdwn2
-rw-r--r--doc/bugs/Share_with_friends_crash_in_osx/comment_13_65de2b5dd3af89c2f0f6508ffddda3b5._comment12
-rw-r--r--doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.mdwn (renamed from doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.txt)0
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows.mdwn41
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_1_3dfa4559dceec50c08ba180f41b4c220._comment14
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_2_4dafea4367d455c2e63b0f7b1cc39559._comment10
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_3_bdde68a990a330ee0cf626be44b1c132._comment8
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_4_9140fb8034b1449ee2f4762093bc1f89._comment10
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_5_661ca15b68bc0e3fbe85f11400570446._comment15
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_6_0e8820169c0300d296c697154fd05dc4._comment8
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_7_b23a2bf106053f105798b270536057e5._comment38
-rw-r--r--doc/bugs/Unicode_file_names_ignored_on_Windows/comment_8_7f23911705eaa58a9230f19ab890e87f._comment12
-rw-r--r--doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_8_35c949aca52de83af4881a9da6340185._comment8
-rw-r--r--doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_9_9100031689eaa460791191d9bfb746d8._comment8
-rw-r--r--doc/bugs/__92____92___instead_of___47___on_rsync_special_remote_on_linux_accessed_from_a_windows_git-annex.mdwn27
-rw-r--r--doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories.mdwn88
-rw-r--r--doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_1_930b40e0f68da95d335eea5bd4216126._comment12
-rw-r--r--doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_2_5397d488bc337cb3d7cb46ed774d0437._comment90
-rw-r--r--doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_3_1b30e7611ec824dc6e79ef35e43ac740._comment10
-rw-r--r--doc/bugs/__96__minimal_build__39____fails_due_to_missing_stm_dependency/comment_1_86e26ee9ec90aa00f25392052737f0f0._comment2
-rw-r--r--doc/bugs/_impossible_to_switch_repositories_on_android__in_webapp/comment_3_9ffafbeb572e110b3e072029d1ce177c._comment8
-rw-r--r--doc/bugs/copy_to_--fast_should_not_mention_every_file_it_checks.mdwn3
-rw-r--r--doc/bugs/enormous_fsck_output_OOM.mdwn10
-rw-r--r--doc/bugs/git-annex_fails_to_initialize_under_Windows.mdwn212
-rw-r--r--doc/bugs/git-annex_fails_to_initialize_under_Windows/comment_1_082277b9b906a2cc0fcace6790f5cfad._comment10
-rw-r--r--doc/bugs/git_annex_content_fails_with_a_parse_error.mdwn (renamed from doc/bugs/git_annex_content_fails_with_a_parse_error.txt)0
-rw-r--r--doc/bugs/git_annex_dead_does_not_work_as_expected_when_multiple_repos_exist_with_the_same_name___40__notably_including_dead_ones__41__.mdwn2
-rw-r--r--doc/bugs/git_annex_fsck_in_direct_mode_does_not_checksum_files/comment_2_4ac3b87ec0bc0514c4eff9f5a75b9f5d._comment2
-rw-r--r--doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__.mdwn2
-rw-r--r--doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_3_a234e4f58d2cc3b0110e4e65aceeb2c3._comment20
-rw-r--r--doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_4_a01a867500fd94e6b317e74a0b0b1401._comment8
-rw-r--r--doc/bugs/git_annex_sync_in_direct_mode_does_not_honor_skip-worktree/comment_4_a7eab4171af7e46bcc637aacf630e9db._comment8
-rw-r--r--doc/bugs/git_annex_test_under_windows_8.1.mdwn67
-rw-r--r--doc/bugs/id__95__rsa_on_android/comment_3_cbe24ed08a7ef91c8c0c20ab9b7d25b7._comment10
-rw-r--r--doc/bugs/issues_with_non-posix_compatible_shells.mdwn41
-rw-r--r--doc/bugs/issues_with_non-posix_compatible_shells/comment_1_076948499a9d581a50da52b7690e5d4e._comment8
-rw-r--r--doc/bugs/map_error_after_forget/comment_1_81001ecda65d882ea946611d1e18d59f._comment10
-rw-r--r--doc/bugs/map_error_after_forget/comment_2_24f3b6699f646ec0c20f3d4ca010e345._comment28
-rw-r--r--doc/bugs/map_error_after_forget/comment_3_950e735c6d618e60cffffd1aebf06fd3._comment8
-rw-r--r--doc/bugs/map_error_after_forget/comment_4_39327211f3fd1f9ed196a1f09cf68bdc._comment8
-rw-r--r--doc/bugs/map_error_after_forget/comment_6_471a2f5792dfc7cde4f1eb793984abf1._comment8
-rw-r--r--doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames.mdwn29
-rw-r--r--doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_1_ca10638d4b4b178cfd0de8736542c4dc._comment12
-rw-r--r--doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_2_986a393a512229d35e529ba242b77b1e._comment10
-rw-r--r--doc/bugs/problem_to_addurl_--file_with_ftp.mdwn67
-rw-r--r--doc/bugs/problem_to_addurl_--file_with_ftp/comment_1_2bf44f1653069fb2ed0b124cf8581a48._comment8
-rw-r--r--doc/bugs/problem_to_addurl_--file_with_ftp/comment_2_c85266a9359a9f45e632f31c016a45dc._comment8
-rw-r--r--doc/bugs/problem_to_addurl_--file_with_ftp/comment_3_5bba62e1dd4118bcf7e1c990c7009239._comment22
-rw-r--r--doc/bugs/problems_with_glacier.mdwn65
-rw-r--r--doc/bugs/problems_with_glacier/comment_1_8d233428a16ae4276d9c69b329e8216b._comment12
-rw-r--r--doc/bugs/set_metadata_on_wrong_files.mdwn90
-rw-r--r--doc/bugs/set_metadata_on_wrong_files/comment_1_074f124e5d313e90b3e9217325799587._comment8
-rw-r--r--doc/bugs/ssh:_unprotected_private_key_file.mdwn62
-rw-r--r--doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__.mdwn10
-rw-r--r--doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__/comment_1_462c377dca2484e5598a0b71d91ab64a._comment8
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument.mdwn87
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_1_004cb3015895ad67386276f3e1f0de0d._comment10
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_2_3fe298ebb3ff04d12f2528aa982d7084._comment24
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_3_9302536d1577c12337d714fa3a9ea7a1._comment10
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_4_c1c8de66192957b7026d99b9ff90589c._comment16
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_5_8c2dad766e4115073d49b698919b5ed5._comment8
-rw-r--r--doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_6_8da2a73381309ecef4b2796d8f2bb0bb._comment10
-rw-r--r--doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote.mdwn2
-rw-r--r--doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote/comment_2_f430538101f0ef6114b5e953248fa599._comment8
-rw-r--r--doc/bugs/whereis_outputs_no_informaiton_for_unlocked_files/comment_1_47bd0fc8d1c65f8a868d9722e66c71db._comment10
-rw-r--r--doc/copies.mdwn3
-rw-r--r--doc/design/assistant/blog/day_288__success_stories/comment_15_5749aef8b585b293385b20b75c40f9d8._comment2
-rw-r--r--doc/design/assistant/blog/day_45__long_polling/comment_3_5526c9dd4fd87da56cb8456083169f55._comment2
-rw-r--r--doc/design/assistant/polls/Android_default_directory.mdwn2
-rw-r--r--doc/design/assistant/polls/prioritizing_special_remotes.mdwn2
-rw-r--r--doc/design/assistant/telehash.mdwn3
-rw-r--r--doc/design/caching_database.mdwn124
-rw-r--r--doc/design/metadata/comment_4_c32ade1524487e5fdc6f83b2db39f04c._comment8
-rw-r--r--doc/design/metadata/comment_5_0ac3132cd7a84f0e170fbe3a6f235fe7._comment8
-rw-r--r--doc/design/roadmap.mdwn4
-rw-r--r--doc/devblog/day_-4__forgetting/comment_8_3f7045a00905b4287d950b08d5a77a82._comment9
-rw-r--r--doc/devblog/day_132__database_musings.mdwn17
-rw-r--r--doc/devblog/day_133__db_and_bugfixes.mdwn20
-rw-r--r--doc/devblog/day_134-135__avoiding_the_turing_tarpit.mdwn18
-rw-r--r--doc/devblog/day_136__frustrating_day.mdwn10
-rw-r--r--doc/devblog/day_137-138__bug_triage_and_too_much_windows.mdwn15
-rw-r--r--doc/devblog/day_139-140__traveling.mdwn17
-rw-r--r--doc/devblog/day_141__f-droid_sprint.mdwn3
-rw-r--r--doc/devblog/day_141__f-droid_sprint/comment_1_1cc76207020ac478747117c76d7b5f9c._comment8
-rw-r--r--doc/devblog/day_142__digging_out.mdwn13
-rw-r--r--doc/devblog/day_143__foolish_hiatus.mdwn20
-rw-r--r--doc/devblog/day_144__catching_up.mdwn12
-rw-r--r--doc/devblog/day_144__catching_up/comment_1_311a7245dd12f1a7e432168d16041348._comment8
-rw-r--r--doc/devblog/day_82__rpi_and_synology/comment_1_d154ddcf22027fd06acf9da73e12c006._comment2
-rw-r--r--doc/favicon.icobin405 -> 2550 bytes
-rw-r--r--doc/favicon.pngbin714 -> 0 bytes
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__.mdwn3
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_1_924521ad5972046bac44d2e04ec296c7._comment10
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_2_e2a7f34a3ccc1b6467e6da611c067d66._comment8
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_3_f9a369a6ac69f091e6128990274d3228._comment10
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_4_91b422f8d55b68077245c606c4f7f87c._comment28
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_5_f6128fe75ff3453747f69f12e0fd0a5b._comment12
-rw-r--r--doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_6_9b90b4031a5ed26c375903b33ed65a10._comment17
-rw-r--r--doc/forum/Add_a___34__local__34___remote.mdwn (renamed from doc/forum/Add_a___34__local__34___remote.txt)0
-rw-r--r--doc/forum/Auto_sync_with_music_player/comment_3_99f65a0efaf5d5f9b8ff530acc122860._comment8
-rw-r--r--doc/forum/Folders_for___34__actions__34___-_now_that_views_have_disrupted_the_file_structure__63__.mdwn20
-rw-r--r--doc/forum/GPG_passphrase_handling.mdwn (renamed from doc/forum/GPG_passphrase_handling.txt)0
-rw-r--r--doc/forum/Generating_a_Temp_View_of_Available_Files.mdwn1
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_6_79fb5ec1b47593ab3355543c5499284a._comment8
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_7_75d4450b4608ad0b453bc69159e708de._comment10
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_8_e4e5ad0cda34bb597fe1bb804acc15e9._comment10
-rw-r--r--doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_2_85415e1fceb737919cc1cd9f37242458._comment10
-rw-r--r--doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_3_fb3a591dc60182f7922fc2b5c24f50f1._comment11
-rw-r--r--doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_4_aed0be32e579c7a39c63aa7e3ec5f67b._comment29
-rw-r--r--doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_5_0c9a6c8a92d6c6e04ae3a8349b799c60._comment22
-rw-r--r--doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository.mdwn3
-rw-r--r--doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_1_17db96492e6bc0e243fc7cb62565c4c4._comment17
-rw-r--r--doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_2_e772ea0383ac690cbcbcf125258986cf._comment16
-rw-r--r--doc/forum/Import_options.mdwn (renamed from doc/forum/Import_options.txt)0
-rw-r--r--doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__.mdwn4
-rw-r--r--doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__/comment_1_ce0464d5fca6ada9f1477831fd47ce09._comment8
-rw-r--r--doc/forum/Purge_a_remote.mdwn (renamed from doc/forum/Purge_a_remote.txt)0
-rw-r--r--doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment2
-rw-r--r--doc/forum/Sync_with_one_offline_peer.mdwn (renamed from doc/forum/Sync_with_one_offline_peer.txt)0
-rw-r--r--doc/forum/Tracking_a_directory_with_some_hg_and_git_repositories/comment_4_c889050d3079edefc4633451bd5baff8._comment11
-rw-r--r--doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.mdwn (renamed from doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.txt)0
-rw-r--r--doc/forum/Using_git-annex_as_a_library/comment_3_ac52304a096ebc66967352efaffb060a._comment8
-rw-r--r--doc/forum/Using_git-annex_as_a_library/comment_4_d502fea60bf3a82f8a50f72a90a80c25._comment8
-rw-r--r--doc/forum/XBMC__44___NFS___38___git-annex_.mdwn (renamed from doc/forum/XBMC__44___NFS___38___git-annex_.txt)0
-rw-r--r--doc/forum/central_non-bare_and_git_push.mdwn (renamed from doc/forum/central_non-bare_and_git_push.txt)0
-rw-r--r--doc/forum/faking_location_information.mdwn19
-rw-r--r--doc/forum/git_annex_get_--want-get_another__95__repo/comment_1_0be0b3981ddd0743ff26cf6d396e521d._comment16
-rw-r--r--doc/forum/git_annex_get_--want-get_another__95__repo/comment_2_b1ead1085a87818625579bf1ef151b5d._comment8
-rw-r--r--doc/forum/git_annex_get_--want-get_another__95__repo/comment_3_cf2018852c84b0bf1ac061def6f0ac5d._comment27
-rw-r--r--doc/forum/git_annex_get_--want-get_another__95__repo/comment_4_22562e8f1f2f91b9f9a5939ec9006cb5._comment38
-rw-r--r--doc/forum/git_annex_on_osx_only_creating_symlinks__63____63__/comment_2_978fc11c463a457382fddd668cd1d0dd._comment2
-rw-r--r--doc/forum/handling_MP3_metadata_changes.mdwn (renamed from doc/forum/handling_MP3_metadata_changes.txt)0
-rw-r--r--doc/forum/handling_MP3_metadata_changes/comment_1_aa4955fd64ea5aa836f1a591e185c4a2._comment8
-rw-r--r--doc/forum/ignore_changes_made_by_a_remote.mdwn8
-rw-r--r--doc/forum/ignore_changes_made_by_a_remote/comment_1_825676069d2e1554499b76fd8c306c30._comment10
-rw-r--r--doc/forum/lost_in_walkthrough....mdwn (renamed from doc/forum/lost_in_walkthrough....txt)0
-rw-r--r--doc/forum/manual_update_of_.git__47__annex__47__objects.mdwn (renamed from doc/forum/manual_update_of_.git__47__annex__47__objects.txt)0
-rw-r--r--doc/forum/manual_update_of_.git__47__annex__47__objects/comment_2_a7bbf304b26650a786e358bdc01e3069._comment33
-rw-r--r--doc/forum/manual_update_of_.git__47__annex__47__objects/comment_3_a855096b683c4c4f84e72c797e065d59._comment12
-rw-r--r--doc/forum/multiple_repositories_single_backup.mdwn (renamed from doc/forum/multiple_repositories_single_backup.txt)0
-rw-r--r--doc/forum/multiple_repositories_single_backup/comment_2_bbe19eec0969385a0d4682bf9e9de21a._comment2
-rw-r--r--doc/forum/partial_synchronisation._android_phone.mdwn (renamed from doc/forum/partial_synchronisation._android_phone.txt)0
-rw-r--r--doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__.mdwn13
-rw-r--r--doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_1_7754e2cfb72b034effe8642c1b3e593e._comment11
-rw-r--r--doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_2_04e1da4352ef9f9be90253ea726e5f24._comment12
-rw-r--r--doc/forum/sync_between_indirect_and_direct_mode/comment_3_9acb237711669ec6046a8d07f9ed3b2c._comment8
-rw-r--r--doc/forum/telehash_syncing.mdwn10
-rw-r--r--doc/forum/unrelated_repositories_sync.mdwn15
-rw-r--r--doc/forum/unrelated_repositories_sync/comment_1_c899b7b05a96d14e25c2efadff3b4e52._comment10
-rw-r--r--doc/forum/view_from_numeric_values.mdwn9
-rw-r--r--doc/forum/view_from_numeric_values/comment_1_f3c440f3f0104002a0020ba96ddcf87b._comment11
-rw-r--r--doc/forum/view_from_numeric_values/comment_2_2414e1a8cfd154c339d8fc0e4a630ae9._comment12
-rw-r--r--doc/forum/view_from_numeric_values/comment_3_7879a11cc9767cdaac14f9993182dc25._comment13
-rw-r--r--doc/forum/view_from_numeric_values/comment_4_517c7659654a6fc608eb3332053df8a4._comment28
-rw-r--r--doc/forum/view_including_files_with_no_tags.mdwn5
-rw-r--r--doc/forum/view_including_files_with_no_tags/comment_1_b0aafc023fbec33af268576c4c199af3._comment24
-rw-r--r--doc/forum/view_including_files_with_no_tags/comment_2_5ae9d5308371bdb1f94342c9f9b01aff._comment8
-rw-r--r--doc/git-annex-shell.mdwn7
-rw-r--r--doc/git-annex.mdwn53
-rw-r--r--doc/install.mdwn1
-rw-r--r--doc/install/ArchLinux/comment_6_1d597d6a95f9c2df7dae6e98813e4865._comment36
-rw-r--r--doc/install/ArchLinux/comment_7_2d708977e2fad6b68803494576382df5._comment10
-rw-r--r--doc/install/ArchLinux/comment_8_5b5f5e0b64e5bfb1ea12e8b251c6fb5f._comment15
-rw-r--r--doc/install/Docker.mdwn27
-rw-r--r--doc/install/cabal/comment_33_8d4dfc33cada6091c30d3a43ce404b8b._comment21
-rw-r--r--doc/install/cabal/comment_34_38451e751add6daf479b559c4b6a7c61._comment8
-rw-r--r--doc/install/cabal/comment_35_4d44e4531e6686bd340f26836ad40026._comment8
-rw-r--r--doc/install/cabal/comment_5_8789fc27466714faa5a3a7a6b8ec6e5d._comment2
-rw-r--r--doc/install/fromscratch.mdwn59
-rw-r--r--doc/internals.mdwn16
-rw-r--r--doc/logo_16x16.pngbin0 -> 233 bytes
-rw-r--r--doc/logo_32x32.pngbin0 -> 473 bytes
-rw-r--r--doc/metadata.mdwn17
-rw-r--r--doc/metadata/comment_1_d367fdaf0425b59d694bf16059d47192._comment9
-rw-r--r--doc/metadata/comment_2_e15d2b5a405db4ccdb91d6aad4a22983._comment10
-rw-r--r--doc/news/version_5.20140210.mdwn42
-rw-r--r--doc/news/version_5.20140320.mdwn37
-rw-r--r--doc/preferred_content.mdwn226
-rw-r--r--doc/preferred_content/standard_groups.mdwn117
-rw-r--r--doc/preferred_content/standard_groups/comment_1_026e47e425d06c4b2580238b3187a379._comment13
-rw-r--r--doc/preferred_content/standard_groups/comment_2_460bae34ba7c05357318a202b2932d25._comment8
-rw-r--r--doc/related_software.mdwn2
-rw-r--r--doc/required_content.mdwn17
-rw-r--r--doc/special_remotes/tahoe.mdwn6
-rw-r--r--doc/tips/Synology_NAS_and_git_annex/comment_1_ef7e19f1fd2005eb7cc74509ffb92766._comment9
-rw-r--r--doc/tips/automatically_adding_metadata.mdwn2
-rw-r--r--doc/tips/automatically_adding_metadata/comment_2_bd64a53914107bc000c887b4d4bdf6af._comment12
-rw-r--r--doc/tips/file_manager_integration.mdwn100
-rw-r--r--doc/tips/googledriveannex/comment_1_ce7f2b04e83cc02d9dabb712f266e5cc._comment9
-rw-r--r--doc/tips/metadata_driven_views/comment_1_1d6793701fd8a1a66bae04662cf853ce._comment12
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_19_33c19097b6f2b48dfe09ec4c8d952d06._comment11
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_20_c82af00db3dd74ee9bfe12668e76e57b._comment13
-rw-r--r--doc/todo.mdwn2
-rw-r--r--doc/todo/Bittorrent-like_features.mdwn2
-rw-r--r--doc/todo/Bittorrent-like_features/comment_5_194dd0e8404ea72af9fb6ff34b994998._comment20
-rw-r--r--doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn (renamed from doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn)2
-rw-r--r--doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment (renamed from doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment)0
-rw-r--r--doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment (renamed from doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment)0
-rw-r--r--doc/todo/New_special_remote_suggeston_-_clean_directory.mdwn8
-rw-r--r--doc/todo/Views_Demo.mdwn2
-rw-r--r--doc/todo/Wishlist:_additional_environment_variables_for_hooks/comment_1_d82cbbb478a81a651fbe6cb8b71c1192._comment8
-rw-r--r--doc/todo/add_a_--branch_to_applicable_git-annex_commands.mdwn2
-rw-r--r--doc/todo/add_a_--branch_to_applicable_git-annex_commands/comment_1_3e0a1d1c41f317514dfc496f2274ad1c._comment10
-rw-r--r--doc/todo/add_an_icon_for_the_.desktop_file.mdwn2
-rw-r--r--doc/todo/assistant_parallel_file_transfers.mdwn (renamed from doc/todo/assistant_parallel_file_transfers.txt)0
-rw-r--r--doc/todo/clear_file_names_in_special_remotes.mdwn13
-rw-r--r--doc/todo/clear_file_names_in_special_remotes/comment_1_630f17c9a7ce9a77d5d5867a6e0c799b._comment8
-rw-r--r--doc/todo/clear_file_names_in_special_remotes/comment_2_823c279683ac3f39c921be3fcbf6bfe2._comment10
-rw-r--r--doc/todo/clear_file_names_in_special_remotes/comment_3_4704e465025b543e47c18d565abd2747._comment8
-rw-r--r--doc/todo/openwrt_package.mdwn (renamed from doc/todo/openwrt_package.txt)0
-rw-r--r--doc/todo/required_content.mdwn16
-rw-r--r--doc/todo/required_content/comment_2_132ec6378db63af6281569cf5748b9d3._comment14
-rw-r--r--doc/todo/tahoe_lfs_for_reals.mdwn6
-rw-r--r--doc/todo/union_mounting/comment_3_cf0a0d4fbd929f24f7056115b2acb7de._comment8
-rw-r--r--doc/todo/using_file_metadata_for_preferred___40__wanted__41___content.mdwn12
-rw-r--r--doc/todo/windows_support.mdwn38
-rw-r--r--doc/todo/wishlist:_An_option_like_--git-dir.mdwn2
-rw-r--r--doc/todo/wishlist:_a_spec.remote_for_network_directories_that_would_mount_them_whenever_needed___40__e.g.__44___with_WebDAV__41__.mdwn4
-rw-r--r--doc/todo/wishlist:_assistant_autostart_port_and_secret_configuration.mdwn3
-rw-r--r--doc/todo/wishlist:_define_remotes_that_must_have_all_files.mdwn4
-rw-r--r--doc/todo/wishlist:_git-annex_replicate.mdwn10
-rw-r--r--doc/todo/wishlist:_git_annex_diff/comment_1_16ccf2e1036d9e1a913db81988731b5a._comment8
-rw-r--r--doc/todo/wishlist:_make_partial_files_available_during_transfer/comment_2_8b1cfae6f2b61929a9c6f48ae63c921d._comment12
-rw-r--r--doc/todo/wishlist:_metadata_metadata_view.mdwn23
-rw-r--r--doc/todo/wishlist:_metadata_metadata_view/comment_1_79dbf48cf2e0d649f32bd077f0c9bc5a._comment8
-rw-r--r--doc/todo/wishlist:_metadata_metadata_view/comment_2_5763d0e403c476ac692c1cd50630f824._comment12
-rw-r--r--doc/todo/wishlist:_metadata_metadata_view/comment_3_797e6578c60d8e2ed1f61a8d6403575f._comment8
-rw-r--r--doc/todo/wishlist:_metadata_metadata_view/comment_4_d271fe711b3fe5ffeb52f1caf44622b3._comment10
-rw-r--r--doc/todo/wishlist:_spec.remotes_for_other_peer_network_data_stores___40__gnunet__44___freenet__41__/comment_3_b4ff519ece76c6c3fb29b981320e2e1c._comment10
-rw-r--r--doc/todo/wishlist:_special_remote_Ubuntu_One/comment_1_ab0c761030bc55e8fb75d1b344bb98b9._comment8
-rw-r--r--doc/todo/wishlist:alias_system/comment_1_5afad4b92f9a449d4a82a94ad31feec2._comment8
-rw-r--r--git-annex.cabal28
352 files changed, 6154 insertions, 972 deletions
diff --git a/Annex.hs b/Annex.hs
index 4e3efd0d0..f00276e2f 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -10,7 +10,6 @@
module Annex (
Annex,
AnnexState(..),
- PreferredContentMap,
new,
run,
eval,
@@ -60,7 +59,8 @@ import Types.FileMatcher
import Types.NumCopies
import Types.LockPool
import Types.MetaData
-import qualified Utility.Matcher
+import Types.DesktopNotify
+import Types.CleanupActions
import qualified Data.Map as M
import qualified Data.Set as S
import Utility.Quvi (QuviVersion)
@@ -79,9 +79,6 @@ newtype Annex a = Annex { runAnnex :: ReaderT (MVar AnnexState) IO a }
Applicative
)
-type Matcher a = Either [Utility.Matcher.Token a] (Utility.Matcher.Matcher a)
-type PreferredContentMap = M.Map UUID (Utility.Matcher.Matcher (S.Set UUID -> MatchInfo -> Annex Bool))
-
-- internal state storage
data AnnexState = AnnexState
{ repo :: Git.Repo
@@ -102,9 +99,10 @@ data AnnexState = AnnexState
, forcebackend :: Maybe String
, globalnumcopies :: Maybe NumCopies
, forcenumcopies :: Maybe NumCopies
- , limit :: Matcher (MatchInfo -> Annex Bool)
+ , limit :: ExpandableMatcher Annex
, uuidmap :: Maybe UUIDMap
- , preferredcontentmap :: Maybe PreferredContentMap
+ , preferredcontentmap :: Maybe (FileMatcherMap Annex)
+ , requiredcontentmap :: Maybe (FileMatcherMap Annex)
, shared :: Maybe SharedRepository
, forcetrust :: TrustMap
, trustmap :: Maybe TrustMap
@@ -114,13 +112,14 @@ data AnnexState = AnnexState
, flags :: M.Map String Bool
, fields :: M.Map String String
, modmeta :: [ModMeta]
- , cleanup :: M.Map String (Annex ())
+ , cleanup :: M.Map CleanupAction (Annex ())
, inodeschanged :: Maybe Bool
, useragent :: Maybe String
, errcounter :: Integer
, unusedkeys :: Maybe (S.Set Key)
, quviversion :: Maybe QuviVersion
, existinghooks :: M.Map Git.Hook.Hook Bool
+ , desktopnotify :: DesktopNotify
}
newState :: GitConfig -> Git.Repo -> AnnexState
@@ -143,9 +142,10 @@ newState c r = AnnexState
, forcebackend = Nothing
, globalnumcopies = Nothing
, forcenumcopies = Nothing
- , limit = Left []
+ , limit = BuildingMatcher []
, uuidmap = Nothing
, preferredcontentmap = Nothing
+ , requiredcontentmap = Nothing
, shared = Nothing
, forcetrust = M.empty
, trustmap = Nothing
@@ -162,6 +162,7 @@ newState c r = AnnexState
, unusedkeys = Nothing
, quviversion = Nothing
, existinghooks = M.empty
+ , desktopnotify = mempty
}
{- Makes an Annex state object for the specified git repo.
@@ -210,9 +211,9 @@ setField field value = changeState $ \s ->
s { fields = M.insertWith' const field value $ fields s }
{- Adds a cleanup action to perform. -}
-addCleanup :: String -> Annex () -> Annex ()
-addCleanup uid a = changeState $ \s ->
- s { cleanup = M.insertWith' const uid a $ cleanup s }
+addCleanup :: CleanupAction -> Annex () -> Annex ()
+addCleanup k a = changeState $ \s ->
+ s { cleanup = M.insertWith' const k a $ cleanup s }
{- Sets the type of output to emit. -}
setOutput :: OutputType -> Annex ()
diff --git a/Annex/Branch/Transitions.hs b/Annex/Branch/Transitions.hs
index 42c61d96a..5c2c14548 100644
--- a/Annex/Branch/Transitions.hs
+++ b/Annex/Branch/Transitions.hs
@@ -32,8 +32,12 @@ getTransitionCalculator ForgetDeadRemotes = Just dropDead
dropDead :: FilePath -> String -> TrustMap -> FileTransition
dropDead f content trustmap = case getLogVariety f of
- Just UUIDBasedLog -> ChangeFile $
- UUIDBased.showLog id $ dropDeadFromUUIDBasedLog trustmap $ UUIDBased.parseLog Just content
+ Just UUIDBasedLog
+ -- Don't remove the dead repo from the trust log,
+ -- because git remotes may still exist, and they need
+ -- to still know it's dead.
+ | f == trustLog -> PreserveFile
+ | otherwise -> ChangeFile $ UUIDBased.showLog id $ dropDeadFromUUIDBasedLog trustmap $ UUIDBased.parseLog Just content
Just NewUUIDBasedLog -> ChangeFile $
UUIDBased.showLogNew id $ dropDeadFromUUIDBasedLog trustmap $ UUIDBased.parseLogNew Just content
Just (PresenceLog _) ->
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
index fc722c8e7..6a778db03 100644
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -80,7 +80,7 @@ catKey = catKey' True
catKey' :: Bool -> Ref -> FileMode -> Annex (Maybe Key)
catKey' modeguaranteed ref mode
| isSymLink mode = do
- l <- fromInternalGitPath . encodeW8 . L.unpack <$> get
+ l <- fromInternalGitPath . decodeBS <$> get
return $ if isLinkToAnnex l
then fileKey $ takeFileName l
else Nothing
diff --git a/Annex/FileMatcher.hs b/Annex/FileMatcher.hs
index 750795280..da6a5e0e9 100644
--- a/Annex/FileMatcher.hs
+++ b/Annex/FileMatcher.hs
@@ -13,7 +13,6 @@ import Common.Annex
import Limit
import Utility.Matcher
import Types.Group
-import Types.Limit
import Logs.Group
import Logs.Remote
import Annex.UUID
@@ -25,12 +24,10 @@ import Types.Remote (RemoteConfig)
import Data.Either
import qualified Data.Set as S
-type FileMatcher = Matcher MatchFiles
-
-checkFileMatcher :: FileMatcher -> FilePath -> Annex Bool
+checkFileMatcher :: (FileMatcher Annex) -> FilePath -> Annex Bool
checkFileMatcher matcher file = checkMatcher matcher Nothing (Just file) S.empty True
-checkMatcher :: FileMatcher -> Maybe Key -> AssociatedFile -> AssumeNotPresent -> Bool -> Annex Bool
+checkMatcher :: (FileMatcher Annex) -> Maybe Key -> AssociatedFile -> AssumeNotPresent -> Bool -> Annex Bool
checkMatcher matcher mkey afile notpresent def
| isEmpty matcher = return def
| otherwise = case (mkey, afile) of
@@ -48,31 +45,35 @@ fileMatchInfo file = do
, relFile = file
}
-matchAll :: FileMatcher
+matchAll :: FileMatcher Annex
matchAll = generate []
-parsedToMatcher :: [Either String (Token MatchFiles)] -> Either String FileMatcher
+parsedToMatcher :: [Either String (Token (MatchFiles Annex))] -> Either String (FileMatcher Annex)
parsedToMatcher parsed = case partitionEithers parsed of
([], vs) -> Right $ generate vs
(es, _) -> Left $ unwords $ map ("Parse failure: " ++) es
-exprParser :: GroupMap -> M.Map UUID RemoteConfig -> Maybe UUID -> String -> [Either String (Token MatchFiles)]
-exprParser groupmap configmap mu expr =
+exprParser :: FileMatcher Annex -> FileMatcher Annex -> GroupMap -> M.Map UUID RemoteConfig -> Maybe UUID -> String -> [Either String (Token (MatchFiles Annex))]
+exprParser matchstandard matchgroupwanted groupmap configmap mu expr =
map parse $ tokenizeMatcher expr
where
- parse = parseToken
+ parse = parseToken
+ matchstandard
+ matchgroupwanted
(limitPresent mu)
(limitInDir preferreddir)
groupmap
preferreddir = fromMaybe "public" $
M.lookup "preferreddir" =<< (`M.lookup` configmap) =<< mu
-parseToken :: MkLimit -> MkLimit -> GroupMap -> String -> Either String (Token MatchFiles)
-parseToken checkpresent checkpreferreddir groupmap t
+parseToken :: FileMatcher Annex -> FileMatcher Annex -> MkLimit Annex -> MkLimit Annex -> GroupMap -> String -> Either String (Token (MatchFiles Annex))
+parseToken matchstandard matchgroupwanted checkpresent checkpreferreddir groupmap t
| t `elem` tokens = Right $ token t
+ | t == "standard" = call matchstandard
+ | t == "groupwanted" = call matchgroupwanted
| t == "present" = use checkpresent
| t == "inpreferreddir" = use checkpreferreddir
- | t == "unused" = Right (Operation limitUnused)
+ | t == "unused" = Right $ Operation limitUnused
| otherwise = maybe (Left $ "near " ++ show t) use $ M.lookup k $
M.fromList
[ ("include", limitInclude)
@@ -89,6 +90,8 @@ parseToken checkpresent checkpreferreddir groupmap t
where
(k, v) = separate (== '=') t
use a = Operation <$> a v
+ call sub = Right $ Operation $ \notpresent mi ->
+ matchMrun sub $ \a -> a notpresent mi
{- This is really dumb tokenization; there's no support for quoted values.
- Open and close parens are always treated as standalone tokens;
@@ -100,7 +103,7 @@ tokenizeMatcher = filter (not . null ) . concatMap splitparens . words
{- Generates a matcher for files large enough (or meeting other criteria)
- to be added to the annex, rather than directly to git. -}
-largeFilesMatcher :: Annex FileMatcher
+largeFilesMatcher :: Annex (FileMatcher Annex)
largeFilesMatcher = go =<< annexLargeFiles <$> Annex.getGitConfig
where
go Nothing = return matchAll
@@ -109,5 +112,5 @@ largeFilesMatcher = go =<< annexLargeFiles <$> Annex.getGitConfig
rc <- readRemoteLog
u <- getUUID
either badexpr return $
- parsedToMatcher $ exprParser gm rc (Just u) expr
+ parsedToMatcher $ exprParser matchAll matchAll gm rc (Just u) expr
badexpr e = error $ "bad annex.largefiles configuration: " ++ e
diff --git a/Annex/MetaData.hs b/Annex/MetaData.hs
index 68aef33f1..f382f0ab1 100644
--- a/Annex/MetaData.hs
+++ b/Annex/MetaData.hs
@@ -5,11 +5,15 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-module Annex.MetaData where
+module Annex.MetaData (
+ genMetaData,
+ module X
+) where
import Common.Annex
import qualified Annex
-import Types.MetaData
+import Types.MetaData as X
+import Annex.MetaData.StandardFields as X
import Logs.MetaData
import Annex.CatFile
@@ -19,15 +23,6 @@ import Data.Time.Calendar
import Data.Time.Clock
import Data.Time.Clock.POSIX
-tagMetaField :: MetaField
-tagMetaField = mkMetaFieldUnchecked "tag"
-
-yearMetaField :: MetaField
-yearMetaField = mkMetaFieldUnchecked "year"
-
-monthMetaField :: MetaField
-monthMetaField = mkMetaFieldUnchecked "month"
-
{- Adds metadata for a file that has just been ingested into the
- annex, but has not yet been committed to git.
-
diff --git a/Annex/MetaData/StandardFields.hs b/Annex/MetaData/StandardFields.hs
new file mode 100644
index 000000000..d41fb1506
--- /dev/null
+++ b/Annex/MetaData/StandardFields.hs
@@ -0,0 +1,47 @@
+{- git-annex metadata, standard fields
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Annex.MetaData.StandardFields (
+ tagMetaField,
+ yearMetaField,
+ monthMetaField,
+ lastChangedField,
+ mkLastChangedField,
+ isLastChangedField
+) where
+
+import Types.MetaData
+
+import Data.List
+
+tagMetaField :: MetaField
+tagMetaField = mkMetaFieldUnchecked "tag"
+
+yearMetaField :: MetaField
+yearMetaField = mkMetaFieldUnchecked "year"
+
+monthMetaField :: MetaField
+monthMetaField = mkMetaFieldUnchecked "month"
+
+lastChangedField :: MetaField
+lastChangedField = mkMetaFieldUnchecked lastchanged
+
+mkLastChangedField :: MetaField -> MetaField
+mkLastChangedField f = mkMetaFieldUnchecked (fromMetaField f ++ lastchangedSuffix)
+
+isLastChangedField :: MetaField -> Bool
+isLastChangedField f
+ | f == lastChangedField = True
+ | otherwise = lastchanged `isSuffixOf` s && s /= lastchangedSuffix
+ where
+ s = fromMetaField f
+
+lastchanged :: String
+lastchanged = "lastchanged"
+
+lastchangedSuffix :: String
+lastchangedSuffix = "-lastchanged"
diff --git a/Annex/Notification.hs b/Annex/Notification.hs
new file mode 100644
index 000000000..06a099888
--- /dev/null
+++ b/Annex/Notification.hs
@@ -0,0 +1,81 @@
+{- git-annex desktop notifications
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Annex.Notification where
+
+import Common.Annex
+import Logs.Transfer
+#ifdef WITH_DBUS_NOTIFICATIONS
+import qualified Annex
+import Types.DesktopNotify
+import qualified DBus.Notify as Notify
+import qualified DBus.Client
+#endif
+
+-- Witness that notification has happened.
+data NotifyWitness = NotifyWitness
+
+{- Wrap around an action that performs a transfer, which may run multiple
+ - attempts. Displays notification when supported and when the user asked
+ - for it. -}
+notifyTransfer :: Direction -> Maybe FilePath -> (NotifyWitness -> Annex Bool) -> Annex Bool
+notifyTransfer _ Nothing a = a NotifyWitness
+#ifdef WITH_DBUS_NOTIFICATIONS
+notifyTransfer direction (Just f) a = do
+ wanted <- Annex.getState Annex.desktopnotify
+ let action = if direction == Upload then "uploading" else "downloading"
+ let basedesc = action ++ " " ++ f
+ let startdesc = "started " ++ basedesc
+ let enddesc ok = if ok
+ then "finished " ++ basedesc
+ else basedesc ++ " failed"
+ if (notifyStart wanted || notifyFinish wanted)
+ then do
+ client <- liftIO DBus.Client.connectSession
+ startnotification <- liftIO $ if notifyStart wanted
+ then Just <$> Notify.notify client (mkNote startdesc)
+ else pure Nothing
+ ok <- a NotifyWitness
+ when (notifyFinish wanted) $ liftIO $ void $ maybe
+ (Notify.notify client $ mkNote $ enddesc ok)
+ (\n -> Notify.replace client n $ mkNote $ enddesc ok)
+ startnotification
+ return ok
+ else a NotifyWitness
+#else
+notifyTransfer _ (Just _) a = do a NotifyWitness
+#endif
+
+notifyDrop :: Maybe FilePath -> Bool -> Annex ()
+notifyDrop Nothing _ = noop
+#ifdef WITH_DBUS_NOTIFICATIONS
+notifyDrop (Just f) ok = do
+ wanted <- Annex.getState Annex.desktopnotify
+ when (notifyFinish wanted) $ liftIO $ do
+ client <- DBus.Client.connectSession
+ let msg = if ok
+ then "dropped " ++ f
+ else "failed to drop" ++ f
+ void $ Notify.notify client (mkNote msg)
+#else
+notifyDrop (Just _) _ = noop
+#endif
+
+#ifdef WITH_DBUS_NOTIFICATIONS
+mkNote :: String -> Notify.Note
+mkNote desc = Notify.blankNote
+ { Notify.appName = "git-annex"
+ , Notify.body = Just $ Notify.Text desc
+ , Notify.hints =
+ [ Notify.Category Notify.Transfer
+ , Notify.Urgency Notify.Low
+ , Notify.SuppressSound True
+ ]
+ }
+#endif
diff --git a/Annex/Ssh.hs b/Annex/Ssh.hs
index aedf418f8..bd10a40d4 100644
--- a/Annex/Ssh.hs
+++ b/Annex/Ssh.hs
@@ -9,7 +9,6 @@
module Annex.Ssh (
sshCachingOptions,
- sshCleanup,
sshCacheDir,
sshReadPort,
) where
@@ -24,6 +23,7 @@ import qualified Build.SysConfig as SysConfig
import qualified Annex
import Config
import Utility.Env
+import Types.CleanupActions
#ifndef mingw32_HOST_OS
import Annex.Perms
#endif
@@ -31,7 +31,9 @@ import Annex.Perms
{- Generates parameters to ssh to a given host (or user@host) on a given
- port, with connection caching. -}
sshCachingOptions :: (String, Maybe Integer) -> [CommandParam] -> Annex [CommandParam]
-sshCachingOptions (host, port) opts = go =<< sshInfo (host, port)
+sshCachingOptions (host, port) opts = do
+ Annex.addCleanup SshCachingCleanup sshCleanup
+ go =<< sshInfo (host, port)
where
go (Nothing, params) = ret params
go (Just socketfile, params) = do
@@ -144,8 +146,9 @@ sshCleanup = go =<< sshCacheDir
withQuietOutput createProcessSuccess $
(proc "ssh" $ toCommand $
[ Params "-O stop"
- ] ++ params ++ [Param "any"])
+ ] ++ params ++ [Param "localhost"])
{ cwd = Just dir }
+ liftIO $ nukeFile socketfile
-- Cannot remove the lock file; other processes may
-- be waiting on our exclusive lock to use it.
diff --git a/Annex/Transfer.hs b/Annex/Transfer.hs
new file mode 100644
index 000000000..df5aba09c
--- /dev/null
+++ b/Annex/Transfer.hs
@@ -0,0 +1,131 @@
+{- git-annex transfers
+ -
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Annex.Transfer (
+ module X,
+ upload,
+ download,
+ runTransfer,
+ noRetry,
+ forwardRetry,
+) where
+
+import Common.Annex
+import Logs.Transfer as X
+import Annex.Notification as X
+import Annex.Perms
+import Annex.Exception
+import Utility.Metered
+#ifdef mingw32_HOST_OS
+import Utility.WinLock
+#endif
+
+import Control.Concurrent
+
+upload :: UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex Bool) -> NotifyWitness -> Annex Bool
+upload u key f d a _witness = runTransfer (Transfer Upload u key) f d a
+
+download :: UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex Bool) -> NotifyWitness -> Annex Bool
+download u key f d a _witness = runTransfer (Transfer Download u key) f d a
+
+{- Runs a transfer action. Creates and locks the lock file while the
+ - action is running, and stores info in the transfer information
+ - file.
+ -
+ - If the transfer action returns False, the transfer info is
+ - left in the failedTransferDir.
+ -
+ - If the transfer is already in progress, returns False.
+ -
+ - An upload can be run from a read-only filesystem, and in this case
+ - no transfer information or lock file is used.
+ -}
+runTransfer :: Transfer -> Maybe FilePath -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
+runTransfer t file shouldretry a = do
+ info <- liftIO $ startTransferInfo file
+ (meter, tfile, metervar) <- mkProgressUpdater t info
+ mode <- annexFileMode
+ (fd, inprogress) <- liftIO $ prep tfile mode info
+ if inprogress
+ then do
+ showNote "transfer already in progress"
+ return False
+ else do
+ ok <- retry info metervar $
+ bracketIO (return fd) (cleanup tfile) (const $ a meter)
+ unless ok $ recordFailedTransfer t info
+ return ok
+ where
+#ifndef mingw32_HOST_OS
+ prep tfile mode info = do
+ mfd <- catchMaybeIO $
+ openFd (transferLockFile tfile) ReadWrite (Just mode)
+ defaultFileFlags { trunc = True }
+ case mfd of
+ Nothing -> return (Nothing, False)
+ Just fd -> do
+ locked <- catchMaybeIO $
+ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
+ if isNothing locked
+ then return (Nothing, True)
+ else do
+ void $ tryIO $ writeTransferInfoFile info tfile
+ return (mfd, False)
+#else
+ prep tfile _mode info = do
+ v <- catchMaybeIO $ lockExclusive (transferLockFile tfile)
+ case v of
+ Nothing -> return (Nothing, False)
+ Just Nothing -> return (Nothing, True)
+ Just (Just lockhandle) -> do
+ void $ tryIO $ writeTransferInfoFile info tfile
+ return (Just lockhandle, False)
+#endif
+ cleanup _ Nothing = noop
+ cleanup tfile (Just lockhandle) = do
+ void $ tryIO $ removeFile tfile
+#ifndef mingw32_HOST_OS
+ void $ tryIO $ removeFile $ transferLockFile tfile
+ closeFd lockhandle
+#else
+ {- Windows cannot delete the lockfile until the lock
+ - is closed. So it's possible to race with another
+ - process that takes the lock before it's removed,
+ - so ignore failure to remove.
+ -}
+ dropLock lockhandle
+ void $ tryIO $ removeFile $ transferLockFile tfile
+#endif
+ retry oldinfo metervar run = do
+ v <- tryAnnex run
+ case v of
+ Right b -> return b
+ Left _ -> do
+ b <- getbytescomplete metervar
+ let newinfo = oldinfo { bytesComplete = Just b }
+ if shouldretry oldinfo newinfo
+ then retry newinfo metervar run
+ else return False
+ getbytescomplete metervar
+ | transferDirection t == Upload =
+ liftIO $ readMVar metervar
+ | otherwise = do
+ f <- fromRepo $ gitAnnexTmpObjectLocation (transferKey t)
+ liftIO $ catchDefaultIO 0 $
+ fromIntegral . fileSize <$> getFileStatus f
+
+type RetryDecider = TransferInfo -> TransferInfo -> Bool
+
+noRetry :: RetryDecider
+noRetry _ _ = False
+
+{- Retries a transfer when it fails, as long as the failed transfer managed
+ - to send some data. -}
+forwardRetry :: RetryDecider
+forwardRetry old new = bytesComplete old < bytesComplete new
diff --git a/Assistant/Alert/Utility.hs b/Assistant/Alert/Utility.hs
index 73843be4c..be631e999 100644
--- a/Assistant/Alert/Utility.hs
+++ b/Assistant/Alert/Utility.hs
@@ -14,7 +14,6 @@ import Utility.Tense
import qualified Data.Text as T
import Data.Text (Text)
import qualified Data.Map as M
-import Data.Monoid
{- This is as many alerts as it makes sense to display at a time.
- A display might be smaller, or larger, the point is to not overwhelm the
diff --git a/Assistant/Install.hs b/Assistant/Install.hs
index d29cefb8c..4d02c0ece 100644
--- a/Assistant/Install.hs
+++ b/Assistant/Install.hs
@@ -35,11 +35,14 @@ standaloneAppBase = getEnv "GIT_ANNEX_APP_BASE"
-
- Note that this is done every time it's started, so if the user moves
- it around, the paths this sets up won't break.
+ -
+ - Nautilus hook script installation is done even for packaged apps,
+ - since it has to go into the user's home directory.
-}
ensureInstalled :: IO ()
ensureInstalled = go =<< standaloneAppBase
where
- go Nothing = noop
+ go Nothing = installNautilus "git-annex"
go (Just base) = do
let program = base </> "git-annex"
programfile <- programFile
@@ -78,6 +81,32 @@ ensureInstalled = go =<< standaloneAppBase
viaTmp writeFile shim content
modifyFileMode shim $ addModes [ownerExecuteMode]
+ installNautilus program
+
+installNautilus :: FilePath -> IO ()
+#ifdef linux_HOST_OS
+installNautilus program = do
+ scriptdir <- (\d -> d </> "nautilus" </> "scripts") <$> userDataDir
+ genscript scriptdir "get"
+ genscript scriptdir "drop"
+ where
+ genscript scriptdir action =
+ installscript (scriptdir </> scriptname action) $ unlines
+ [ shebang_local
+ , autoaddedcomment
+ , "exec " ++ program ++ " " ++ action ++ " --notify-start --notify-finish -- \"$@\""
+ ]
+ scriptname action = "git-annex " ++ action
+ installscript f c = whenM (safetoinstallscript f) $ do
+ writeFile f c
+ modifyFileMode f $ addModes [ownerExecuteMode]
+ safetoinstallscript f = catchDefaultIO True $
+ elem autoaddedcomment . lines <$> readFileStrict f
+ autoaddedcomment = "# Automatically added by git-annex, do not edit. (To disable, chmod 600 this file.)"
+#else
+installNautilus _ = noop
+#endif
+
{- Returns a cleaned up environment that lacks settings used to make the
- standalone builds use their bundled libraries and programs.
- Useful when calling programs not included in the standalone builds.
diff --git a/Assistant/Install/Menu.hs b/Assistant/Install/Menu.hs
index 22ca1da9c..d095cdd88 100644
--- a/Assistant/Install/Menu.hs
+++ b/Assistant/Install/Menu.hs
@@ -21,7 +21,7 @@ installMenu command menufile iconsrcdir icondir = do
writeDesktopMenuFile (fdoDesktopMenu command) menufile
installIcon (iconsrcdir </> "logo.svg") $
iconFilePath (iconBaseName ++ ".svg") "scalable" icondir
- installIcon (iconsrcdir </> "favicon.png") $
+ installIcon (iconsrcdir </> "logo_16x16.png") $
iconFilePath (iconBaseName ++ ".png") "16x16" icondir
#endif
diff --git a/Assistant/Ssh.hs b/Assistant/Ssh.hs
index acb2fc11c..4dd32f7d9 100644
--- a/Assistant/Ssh.hs
+++ b/Assistant/Ssh.hs
@@ -197,7 +197,7 @@ authorizedKeysLine gitannexshellonly dir pubkey
- long perl script. -}
| otherwise = pubkey
where
- limitcommand = "command=\"GIT_ANNEX_SHELL_DIRECTORY="++shellEscape dir++" ~/.ssh/git-annex-shell\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty "
+ limitcommand = "command=\"env GIT_ANNEX_SHELL_DIRECTORY="++shellEscape dir++" ~/.ssh/git-annex-shell\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty "
{- Generates a ssh key pair. -}
genSshKeyPair :: IO SshKeyPair
diff --git a/Assistant/Threads/ConfigMonitor.hs b/Assistant/Threads/ConfigMonitor.hs
index a92c7d785..d02e53db5 100644
--- a/Assistant/Threads/ConfigMonitor.hs
+++ b/Assistant/Threads/ConfigMonitor.hs
@@ -62,15 +62,17 @@ configFilesActions =
, (groupLog, void $ liftAnnex groupMapLoad)
, (numcopiesLog, void $ liftAnnex globalNumCopiesLoad)
, (scheduleLog, void updateScheduleLog)
- -- Preferred content settings depend on most of the other configs,
- -- so will be reloaded whenever any configs change.
+ -- Preferred and required content settings depend on most of the
+ -- other configs, so will be reloaded whenever any configs change.
, (preferredContentLog, noop)
+ , (requiredContentLog, noop)
+ , (groupPreferredContentLog, noop)
]
reloadConfigs :: Configs -> Assistant ()
reloadConfigs changedconfigs = do
sequence_ as
- void $ liftAnnex preferredContentMapLoad
+ void $ liftAnnex preferredRequiredMapsLoad
{- Changes to the remote log, or the trust log, can affect the
- syncRemotes list. Changes to the uuid log may affect its
- display so are also included. -}
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
index 8a8e8faf0..97ccf083e 100644
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -35,6 +35,7 @@ import Annex.CatFile
import Annex.CheckIgnore
import Annex.Link
import Annex.FileMatcher
+import Types.FileMatcher
import Annex.ReplaceFile
import Git.Types
import Config
@@ -196,7 +197,7 @@ runHandler handler file filestatus = void $ do
| otherwise = f
{- Small files are added to git as-is, while large ones go into the annex. -}
-add :: FileMatcher -> FilePath -> Assistant (Maybe Change)
+add :: FileMatcher Annex -> FilePath -> Assistant (Maybe Change)
add bigfilematcher file = ifM (liftAnnex $ checkFileMatcher bigfilematcher file)
( pendingAddChange file
, do
@@ -205,7 +206,7 @@ add bigfilematcher file = ifM (liftAnnex $ checkFileMatcher bigfilematcher file)
madeChange file AddFileChange
)
-onAdd :: FileMatcher -> Handler
+onAdd :: FileMatcher Annex -> Handler
onAdd matcher file filestatus
| maybe False isRegularFile filestatus =
unlessIgnored file $
@@ -218,7 +219,7 @@ shouldRestage ds = scanComplete ds || forceRestage ds
{- In direct mode, add events are received for both new files, and
- modified existing files.
-}
-onAddDirect :: Bool -> FileMatcher -> Handler
+onAddDirect :: Bool -> FileMatcher Annex -> Handler
onAddDirect symlinkssupported matcher file fs = do
v <- liftAnnex $ catKeyFile file
case (v, fs) of
diff --git a/Assistant/Threads/WebApp.hs b/Assistant/Threads/WebApp.hs
index 7b24ccea1..8d977194b 100644
--- a/Assistant/Threads/WebApp.hs
+++ b/Assistant/Threads/WebApp.hs
@@ -73,7 +73,7 @@ webAppThread assistantdata urlrenderer noannex cannotrun postfirstrun listenhost
#endif
webapp <- WebApp
<$> pure assistantdata
- <*> (pack <$> genRandomToken)
+ <*> genAuthToken
<*> getreldir
<*> pure staticRoutes
<*> pure postfirstrun
@@ -125,9 +125,13 @@ myUrl tlssettings webapp addr = unpack $ yesodRender webapp urlbase DashboardR [
getTlsSettings :: Annex (Maybe TLS.TLSSettings)
getTlsSettings = do
+#ifdef WITH_WEBAPP_SECURE
cert <- fromRepo gitAnnexWebCertificate
privkey <- fromRepo gitAnnexWebPrivKey
ifM (liftIO $ allM doesFileExist [cert, privkey])
( return $ Just $ TLS.tlsSettings cert privkey
, return Nothing
)
+#else
+ return Nothing
+#endif
diff --git a/Build/NullSoftInstaller.hs b/Build/NullSoftInstaller.hs
index 7cfb08f27..b3d323ce2 100644
--- a/Build/NullSoftInstaller.hs
+++ b/Build/NullSoftInstaller.hs
@@ -67,7 +67,7 @@ uninstaller :: FilePath
uninstaller = "git-annex-uninstall.exe"
gitInstallDir :: Exp FilePath
-gitInstallDir = fromString "$PROGRAMFILES\\Git\\cmd"
+gitInstallDir = fromString "$PROGRAMFILES\\Git\\bin"
startMenuItem :: Exp FilePath
startMenuItem = "$SMPROGRAMS/git-annex.lnk"
diff --git a/BuildFlags.hs b/BuildFlags.hs
index d5c98aa4e..59a060cb5 100644
--- a/BuildFlags.hs
+++ b/BuildFlags.hs
@@ -22,8 +22,8 @@ buildFlags = filter (not . null)
#else
#warning Building without the webapp. You probably need to install Yesod..
#endif
-#ifdef WITH_WEBAPP_HTTPS
- , "Webapp-https"
+#ifdef WITH_WEBAPP_SECURE
+ , "Webapp-secure"
#endif
#ifdef WITH_PAIRING
, "Pairing"
@@ -57,6 +57,9 @@ buildFlags = filter (not . null)
#ifdef WITH_DBUS
, "DBus"
#endif
+#ifdef WITH_DESKTOP_NOTIFY
+ , "DesktopNotify"
+#endif
#ifdef WITH_XMPP
, "XMPP"
#else
diff --git a/CmdLine.hs b/CmdLine.hs
index a920898dc..a165b041a 100644
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -26,7 +26,6 @@ import qualified Annex
import qualified Git
import qualified Git.AutoCorrect
import Annex.Content
-import Annex.Ssh
import Annex.Environment
import Command
import Types.Messages
@@ -107,4 +106,3 @@ shutdown nocommit = do
saveState nocommit
sequence_ =<< M.elems <$> Annex.getState Annex.cleanup
liftIO reapZombies -- zombies from long-running git processes
- sshCleanup -- ssh connection caching
diff --git a/CmdLine/Option.hs b/CmdLine/Option.hs
index 915b06849..ce44d2ace 100644
--- a/CmdLine/Option.hs
+++ b/CmdLine/Option.hs
@@ -20,6 +20,7 @@ import System.Console.GetOpt
import Common.Annex
import qualified Annex
import Types.Messages
+import Types.DesktopNotify
import Limit
import CmdLine.Usage
@@ -41,6 +42,10 @@ commonOptions =
"don't show debug messages"
, Option ['b'] ["backend"] (ReqArg setforcebackend paramName)
"specify key-value backend to use"
+ , Option [] ["notify-finish"] (NoArg (setdesktopnotify mkNotifyFinish))
+ "show desktop notification after transfer finishes"
+ , Option [] ["notify-start"] (NoArg (setdesktopnotify mkNotifyStart))
+ "show desktop notification after transfer completes"
]
where
setforce v = Annex.changeState $ \s -> s { Annex.force = v }
@@ -49,6 +54,7 @@ commonOptions =
setforcebackend v = Annex.changeState $ \s -> s { Annex.forcebackend = Just v }
setdebug = Annex.changeGitConfig $ \c -> c { annexDebug = True }
unsetdebug = Annex.changeGitConfig $ \c -> c { annexDebug = False }
+ setdesktopnotify v = Annex.changeState $ \s -> s { Annex.desktopnotify = Annex.desktopnotify s <> v }
matcherOptions :: [Option]
matcherOptions =
diff --git a/CmdLine/Seek.hs b/CmdLine/Seek.hs
index e95b9f005..abbe52af8 100644
--- a/CmdLine/Seek.hs
+++ b/CmdLine/Seek.hs
@@ -30,14 +30,15 @@ withFilesInGit :: (FilePath -> CommandStart) -> CommandSeek
withFilesInGit a params = seekActions $ prepFiltered a $
seekHelper LsFiles.inRepo params
-withFilesNotInGit :: (FilePath -> CommandStart) -> CommandSeek
-withFilesNotInGit a params = do
- {- dotfiles are not acted on unless explicitly listed -}
- files <- filter (not . dotfile) <$>
- seekunless (null ps && not (null params)) ps
- dotfiles <- seekunless (null dotps) dotps
- seekActions $ prepFiltered a $
- return $ concat $ segmentPaths params (files++dotfiles)
+withFilesNotInGit :: Bool -> (FilePath -> CommandStart) -> CommandSeek
+withFilesNotInGit skipdotfiles a params
+ | skipdotfiles = do
+ {- dotfiles are not acted on unless explicitly listed -}
+ files <- filter (not . dotfile) <$>
+ seekunless (null ps && not (null params)) ps
+ dotfiles <- seekunless (null dotps) dotps
+ go (files++dotfiles)
+ | otherwise = go =<< seekunless False params
where
(dotps, ps) = partition dotfile params
seekunless True _ = return []
@@ -45,6 +46,8 @@ withFilesNotInGit a params = do
force <- Annex.getState Annex.force
g <- gitRepo
liftIO $ Git.Command.leaveZombie <$> LsFiles.notInRepo force l g
+ go l = seekActions $ prepFiltered a $
+ return $ concat $ segmentPaths params l
withPathContents :: ((FilePath, FilePath) -> CommandStart) -> CommandSeek
withPathContents a params = seekActions $
diff --git a/CmdLine/Usage.hs b/CmdLine/Usage.hs
index 64b512144..1d0bba954 100644
--- a/CmdLine/Usage.hs
+++ b/CmdLine/Usage.hs
@@ -73,6 +73,8 @@ paramNumRange :: String
paramNumRange = "NUM|RANGE"
paramRemote :: String
paramRemote = "REMOTE"
+paramField :: String
+paramField = "FIELD"
paramGlob :: String
paramGlob = "GLOB"
paramName :: String
diff --git a/Command/Add.hs b/Command/Add.hs
index 3361a430a..f9e2b3342 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -34,8 +34,12 @@ import Annex.ReplaceFile
import Utility.Tmp
def :: [Command]
-def = [notBareRepo $ command "add" paramPaths seek SectionCommon
- "add files to annex"]
+def = [notBareRepo $ withOptions [includeDotFilesOption] $
+ command "add" paramPaths seek SectionCommon
+ "add files to annex"]
+
+includeDotFilesOption :: Option
+includeDotFilesOption = flagOption [] "include-dotfiles" "don't skip dotfiles"
{- Add acts on both files not checked into git yet, and unlocked files.
-
@@ -47,7 +51,8 @@ seek ps = do
( start file
, stop
)
- go withFilesNotInGit
+ skipdotfiles <- not <$> Annex.getFlag (optionName includeDotFilesOption)
+ go $ withFilesNotInGit skipdotfiles
ifM isDirect
( go withFilesMaybeModified
, go withFilesUnlocked
@@ -93,12 +98,15 @@ start file = ifAnnexed file addpresent add
- Lockdown can fail if a file gets deleted, and Nothing will be returned.
-}
lockDown :: FilePath -> Annex (Maybe KeySource)
-lockDown file = ifM crippledFileSystem
- ( liftIO $ catchMaybeIO nohardlink
- , do
+lockDown = either (\e -> showErr e >> return Nothing) (return . Just) <=< lockDown'
+
+lockDown' :: FilePath -> Annex (Either IOException KeySource)
+lockDown' file = ifM crippledFileSystem
+ ( liftIO $ tryIO nohardlink
+ , tryAnnexIO $ do
tmp <- fromRepo gitAnnexTmpMiscDir
createAnnexDirectory tmp
- eitherToMaybe <$> tryAnnexIO (go tmp)
+ go tmp
)
where
{- In indirect mode, the write bit is removed from the file as part
diff --git a/Command/AddUrl.hs b/Command/AddUrl.hs
index a0978a88d..b108be507 100644
--- a/Command/AddUrl.hs
+++ b/Command/AddUrl.hs
@@ -26,7 +26,7 @@ import Types.KeySource
import Config
import Annex.Content.Direct
import Logs.Location
-import qualified Logs.Transfer as Transfer
+import qualified Annex.Transfer as Transfer
#ifdef WITH_QUVI
import Annex.Quvi
import qualified Utility.Quvi as Quvi
@@ -116,9 +116,10 @@ addUrlFileQuvi relaxed quviurl videourl file = do
prepGetViaTmpChecked sizedkey $ do
tmp <- fromRepo $ gitAnnexTmpObjectLocation key
showOutput
- ok <- Transfer.download webUUID key (Just file) Transfer.forwardRetry $ const $ do
- liftIO $ createDirectoryIfMissing True (parentDir tmp)
- downloadUrl [videourl] tmp
+ ok <- Transfer.notifyTransfer Transfer.Download (Just file) $
+ Transfer.download webUUID key (Just file) Transfer.forwardRetry $ const $ do
+ liftIO $ createDirectoryIfMissing True (parentDir tmp)
+ downloadUrl [videourl] tmp
if ok
then cleanup quviurl file key (Just tmp)
else return False
@@ -133,17 +134,20 @@ perform relaxed url file = ifAnnexed file addurl geturl
| relaxed = do
setUrlPresent key url
next $ return True
- | otherwise = do
- (exists, samesize) <- Url.withUrlOptions $ Url.check url (keySize key)
- if exists && samesize
- then do
- setUrlPresent key url
- next $ return True
- else do
- warning $ if exists
- then "url does not have expected file size (use --relaxed to bypass this check) " ++ url
- else "failed to verify url exists: " ++ url
- stop
+ | otherwise = ifM (elem url <$> getUrls key)
+ ( stop
+ , do
+ (exists, samesize) <- Url.withUrlOptions $ Url.check url (keySize key)
+ if exists && samesize
+ then do
+ setUrlPresent key url
+ next $ return True
+ else do
+ warning $ "while adding a new url to an already annexed file, " ++ if exists
+ then "url does not have expected file size (use --relaxed to bypass this check) " ++ url
+ else "failed to verify url exists: " ++ url
+ stop
+ )
addUrlFile :: Bool -> URLString -> FilePath -> Annex Bool
addUrlFile relaxed url file = do
@@ -179,7 +183,7 @@ download url file = do
, return False
)
where
- runtransfer dummykey tmp =
+ runtransfer dummykey tmp = Transfer.notifyTransfer Transfer.Download (Just file) $
Transfer.download webUUID dummykey (Just file) Transfer.forwardRetry $ const $ do
liftIO $ createDirectoryIfMissing True (parentDir tmp)
downloadUrl [url] tmp
diff --git a/Command/ConfigList.hs b/Command/ConfigList.hs
index 58b738864..219685c21 100644
--- a/Command/ConfigList.hs
+++ b/Command/ConfigList.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2010 Joey Hess <joey@kitenet.net>
+ - Copyright 2010-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -10,6 +10,8 @@ module Command.ConfigList where
import Common.Annex
import Command
import Annex.UUID
+import Annex.Init
+import qualified Annex.Branch
import qualified Git.Config
import Remote.GCrypt (coreGCryptId)
@@ -22,9 +24,23 @@ seek = withNothing start
start :: CommandStart
start = do
- u <- getUUID
+ u <- findOrGenUUID
showConfig "annex.uuid" $ fromUUID u
showConfig coreGCryptId =<< fromRepo (Git.Config.get coreGCryptId "")
stop
where
showConfig k v = liftIO $ putStrLn $ k ++ "=" ++ v
+
+{- The repository may not yet have a UUID; automatically initialize it
+ - when there's a git-annex branch available. -}
+findOrGenUUID :: Annex UUID
+findOrGenUUID = do
+ u <- getUUID
+ if u /= NoUUID
+ then return u
+ else ifM Annex.Branch.hasSibling
+ ( do
+ initialize Nothing
+ getUUID
+ , return NoUUID
+ )
diff --git a/Command/Drop.hs b/Command/Drop.hs
index d29195b05..269c4c26b 100644
--- a/Command/Drop.hs
+++ b/Command/Drop.hs
@@ -14,9 +14,13 @@ import qualified Annex
import Annex.UUID
import Logs.Location
import Logs.Trust
+import Logs.PreferredContent
import Config.NumCopies
import Annex.Content
import Annex.Wanted
+import Annex.Notification
+
+import qualified Data.Set as S
def :: [Command]
def = [withOptions [dropFromOption] $ command "drop" paramPaths seek
@@ -44,27 +48,34 @@ start from file (key, _) = checkDropAuto from file key $ \numcopies ->
startLocal :: AssociatedFile -> NumCopies -> Key -> Maybe Remote -> CommandStart
startLocal afile numcopies key knownpresentremote = stopUnless (inAnnex key) $ do
showStart' "drop" key afile
- next $ performLocal key numcopies knownpresentremote
+ next $ performLocal key afile numcopies knownpresentremote
startRemote :: AssociatedFile -> NumCopies -> Key -> Remote -> CommandStart
startRemote afile numcopies key remote = do
showStart' ("drop " ++ Remote.name remote) key afile
- next $ performRemote key numcopies remote
+ next $ performRemote key afile numcopies remote
-performLocal :: Key -> NumCopies -> Maybe Remote -> CommandPerform
-performLocal key numcopies knownpresentremote = lockContent key $ do
+performLocal :: Key -> AssociatedFile -> NumCopies -> Maybe Remote -> CommandPerform
+performLocal key afile numcopies knownpresentremote = lockContent key $ do
(remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
let trusteduuids' = case knownpresentremote of
Nothing -> trusteduuids
Just r -> nub (Remote.uuid r:trusteduuids)
untrusteduuids <- trustGet UnTrusted
let tocheck = Remote.remotesWithoutUUID remotes (trusteduuids'++untrusteduuids)
- stopUnless (canDropKey key numcopies trusteduuids' tocheck []) $ do
- removeAnnex key
- next $ cleanupLocal key
-
-performRemote :: Key -> NumCopies -> Remote -> CommandPerform
-performRemote key numcopies remote = lockContent key $ do
+ u <- getUUID
+ ifM (canDrop u key afile numcopies trusteduuids' tocheck [])
+ ( do
+ removeAnnex key
+ notifyDrop afile True
+ next $ cleanupLocal key
+ , do
+ notifyDrop afile False
+ stop
+ )
+
+performRemote :: Key -> AssociatedFile -> NumCopies -> Remote -> CommandPerform
+performRemote key afile numcopies remote = lockContent key $ do
-- Filter the remote it's being dropped from out of the lists of
-- places assumed to have the key, and places to check.
-- When the local repo has the key, that's one additional copy.
@@ -76,7 +87,7 @@ performRemote key numcopies remote = lockContent key $ do
untrusteduuids <- trustGet UnTrusted
let tocheck = filter (/= remote) $
Remote.remotesWithoutUUID remotes (have++untrusteduuids)
- stopUnless (canDropKey key numcopies have tocheck [uuid]) $ do
+ stopUnless (canDrop uuid key afile numcopies have tocheck [uuid]) $ do
ok <- Remote.removeKey remote key
next $ cleanupRemote key remote ok
where
@@ -95,13 +106,19 @@ cleanupRemote key remote ok = do
{- Checks specified remotes to verify that enough copies of a key exist to
- allow it to be safely removed (with no data loss). Can be provided with
- - some locations where the key is known/assumed to be present. -}
-canDropKey :: Key -> NumCopies -> [UUID] -> [Remote] -> [UUID] -> Annex Bool
-canDropKey key numcopies have check skip = do
- force <- Annex.getState Annex.force
- if force || numcopies == NumCopies 0
- then return True
- else findCopies key numcopies skip have check
+ - some locations where the key is known/assumed to be present.
+ -
+ - Also checks if it's required content, and refuses to drop if so.
+ -
+ - --force overrides and always allows dropping.
+ -}
+canDrop :: UUID -> Key -> AssociatedFile -> NumCopies -> [UUID] -> [Remote] -> [UUID] -> Annex Bool
+canDrop dropfrom key afile numcopies have check skip = ifM (Annex.getState Annex.force)
+ ( return True
+ , checkRequiredContent dropfrom key afile
+ <&&>
+ findCopies key numcopies skip have check
+ )
findCopies :: Key -> NumCopies -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
findCopies key need skip = helper [] []
@@ -137,6 +154,19 @@ notEnoughCopies key need have skip bad = do
unsafe = showNote "unsafe"
hint = showLongNote "(Use --force to override this check, or adjust numcopies.)"
+checkRequiredContent :: UUID -> Key -> AssociatedFile -> Annex Bool
+checkRequiredContent u k afile =
+ ifM (isRequiredContent (Just u) S.empty (Just k) afile False)
+ ( requiredContent
+ , return True
+ )
+
+requiredContent :: Annex Bool
+requiredContent = do
+ showLongNote "That file is required content, it cannot be dropped!"
+ showLongNote "(Use --force to override this check, or adjust required content configuration.)"
+ return False
+
{- In auto mode, only runs the action if there are enough
- copies on other semitrusted repositories. -}
checkDropAuto :: Maybe Remote -> FilePath -> Key -> (NumCopies -> CommandStart) -> CommandStart
diff --git a/Command/DropUnused.hs b/Command/DropUnused.hs
index 345d03032..ce49795c9 100644
--- a/Command/DropUnused.hs
+++ b/Command/DropUnused.hs
@@ -34,8 +34,8 @@ perform numcopies key = maybe droplocal dropremote =<< Remote.byNameWithUUID =<<
where
dropremote r = do
showAction $ "from " ++ Remote.name r
- Command.Drop.performRemote key numcopies r
- droplocal = Command.Drop.performLocal key numcopies Nothing
+ Command.Drop.performRemote key Nothing numcopies r
+ droplocal = Command.Drop.performLocal key Nothing numcopies Nothing
from = Annex.getField $ optionName Command.Drop.dropFromOption
performOther :: (Key -> Git.Repo -> FilePath) -> Key -> CommandPerform
diff --git a/Command/Fsck.hs b/Command/Fsck.hs
index 059f3e91e..88a9915c4 100644
--- a/Command/Fsck.hs
+++ b/Command/Fsck.hs
@@ -29,6 +29,7 @@ import Utility.DataUnits
import Utility.FileMode
import Config
import Types.Key
+import Types.CleanupActions
import Utility.HumanTime
import Git.FilePath
import Utility.PID
@@ -93,7 +94,7 @@ getIncremental = do
checkschedule Nothing = error "bad --incremental-schedule value"
checkschedule (Just delta) = do
- Annex.addCleanup "" $ do
+ Annex.addCleanup FsckCleanup $ do
v <- getStartTime
case v of
Nothing -> noop
diff --git a/Command/Get.hs b/Command/Get.hs
index f436b15b5..bef466724 100644
--- a/Command/Get.hs
+++ b/Command/Get.hs
@@ -11,7 +11,7 @@ import Common.Annex
import Command
import qualified Remote
import Annex.Content
-import Logs.Transfer
+import Annex.Transfer
import Config.NumCopies
import Annex.Wanted
import qualified Command.Move
@@ -69,15 +69,15 @@ getKeyFile' key afile dest = dispatch
showNote "not available"
showlocs
return False
- dispatch remotes = trycopy remotes remotes
- trycopy full [] = do
+ dispatch remotes = notifyTransfer Download afile $ trycopy remotes remotes
+ trycopy full [] _ = do
Remote.showTriedRemotes full
showlocs
return False
- trycopy full (r:rs) =
+ trycopy full (r:rs) witness =
ifM (probablyPresent r)
- ( docopy r (trycopy full rs)
- , trycopy full rs
+ ( docopy r witness <||> trycopy full rs witness
+ , trycopy full rs witness
)
showlocs = Remote.showLocations key []
"No other repository is known to contain the file."
@@ -87,8 +87,6 @@ getKeyFile' key afile dest = dispatch
| Remote.hasKeyCheap r =
either (const False) id <$> Remote.hasKey r key
| otherwise = return True
- docopy r continue = do
- ok <- download (Remote.uuid r) key afile noRetry $ \p -> do
- showAction $ "from " ++ Remote.name r
- Remote.retrieveKeyFile r key afile dest p
- if ok then return ok else continue
+ docopy r = download (Remote.uuid r) key afile noRetry $ \p -> do
+ showAction $ "from " ++ Remote.name r
+ Remote.retrieveKeyFile r key afile dest p
diff --git a/Command/List.hs b/Command/List.hs
index ba6251333..1fa206405 100644
--- a/Command/List.hs
+++ b/Command/List.hs
@@ -38,7 +38,7 @@ seek ps = do
getList :: Annex [(UUID, RemoteName, TrustLevel)]
getList = ifM (Annex.getFlag $ optionName allrepos)
- ( nubBy ((==) `on` fst3) <$> ((++) <$> getRemotes <*> getAll)
+ ( nubBy ((==) `on` fst3) <$> ((++) <$> getRemotes <*> getAllUUIDs)
, getRemotes
)
where
@@ -48,7 +48,7 @@ getList = ifM (Annex.getFlag $ optionName allrepos)
hereu <- getUUID
heretrust <- lookupTrust hereu
return $ (hereu, "here", heretrust) : zip3 (map uuid rs) (map name rs) ts
- getAll = do
+ getAllUUIDs = do
rs <- M.toList <$> uuidMap
rs3 <- forM rs $ \(u, n) -> (,,)
<$> pure u
diff --git a/Command/Map.hs b/Command/Map.hs
index 9b80d2035..7c11fb2ef 100644
--- a/Command/Map.hs
+++ b/Command/Map.hs
@@ -158,7 +158,8 @@ absRepo reference r
| Git.repoIsUrl r = return r
| otherwise = liftIO $ do
r' <- Git.Construct.fromAbsPath =<< absPath (Git.repoPath r)
- flip Annex.eval Annex.gitRepo =<< Annex.new r'
+ r'' <- safely $ flip Annex.eval Annex.gitRepo =<< Annex.new r'
+ return (fromMaybe r' r'')
{- Checks if two repos are the same. -}
same :: Git.Repo -> Git.Repo -> Bool
@@ -192,14 +193,9 @@ tryScan :: Git.Repo -> Annex (Maybe Git.Repo)
tryScan r
| Git.repoIsSsh r = sshscan
| Git.repoIsUrl r = return Nothing
- | otherwise = safely $ Git.Config.read r
+ | otherwise = liftIO $ safely $ Git.Config.read r
where
- safely a = do
- result <- liftIO (try a :: IO (Either SomeException Git.Repo))
- case result of
- Left _ -> return Nothing
- Right r' -> return $ Just r'
- pipedconfig cmd params = safely $
+ pipedconfig cmd params = liftIO $ safely $
withHandle StdoutHandle createProcessSuccess p $
Git.Config.hRead r
where
@@ -247,3 +243,10 @@ combineSame = map snd . nubBy sameuuid . map pair
where
sameuuid (u1, _) (u2, _) = u1 == u2 && u1 /= NoUUID
pair r = (getUncachedUUID r, r)
+
+safely :: IO Git.Repo -> IO (Maybe Git.Repo)
+safely a = do
+ result <- try a :: IO (Either SomeException Git.Repo)
+ case result of
+ Left _ -> return Nothing
+ Right r' -> return $ Just r'
diff --git a/Command/MetaData.hs b/Command/MetaData.hs
index 55d67c6b7..d932315ab 100644
--- a/Command/MetaData.hs
+++ b/Command/MetaData.hs
@@ -12,16 +12,24 @@ import qualified Annex
import Command
import Annex.MetaData
import Logs.MetaData
-import Types.MetaData
import qualified Data.Set as S
import Data.Time.Clock.POSIX
def :: [Command]
-def = [withOptions [setOption, tagOption, untagOption, jsonOption] $
+def = [withOptions metaDataOptions $
command "metadata" paramPaths seek
SectionMetaData "sets metadata of a file"]
+metaDataOptions :: [Option]
+metaDataOptions =
+ [ setOption
+ , tagOption
+ , untagOption
+ , getOption
+ , jsonOption
+ ] ++ keyOptions
+
storeModMeta :: ModMeta -> Annex ()
storeModMeta modmeta = Annex.changeState $
\s -> s { Annex.modmeta = modmeta:Annex.modmeta s }
@@ -31,6 +39,9 @@ setOption = Option ['s'] ["set"] (ReqArg mkmod "FIELD[+-]=VALUE") "set metadata"
where
mkmod = either error storeModMeta . parseModMeta
+getOption :: Option
+getOption = fieldOption ['g'] "get" paramField "get single metadata field"
+
tagOption :: Option
tagOption = Option ['t'] ["tag"] (ReqArg mkmod "TAG") "set a tag"
where
@@ -44,19 +55,35 @@ untagOption = Option ['u'] ["untag"] (ReqArg mkmod "TAG") "remove a tag"
seek :: CommandSeek
seek ps = do
modmeta <- Annex.getState Annex.modmeta
+ getfield <- getOptionField getOption $ \ms ->
+ return $ either error id . mkMetaField <$> ms
now <- liftIO getPOSIXTime
- withFilesInGit (whenAnnexed $ start now modmeta) ps
+ withKeyOptions
+ (startKeys now getfield modmeta)
+ (withFilesInGit (whenAnnexed $ start now getfield modmeta))
+ ps
+
+start :: POSIXTime -> Maybe MetaField -> [ModMeta] -> FilePath -> (Key, Backend) -> CommandStart
+start now f ms file (k, _) = start' (Just file) now f ms k
+
+startKeys :: POSIXTime -> Maybe MetaField -> [ModMeta] -> Key -> CommandStart
+startKeys = start' Nothing
-start :: POSIXTime -> [ModMeta] -> FilePath -> (Key, Backend) -> CommandStart
-start now ms file (k, _) = do
- showStart "metadata" file
+start' :: AssociatedFile -> POSIXTime -> Maybe MetaField -> [ModMeta] -> Key -> CommandStart
+start' afile now Nothing ms k = do
+ showStart' "metadata" k afile
next $ perform now ms k
+start' _ _ (Just f) _ k = do
+ l <- S.toList . currentMetaDataValues f <$> getCurrentMetaData k
+ liftIO $ forM_ l $
+ putStrLn . fromMetaValue
+ stop
perform :: POSIXTime -> [ModMeta] -> Key -> CommandPerform
perform _ [] k = next $ cleanup k
perform now ms k = do
oldm <- getCurrentMetaData k
- let m = foldl' unionMetaData emptyMetaData $ map (modMeta oldm) ms
+ let m = combineMetaData $ map (modMeta oldm) ms
addMetaData' k m now
next $ cleanup k
diff --git a/Command/Move.hs b/Command/Move.hs
index af3623da0..206a875b7 100644
--- a/Command/Move.hs
+++ b/Command/Move.hs
@@ -14,8 +14,8 @@ import qualified Annex
import Annex.Content
import qualified Remote
import Annex.UUID
+import Annex.Transfer
import Logs.Presence
-import Logs.Transfer
def :: [Command]
def = [withOptions moveOptions $ command "move" paramPaths seek
@@ -69,28 +69,38 @@ toStart dest move afile key = do
ishere <- inAnnex key
if not ishere || u == Remote.uuid dest
then stop -- not here, so nothing to do
- else do
- showMoveAction move key afile
- next $ toPerform dest move key afile
-toPerform :: Remote -> Bool -> Key -> AssociatedFile -> CommandPerform
-toPerform dest move key afile = moveLock move key $ do
- -- Checking the remote is expensive, so not done in the start step.
- -- In fast mode, location tracking is assumed to be correct,
- -- and an explicit check is not done, when copying. When moving,
- -- it has to be done, to avoid inaverdent data loss.
+ else toStart' dest move afile key
+
+toStart' :: Remote -> Bool -> AssociatedFile -> Key -> CommandStart
+toStart' dest move afile key = do
fast <- Annex.getState Annex.fast
- let fastcheck = fast && not move && not (Remote.hasKeyCheap dest)
- isthere <- if fastcheck
- then Right <$> expectedpresent
- else Remote.hasKey dest key
+ if fast && not move && not (Remote.hasKeyCheap dest)
+ then ifM (expectedPresent dest key)
+ ( stop
+ , go True (pure $ Right False)
+ )
+ else go False (Remote.hasKey dest key)
+ where
+ go fastcheck isthere = do
+ showMoveAction move key afile
+ next $ toPerform dest move key afile fastcheck =<< isthere
+
+expectedPresent :: Remote -> Key -> Annex Bool
+expectedPresent dest key = do
+ remotes <- Remote.keyPossibilities key
+ return $ dest `elem` remotes
+
+toPerform :: Remote -> Bool -> Key -> AssociatedFile -> Bool -> Either String Bool -> CommandPerform
+toPerform dest move key afile fastcheck isthere = moveLock move key $
case isthere of
Left err -> do
showNote err
stop
Right False -> do
showAction $ "to " ++ Remote.name dest
- ok <- upload (Remote.uuid dest) key afile noRetry $
- Remote.storeKey dest key afile
+ ok <- notifyTransfer Upload afile $
+ upload (Remote.uuid dest) key afile noRetry $
+ Remote.storeKey dest key afile
if ok
then do
Remote.logStatus dest key InfoPresent
@@ -100,7 +110,7 @@ toPerform dest move key afile = moveLock move key $ do
warning "This could have failed because --fast is enabled."
stop
Right True -> do
- unlessM expectedpresent $
+ unlessM (expectedPresent dest key) $
Remote.logStatus dest key InfoPresent
finish
where
@@ -109,9 +119,6 @@ toPerform dest move key afile = moveLock move key $ do
removeAnnex key
next $ Command.Drop.cleanupLocal key
| otherwise = next $ return True
- expectedpresent = do
- remotes <- Remote.keyPossibilities key
- return $ dest `elem` remotes
{- Moves (or copies) the content of an annexed file from a remote
- to the current repository.
@@ -149,9 +156,10 @@ fromPerform src move key afile = moveLock move key $
, handle move =<< go
)
where
- go = download (Remote.uuid src) key afile noRetry $ \p -> do
- showAction $ "from " ++ Remote.name src
- getViaTmp key $ \t -> Remote.retrieveKeyFile src key afile t p
+ go = notifyTransfer Download afile $
+ download (Remote.uuid src) key afile noRetry $ \p -> do
+ showAction $ "from " ++ Remote.name src
+ getViaTmp key $ \t -> Remote.retrieveKeyFile src key afile t p
handle _ False = stop -- failed
handle False True = next $ return True -- copy complete
handle True True = do -- finish moving
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
index fa34ad245..412b9ae08 100644
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -5,6 +5,8 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Command.PreCommit where
import Common.Annex
@@ -16,11 +18,17 @@ import Annex.Direct
import Annex.Hook
import Annex.View
import Annex.View.ViewedFile
+import Annex.Perms
+import Annex.Exception
import Logs.View
import Logs.MetaData
import Types.View
import Types.MetaData
+#ifdef mingw32_HOST_OS
+import Utility.WinLock
+#endif
+
import qualified Data.Set as S
def :: [Command]
@@ -28,7 +36,7 @@ def = [command "pre-commit" paramPaths seek SectionPlumbing
"run by git pre-commit hook"]
seek :: CommandSeek
-seek ps = ifM isDirect
+seek ps = lockPreCommitHook $ ifM isDirect
( do
-- update direct mode mappings for committed files
withWords startDirect ps
@@ -82,3 +90,22 @@ showMetaDataChange = showLongNote . unlines . concatMap showmeta . fromMetaData
showset v
| isSet v = "+"
| otherwise = "-"
+
+{- Takes exclusive lock; blocks until available. -}
+lockPreCommitHook :: Annex a -> Annex a
+lockPreCommitHook a = do
+ lockfile <- fromRepo gitAnnexPreCommitLock
+ createAnnexDirectory $ takeDirectory lockfile
+ mode <- annexFileMode
+ bracketIO (lock lockfile mode) unlock (const a)
+ where
+#ifndef mingw32_HOST_OS
+ lock lockfile mode = do
+ l <- liftIO $ noUmask mode $ createFile lockfile mode
+ liftIO $ waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
+ return l
+ unlock = closeFd
+#else
+ lock lockfile _mode = liftIO $ waitToLock $ lockExclusive lockfile
+ unlock = dropLock
+#endif
diff --git a/Command/SendKey.hs b/Command/SendKey.hs
index 2215b16b2..a201d1b89 100644
--- a/Command/SendKey.hs
+++ b/Command/SendKey.hs
@@ -12,7 +12,7 @@ import Command
import Annex.Content
import Annex
import Utility.Rsync
-import Logs.Transfer
+import Annex.Transfer
import qualified CmdLine.GitAnnexShell.Fields as Fields
import Utility.Metered
diff --git a/Command/Sync.hs b/Command/Sync.hs
index 07006ef28..a4004736a 100644
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -376,5 +376,5 @@ syncFile rs f (k, _) = do
put dest = do
ok <- commandAction $ do
showStart "copy" f
- next $ Command.Move.toPerform dest False k (Just f)
+ Command.Move.toStart' dest False (Just f) k
return (ok, if ok then Just (Remote.uuid dest) else Nothing)
diff --git a/Command/TransferKey.hs b/Command/TransferKey.hs
index b6b237467..13bfd825e 100644
--- a/Command/TransferKey.hs
+++ b/Command/TransferKey.hs
@@ -11,7 +11,7 @@ import Common.Annex
import Command
import Annex.Content
import Logs.Location
-import Logs.Transfer
+import Annex.Transfer
import qualified Remote
import Types.Remote
@@ -41,7 +41,7 @@ start to from file key =
_ -> error "specify either --from or --to"
toPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
-toPerform remote key file = go $
+toPerform remote key file = go Upload file $
upload (uuid remote) key file forwardRetry $ \p -> do
ok <- Remote.storeKey remote key file p
when ok $
@@ -49,9 +49,9 @@ toPerform remote key file = go $
return ok
fromPerform :: Remote -> Key -> AssociatedFile -> CommandPerform
-fromPerform remote key file = go $
+fromPerform remote key file = go Upload file $
download (uuid remote) key file forwardRetry $ \p ->
getViaTmp key $ \t -> Remote.retrieveKeyFile remote key file t p
-go :: Annex Bool -> CommandPerform
-go a = a >>= liftIO . exitBool
+go :: Direction -> AssociatedFile -> (NotifyWitness -> Annex Bool) -> CommandPerform
+go direction file a = notifyTransfer direction file a >>= liftIO . exitBool
diff --git a/Command/TransferKeys.hs b/Command/TransferKeys.hs
index b42628609..8f4498eb1 100644
--- a/Command/TransferKeys.hs
+++ b/Command/TransferKeys.hs
@@ -13,7 +13,7 @@ import Common.Annex
import Command
import Annex.Content
import Logs.Location
-import Logs.Transfer
+import Annex.Transfer
import qualified Remote
import Types.Key
@@ -34,14 +34,15 @@ start = withHandles $ \(readh, writeh) -> do
stop
where
runner (TransferRequest direction remote key file)
- | direction == Upload =
+ | direction == Upload = notifyTransfer direction file $
upload (Remote.uuid remote) key file forwardRetry $ \p -> do
ok <- Remote.storeKey remote key file p
when ok $
Remote.logStatus remote key InfoPresent
return ok
- | otherwise = download (Remote.uuid remote) key file forwardRetry $ \p ->
- getViaTmp key $ \t -> Remote.retrieveKeyFile remote key file t p
+ | otherwise = notifyTransfer direction file $
+ download (Remote.uuid remote) key file forwardRetry $ \p ->
+ getViaTmp key $ \t -> Remote.retrieveKeyFile remote key file t p
{- stdin and stdout are connected with the caller, to be used for
- communication with it. But doing a transfer might involve something
diff --git a/Command/Unannex.hs b/Command/Unannex.hs
index 1f2978430..3da7c2a41 100644
--- a/Command/Unannex.hs
+++ b/Command/Unannex.hs
@@ -16,15 +16,47 @@ import qualified Annex
import Annex.Content
import Annex.Content.Direct
import qualified Git.Command
-import qualified Git.LsFiles as LsFiles
+import qualified Git.Ref
+import qualified Git.DiffTree as DiffTree
import Utility.CopyFile
+import Command.PreCommit (lockPreCommitHook)
def :: [Command]
def = [command "unannex" paramPaths seek SectionUtility
"undo accidential add command"]
seek :: CommandSeek
-seek = withFilesInGit $ whenAnnexed start
+seek = wrapUnannex . (withFilesInGit $ whenAnnexed start)
+
+wrapUnannex :: Annex a -> Annex a
+wrapUnannex a = ifM isDirect
+ ( a
+ {- Run with the pre-commit hook disabled, to avoid confusing
+ - behavior if an unannexed file is added back to git as
+ - a normal, non-annexed file and then committed.
+ - Otherwise, the pre-commit hook would think that the file
+ - has been unlocked and needs to be re-annexed.
+ -
+ - At the end, make a commit removing the unannexed files.
+ -}
+ , ifM cleanindex
+ ( lockPreCommitHook $ commit `after` a
+ , error "Cannot proceed with uncommitted changes staged in the index. Recommend you: git commit"
+ )
+ )
+ where
+ commit = inRepo $ Git.Command.run
+ [ Param "commit"
+ , Param "-q"
+ , Param "--allow-empty"
+ , Param "--no-verify"
+ , Param "-m", Param "content removed from git annex"
+ ]
+ cleanindex = do
+ (diff, cleanup) <- inRepo $ DiffTree.diffIndex Git.Ref.headRef
+ if null diff
+ then void (liftIO cleanup) >> return True
+ else void (liftIO cleanup) >> return False
start :: FilePath -> (Key, Backend) -> CommandStart
start file (key, _) = stopUnless (inAnnex key) $ do
@@ -36,26 +68,7 @@ start file (key, _) = stopUnless (inAnnex key) $ do
performIndirect :: FilePath -> Key -> CommandPerform
performIndirect file key = do
liftIO $ removeFile file
-
- -- git rm deletes empty directory without --cached
inRepo $ Git.Command.run [Params "rm --cached --force --quiet --", File file]
-
- -- If the file was already committed, it is now staged for removal.
- -- Commit that removal now, to avoid later confusing the
- -- pre-commit hook, if this file is later added back to
- -- git as a normal non-annexed file, to thinking that the
- -- file has been unlocked and needs to be re-annexed.
- (s, reap) <- inRepo $ LsFiles.staged [file]
- unless (null s) $
- inRepo $ Git.Command.run
- [ Param "commit"
- , Param "-q"
- , Param "--no-verify"
- , Param "-m", Param "content removed from git annex"
- , Param "--", File file
- ]
- void $ liftIO reap
-
next $ cleanupIndirect file key
cleanupIndirect :: FilePath -> Key -> CommandCleanup
diff --git a/Command/Uninit.hs b/Command/Uninit.hs
index 2a9e3e687..5b2adf0bd 100644
--- a/Command/Uninit.hs
+++ b/Command/Uninit.hs
@@ -36,7 +36,7 @@ check = do
seek :: CommandSeek
seek ps = do
- withFilesNotInGit (whenAnnexed startCheckIncomplete) ps
+ withFilesNotInGit False (whenAnnexed startCheckIncomplete) ps
withFilesInGit (whenAnnexed Command.Unannex.start) ps
finish
diff --git a/Command/Unused.hs b/Command/Unused.hs
index c174cd256..3e844e5a8 100644
--- a/Command/Unused.hs
+++ b/Command/Unused.hs
@@ -10,7 +10,6 @@
module Command.Unused where
import qualified Data.Set as S
-import qualified Data.ByteString.Lazy as L
import Data.BloomFilter
import Data.BloomFilter.Easy
import Data.BloomFilter.Hash
@@ -296,7 +295,7 @@ withKeysReferencedInGitRef a ref = do
liftIO $ void clean
where
tKey True = fmap fst <$$> Backend.lookupFile . getTopFilePath . DiffTree.file
- tKey False = fileKey . takeFileName . encodeW8 . L.unpack <$$>
+ tKey False = fileKey . takeFileName . decodeBS <$$>
catFile ref . getTopFilePath . DiffTree.file
{- Looks in the specified directory for bad/tmp keys, and returns a list
diff --git a/Command/Vicfg.hs b/Command/Vicfg.hs
index 7608959c2..d7d5229da 100644
--- a/Command/Vicfg.hs
+++ b/Command/Vicfg.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -60,7 +60,9 @@ vicfg curcfg f = do
data Cfg = Cfg
{ cfgTrustMap :: TrustMap
, cfgGroupMap :: M.Map UUID (S.Set Group)
- , cfgPreferredContentMap :: M.Map UUID String
+ , cfgPreferredContentMap :: M.Map UUID PreferredContentExpression
+ , cfgRequiredContentMap :: M.Map UUID PreferredContentExpression
+ , cfgGroupPreferredContentMap :: M.Map Group PreferredContentExpression
, cfgScheduleMap :: M.Map UUID [ScheduledActivity]
}
@@ -69,25 +71,44 @@ getCfg = Cfg
<$> trustMapRaw -- without local trust overrides
<*> (groupsByUUID <$> groupMap)
<*> preferredContentMapRaw
+ <*> requiredContentMapRaw
+ <*> groupPreferredContentMapRaw
<*> scheduleMap
setCfg :: Cfg -> Cfg -> Annex ()
setCfg curcfg newcfg = do
- let (trustchanges, groupchanges, preferredcontentchanges, schedulechanges) = diffCfg curcfg newcfg
- mapM_ (uncurry trustSet) $ M.toList trustchanges
- mapM_ (uncurry groupSet) $ M.toList groupchanges
- mapM_ (uncurry preferredContentSet) $ M.toList preferredcontentchanges
- mapM_ (uncurry scheduleSet) $ M.toList schedulechanges
-
-diffCfg :: Cfg -> Cfg -> (TrustMap, M.Map UUID (S.Set Group), M.Map UUID String, M.Map UUID [ScheduledActivity])
-diffCfg curcfg newcfg = (diff cfgTrustMap, diff cfgGroupMap, diff cfgPreferredContentMap, diff cfgScheduleMap)
+ let diff = diffCfg curcfg newcfg
+ mapM_ (uncurry trustSet) $ M.toList $ cfgTrustMap diff
+ mapM_ (uncurry groupSet) $ M.toList $ cfgGroupMap diff
+ mapM_ (uncurry preferredContentSet) $ M.toList $ cfgPreferredContentMap diff
+ mapM_ (uncurry requiredContentSet) $ M.toList $ cfgRequiredContentMap diff
+ mapM_ (uncurry groupPreferredContentSet) $ M.toList $ cfgGroupPreferredContentMap diff
+ mapM_ (uncurry scheduleSet) $ M.toList $ cfgScheduleMap diff
+
+diffCfg :: Cfg -> Cfg -> Cfg
+diffCfg curcfg newcfg = Cfg
+ { cfgTrustMap = diff cfgTrustMap
+ , cfgGroupMap = diff cfgGroupMap
+ , cfgPreferredContentMap = diff cfgPreferredContentMap
+ , cfgRequiredContentMap = diff cfgRequiredContentMap
+ , cfgGroupPreferredContentMap = diff cfgGroupPreferredContentMap
+ , cfgScheduleMap = diff cfgScheduleMap
+ }
where
diff f = M.differenceWith (\x y -> if x == y then Nothing else Just x)
(f newcfg) (f curcfg)
genCfg :: Cfg -> M.Map UUID String -> String
-genCfg cfg descs = unlines $ concat
- [intro, trust, groups, preferredcontent, schedule]
+genCfg cfg descs = unlines $ intercalate [""]
+ [ intro
+ , trust
+ , groups
+ , preferredcontent
+ , grouppreferredcontent
+ , standardgroups
+ , requiredcontent
+ , schedule
+ ]
where
intro =
[ com "git-annex configuration"
@@ -95,22 +116,20 @@ genCfg cfg descs = unlines $ concat
, com "Changes saved to this file will be recorded in the git-annex branch."
, com ""
, com "Lines in this file have the format:"
- , com " setting uuid = value"
+ , com " setting field = value"
]
- trust = settings cfgTrustMap
- [ ""
- , com "Repository trust configuration"
+ trust = settings cfg descs cfgTrustMap
+ [ com "Repository trust configuration"
, com "(Valid trust levels: " ++ trustlevels ++ ")"
]
(\(t, u) -> line "trust" u $ showTrustLevel t)
(\u -> lcom $ line "trust" u $ showTrustLevel SemiTrusted)
where
- trustlevels = unwords $ map showTrustLevel [Trusted .. DeadTrusted]
+ trustlevels = unwords $ map showTrustLevel [Trusted .. DeadTrusted]
- groups = settings cfgGroupMap
- [ ""
- , com "Repository groups"
+ groups = settings cfg descs cfgGroupMap
+ [ com "Repository groups"
, com $ "(Standard groups: " ++ grouplist ++ ")"
, com "(Separate group names with spaces)"
]
@@ -119,33 +138,65 @@ genCfg cfg descs = unlines $ concat
where
grouplist = unwords $ map fromStandardGroup [minBound..]
- preferredcontent = settings cfgPreferredContentMap
- [ ""
- , com "Repository preferred contents"
+ preferredcontent = settings cfg descs cfgPreferredContentMap
+ [ com "Repository preferred contents" ]
+ (\(s, u) -> line "wanted" u s)
+ (\u -> line "wanted" u "standard")
+
+ requiredcontent = settings cfg descs cfgRequiredContentMap
+ [ com "Repository required contents" ]
+ (\(s, u) -> line "required" u s)
+ (\u -> line "required" u "")
+
+ grouppreferredcontent = settings' cfg allgroups cfgGroupPreferredContentMap
+ [ com "Group preferred contents"
+ , com "(Used by repositories with \"groupwanted\" in their preferred contents)"
]
- (\(s, u) -> line "content" u s)
- (\u -> line "content" u "")
+ (\(s, g) -> gline g s)
+ (\g -> gline g "standard")
+ where
+ gline g value = [ unwords ["groupwanted", g, "=", value] ]
+ allgroups = S.unions $ stdgroups : M.elems (cfgGroupMap cfg)
+ stdgroups = S.fromList $ map fromStandardGroup [minBound..maxBound]
- schedule = settings cfgScheduleMap
- [ ""
- , com "Scheduled activities"
+ standardgroups =
+ [ com "Standard preferred contents"
+ , com "(Used by wanted or groupwanted expressions containing \"standard\")"
+ , com "(For reference only; built-in and cannot be changed!)"
+ ]
+ ++ map gline [minBound..maxBound]
+ where
+ gline g = com $ unwords
+ [ "standard"
+ , fromStandardGroup g, "=", standardPreferredContent g
+ ]
+
+ schedule = settings cfg descs cfgScheduleMap
+ [ com "Scheduled activities"
, com "(Separate multiple activities with \"; \")"
]
(\(l, u) -> line "schedule" u $ fromScheduledActivities l)
(\u -> line "schedule" u "")
- settings field desc showvals showdefaults = concat
- [ desc
- , concatMap showvals $ sort $ map swap $ M.toList $ field cfg
- , concatMap (lcom . showdefaults) $ missing field
- ]
-
line setting u value =
[ com $ "(for " ++ fromMaybe "" (M.lookup u descs) ++ ")"
, unwords [setting, fromUUID u, "=", value]
]
- lcom = map (\l -> if "#" `isPrefixOf` l then l else '#' : l)
- missing field = S.toList $ M.keysSet descs `S.difference` M.keysSet (field cfg)
+
+settings :: Ord v => Cfg -> M.Map UUID String -> (Cfg -> M.Map UUID v) -> [String] -> ((v, UUID) -> [String]) -> (UUID -> [String]) -> [String]
+settings cfg descs = settings' cfg (M.keysSet descs)
+
+settings' :: (Ord v, Ord f) => Cfg -> S.Set f -> (Cfg -> M.Map f v) -> [String] -> ((v, f) -> [String]) -> (f -> [String]) -> [String]
+settings' cfg s field desc showvals showdefaults = concat
+ [ desc
+ , concatMap showvals $ sort $ map swap $ M.toList $ field cfg
+ , concatMap (lcom . showdefaults) missing
+ ]
+ where
+ missing = S.toList $ s `S.difference` M.keysSet (field cfg)
+
+lcom :: [String] -> [String]
+lcom = map (\l -> if "#" `isPrefixOf` l then l else '#' : l)
{- If there's a parse error, returns a new version of the file,
- with the problem lines noted. -}
@@ -163,16 +214,16 @@ parseCfg curcfg = go [] curcfg . lines
parse l cfg
| null l = Right cfg
| "#" `isPrefixOf` l = Right cfg
- | null setting || null u = Left "missing repository uuid"
- | otherwise = handle cfg (toUUID u) setting value'
+ | null setting || null f = Left "missing field"
+ | otherwise = handle cfg f setting value'
where
(setting, rest) = separate isSpace l
(r, value) = separate (== '=') rest
value' = trimspace value
- u = reverse $ trimspace $ reverse $ trimspace r
+ f = reverse $ trimspace $ reverse $ trimspace r
trimspace = dropWhile isSpace
- handle cfg u setting value
+ handle cfg f setting value
| setting == "trust" = case readTrustLevel value of
Nothing -> badval "trust value" value
Just t ->
@@ -181,18 +232,32 @@ parseCfg curcfg = go [] curcfg . lines
| setting == "group" =
let m = M.insert u (S.fromList $ words value) (cfgGroupMap cfg)
in Right $ cfg { cfgGroupMap = m }
- | setting == "content" =
+ | setting == "wanted" =
case checkPreferredContentExpression value of
Just e -> Left e
Nothing ->
let m = M.insert u value (cfgPreferredContentMap cfg)
in Right $ cfg { cfgPreferredContentMap = m }
+ | setting == "required" =
+ case checkPreferredContentExpression value of
+ Just e -> Left e
+ Nothing ->
+ let m = M.insert u value (cfgRequiredContentMap cfg)
+ in Right $ cfg { cfgRequiredContentMap = m }
+ | setting == "groupwanted" =
+ case checkPreferredContentExpression value of
+ Just e -> Left e
+ Nothing ->
+ let m = M.insert f value (cfgGroupPreferredContentMap cfg)
+ in Right $ cfg { cfgGroupPreferredContentMap = m }
| setting == "schedule" = case parseScheduledActivities value of
Left e -> Left e
Right l ->
let m = M.insert u l (cfgScheduleMap cfg)
in Right $ cfg { cfgScheduleMap = m }
| otherwise = badval "setting" setting
+ where
+ u = toUUID f
showerr (Just msg, l) = [parseerr ++ msg, l]
showerr (Nothing, l)
@@ -203,11 +268,11 @@ parseCfg curcfg = go [] curcfg . lines
badval desc val = Left $ "unknown " ++ desc ++ " \"" ++ val ++ "\""
badheader =
- [ com "There was a problem parsing your input."
- , com "Search for \"Parse error\" to find the bad lines."
- , com "Either fix the bad lines, or delete them (to discard your changes)."
+ [ com "** There was a problem parsing your input!"
+ , com "** Search for \"Parse error\" to find the bad lines."
+ , com "** Either fix the bad lines, or delete them (to discard your changes)."
]
- parseerr = com "Parse error in next line: "
+ parseerr = com "** Parse error in next line: "
com :: String -> String
com s = "# " ++ s
diff --git a/Common.hs b/Common.hs
index 6612c9c54..4d6165ac5 100644
--- a/Common.hs
+++ b/Common.hs
@@ -11,6 +11,7 @@ import Control.Exception.Extensible as X (IOException)
import Data.Maybe as X
import Data.List as X hiding (head, tail, init, last)
import Data.String.Utils as X hiding (join)
+import Data.Monoid as X
import System.FilePath as X
import System.Directory as X
diff --git a/Git/CatFile.hs b/Git/CatFile.hs
index c7c51b894..8e64fc558 100644
--- a/Git/CatFile.hs
+++ b/Git/CatFile.hs
@@ -108,6 +108,6 @@ catTree h treeref = go <$> catObjectDetails h treeref
dropsha = L.drop 21
parsemodefile b =
- let (modestr, file) = separate (== ' ') (encodeW8 $ L.unpack b)
+ let (modestr, file) = separate (== ' ') (decodeBS b)
in (file, readmode modestr)
readmode = fst . fromMaybe (0, undefined) . headMaybe . readOct
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
index b3948cb1d..80f76dd90 100644
--- a/Git/Fsck.hs
+++ b/Git/Fsck.hs
@@ -24,10 +24,16 @@ import qualified Git.Version
import qualified Data.Set as S
import System.Process (std_out, std_err)
+import Control.Concurrent.Async
type MissingObjects = S.Set Sha
-data FsckResults = FsckFoundMissing MissingObjects | FsckFailed
+data FsckResults
+ = FsckFoundMissing
+ { missingObjects :: MissingObjects
+ , missingObjectsTruncated :: Bool
+ }
+ | FsckFailed
deriving (Show)
{- Runs fsck to find some of the broken objects in the repository.
@@ -53,22 +59,26 @@ findBroken batchmode r = do
{ std_out = CreatePipe
, std_err = CreatePipe
}
- bad1 <- readMissingObjs r supportsNoDangling (stdoutHandle p)
- bad2 <- readMissingObjs r supportsNoDangling (stderrHandle p)
+ (bad1, bad2) <- concurrently
+ (readMissingObjs maxobjs r supportsNoDangling (stdoutHandle p))
+ (readMissingObjs maxobjs r supportsNoDangling (stderrHandle p))
fsckok <- checkSuccessProcess pid
+ let truncated = S.size bad1 == maxobjs || S.size bad1 == maxobjs
let badobjs = S.union bad1 bad2
if S.null badobjs && not fsckok
then return FsckFailed
- else return $ FsckFoundMissing badobjs
+ else return $ FsckFoundMissing badobjs truncated
+ where
+ maxobjs = 10000
foundBroken :: FsckResults -> Bool
foundBroken FsckFailed = True
-foundBroken (FsckFoundMissing s) = not (S.null s)
+foundBroken (FsckFoundMissing s _) = not (S.null s)
knownMissing :: FsckResults -> MissingObjects
knownMissing FsckFailed = S.empty
-knownMissing (FsckFoundMissing s) = s
+knownMissing (FsckFoundMissing s _) = s
{- Finds objects that are missing from the git repsitory, or are corrupt.
-
@@ -78,9 +88,9 @@ knownMissing (FsckFoundMissing s) = s
findMissing :: [Sha] -> Repo -> IO MissingObjects
findMissing objs r = S.fromList <$> filterM (`isMissing` r) objs
-readMissingObjs :: Repo -> Bool -> Handle -> IO MissingObjects
-readMissingObjs r supportsNoDangling h = do
- objs <- findShas supportsNoDangling <$> hGetContents h
+readMissingObjs :: Int -> Repo -> Bool -> Handle -> IO MissingObjects
+readMissingObjs maxobjs r supportsNoDangling h = do
+ objs <- take maxobjs . findShas supportsNoDangling <$> hGetContents h
findMissing objs r
isMissing :: Sha -> Repo -> IO Bool
diff --git a/Git/Repair.hs b/Git/Repair.hs
index 0f31854b7..67ded359f 100644
--- a/Git/Repair.hs
+++ b/Git/Repair.hs
@@ -1,7 +1,6 @@
{- git repository recovery
-import qualified Data.Set as S
-
- - Copyright 2013 Joey Hess <joey@kitenet.net>
+ - Copyright 2013-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -115,7 +114,9 @@ retrieveMissingObjects missing referencerepo r
void $ copyObjects tmpr r
case stillmissing of
FsckFailed -> return $ FsckFailed
- FsckFoundMissing s -> FsckFoundMissing <$> findMissing (S.toList s) r
+ FsckFoundMissing s t -> FsckFoundMissing
+ <$> findMissing (S.toList s) r
+ <*> pure t
, return stillmissing
)
pullremotes tmpr (rmt:rmts) fetchrefs ms
@@ -128,9 +129,9 @@ retrieveMissingObjects missing referencerepo r
void $ copyObjects tmpr r
case ms of
FsckFailed -> pullremotes tmpr rmts fetchrefs ms
- FsckFoundMissing s -> do
+ FsckFoundMissing s t -> do
stillmissing <- findMissing (S.toList s) r
- pullremotes tmpr rmts fetchrefs (FsckFoundMissing stillmissing)
+ pullremotes tmpr rmts fetchrefs (FsckFoundMissing stillmissing t)
, pullremotes tmpr rmts fetchrefs ms
)
fetchfrom fetchurl ps = runBool $
@@ -278,7 +279,7 @@ findUncorruptedCommit missing goodcommits branch r = do
then return (Just c, gcs')
else findfirst gcs' cs
-{- Verifies tha none of the missing objects in the set are used by
+{- Verifies that none of the missing objects in the set are used by
- the commit. Also adds to a set of commit shas that have been verified to
- be good, which can be passed into subsequent calls to avoid
- redundant work when eg, chasing down branches to find the first
@@ -452,7 +453,7 @@ runRepair' removablebranch fsckresult forced referencerepo g = do
missing <- findBroken False g
stillmissing <- retrieveMissingObjects missing referencerepo g
case stillmissing of
- FsckFoundMissing s
+ FsckFoundMissing s t
| S.null s -> if repoIsLocalBare g
then successfulfinish []
else ifM (checkIndex g)
@@ -465,7 +466,7 @@ runRepair' removablebranch fsckresult forced referencerepo g = do
)
| otherwise -> if forced
then ifM (checkIndex g)
- ( continuerepairs s
+ ( forcerepair s t
, corruptedindex
)
else do
@@ -478,17 +479,16 @@ runRepair' removablebranch fsckresult forced referencerepo g = do
| forced -> ifM (pure (repoIsLocalBare g) <||> checkIndex g)
( do
cleanCorruptObjects FsckFailed g
- missing' <- findBroken False g
- case missing' of
+ stillmissing' <- findBroken False g
+ case stillmissing' of
FsckFailed -> return (False, [])
- FsckFoundMissing stillmissing' ->
- continuerepairs stillmissing'
+ FsckFoundMissing s t -> forcerepair s t
, corruptedindex
)
| otherwise -> unsuccessfulfinish
where
- continuerepairs stillmissing = do
- (removedbranches, goodcommits) <- removeBadBranches removablebranch stillmissing emptyGoodCommits g
+ repairbranches missing = do
+ (removedbranches, goodcommits) <- removeBadBranches removablebranch missing emptyGoodCommits g
let remotebranches = filter isTrackingBranch removedbranches
unless (null remotebranches) $
putStrLn $ unwords
@@ -496,32 +496,43 @@ runRepair' removablebranch fsckresult forced referencerepo g = do
, show (length remotebranches)
, "remote tracking branches that referred to missing objects."
]
- (resetbranches, deletedbranches, _) <- resetLocalBranches stillmissing goodcommits g
+ (resetbranches, deletedbranches, _) <- resetLocalBranches missing goodcommits g
displayList (map fromRef resetbranches)
"Reset these local branches to old versions before the missing objects were committed:"
displayList (map fromRef deletedbranches)
"Deleted these local branches, which could not be recovered due to missing objects:"
+ return (resetbranches ++ deletedbranches)
+
+ forcerepair missing fscktruncated = do
+ modifiedbranches <- repairbranches missing
deindexedfiles <- rewriteIndex g
displayList deindexedfiles
"Removed these missing files from the index. You should look at what files are present in your working tree and git add them back to the index when appropriate."
- let modifiedbranches = resetbranches ++ deletedbranches
- if null resetbranches && null deletedbranches
- then successfulfinish modifiedbranches
- else do
- unless (repoIsLocalBare g) $ do
- mcurr <- Branch.currentUnsafe g
- case mcurr of
- Nothing -> return ()
- Just curr -> when (any (== curr) modifiedbranches) $ do
+
+ -- When the fsck results were truncated, try
+ -- fscking again, and as long as different
+ -- missing objects are found, continue
+ -- the repair process.
+ if fscktruncated
+ then do
+ fsckresult' <- findBroken False g
+ case fsckresult' of
+ FsckFailed -> do
+ putStrLn "git fsck is failing"
+ return (False, modifiedbranches)
+ FsckFoundMissing s _
+ | S.null s -> successfulfinish modifiedbranches
+ | S.null (s `S.difference` missing) -> do
putStrLn $ unwords
- [ "You currently have"
- , fromRef curr
- , "checked out. You may have staged changes in the index that can be committed to recover the lost state of this branch!"
+ [ show (S.size s)
+ , "missing objects could not be recovered!"
]
- putStrLn "Successfully recovered repository!"
- putStrLn "Please carefully check that the changes mentioned above are ok.."
- return (True, modifiedbranches)
-
+ return (False, modifiedbranches)
+ | otherwise -> do
+ (ok, modifiedbranches') <- runRepairOf fsckresult' removablebranch forced referencerepo g
+ return (ok, modifiedbranches++modifiedbranches')
+ else successfulfinish modifiedbranches
+
corruptedindex = do
nukeFile (indexFile g)
-- The corrupted index can prevent fsck from finding other
@@ -531,12 +542,28 @@ runRepair' removablebranch fsckresult forced referencerepo g = do
putStrLn "Removed the corrupted index file. You should look at what files are present in your working tree and git add them back to the index when appropriate."
return result
- successfulfinish modifiedbranches = do
- mapM_ putStrLn
- [ "Successfully recovered repository!"
- , "You should run \"git fsck\" to make sure, but it looks like everything was recovered ok."
- ]
- return (True, modifiedbranches)
+ successfulfinish modifiedbranches
+ | null modifiedbranches = do
+ mapM_ putStrLn
+ [ "Successfully recovered repository!"
+ , "You should run \"git fsck\" to make sure, but it looks like everything was recovered ok."
+ ]
+ return (True, modifiedbranches)
+ | otherwise = do
+ unless (repoIsLocalBare g) $ do
+ mcurr <- Branch.currentUnsafe g
+ case mcurr of
+ Nothing -> return ()
+ Just curr -> when (any (== curr) modifiedbranches) $ do
+ putStrLn $ unwords
+ [ "You currently have"
+ , fromRef curr
+ , "checked out. You may have staged changes in the index that can be committed to recover the lost state of this branch!"
+ ]
+ putStrLn "Successfully recovered repository!"
+ putStrLn "Please carefully check that the changes mentioned above are ok.."
+ return (True, modifiedbranches)
+
unsuccessfulfinish = do
if repoIsLocalBare g
then do
diff --git a/Limit.hs b/Limit.hs
index 62c5456fe..b46ff1a06 100644
--- a/Limit.hs
+++ b/Limit.hs
@@ -20,7 +20,6 @@ import Types.TrustLevel
import Types.Key
import Types.Group
import Types.FileMatcher
-import Types.Limit
import Types.MetaData
import Logs.MetaData
import Logs.Group
@@ -45,21 +44,20 @@ getMatcher :: Annex (MatchInfo -> Annex Bool)
getMatcher = Utility.Matcher.matchM <$> getMatcher'
getMatcher' :: Annex (Utility.Matcher.Matcher (MatchInfo -> Annex Bool))
-getMatcher' = do
- m <- Annex.getState Annex.limit
- case m of
- Right r -> return r
- Left l -> do
- let matcher = Utility.Matcher.generate (reverse l)
- Annex.changeState $ \s ->
- s { Annex.limit = Right matcher }
- return matcher
+getMatcher' = go =<< Annex.getState Annex.limit
+ where
+ go (CompleteMatcher matcher) = return matcher
+ go (BuildingMatcher l) = do
+ let matcher = Utility.Matcher.generate (reverse l)
+ Annex.changeState $ \s ->
+ s { Annex.limit = CompleteMatcher matcher }
+ return matcher
{- Adds something to the limit list, which is built up reversed. -}
add :: Utility.Matcher.Token (MatchInfo -> Annex Bool) -> Annex ()
add l = Annex.changeState $ \s -> s { Annex.limit = prepend $ Annex.limit s }
where
- prepend (Left ls) = Left $ l:ls
+ prepend (BuildingMatcher ls) = BuildingMatcher $ l:ls
prepend _ = error "internal"
{- Adds a new token. -}
@@ -67,21 +65,21 @@ addToken :: String -> Annex ()
addToken = add . Utility.Matcher.token
{- Adds a new limit. -}
-addLimit :: Either String MatchFiles -> Annex ()
+addLimit :: Either String (MatchFiles Annex) -> Annex ()
addLimit = either error (\l -> add $ Utility.Matcher.Operation $ l S.empty)
{- Add a limit to skip files that do not match the glob. -}
addInclude :: String -> Annex ()
addInclude = addLimit . limitInclude
-limitInclude :: MkLimit
+limitInclude :: MkLimit Annex
limitInclude glob = Right $ const $ return . matchGlobFile glob
{- Add a limit to skip files that match the glob. -}
addExclude :: String -> Annex ()
addExclude = addLimit . limitExclude
-limitExclude :: MkLimit
+limitExclude :: MkLimit Annex
limitExclude glob = Right $ const $ return . not . matchGlobFile glob
matchGlobFile :: String -> (MatchInfo -> Bool)
@@ -94,18 +92,16 @@ matchGlobFile glob = go
{- Adds a limit to skip files not believed to be present
- in a specfied repository. Optionally on a prior date. -}
addIn :: String -> Annex ()
-addIn = addLimit . limitIn
-
-limitIn :: MkLimit
-limitIn s = Right $ \notpresent -> checkKey $ \key ->
- if name == "."
- then if null date
- then inhere notpresent key
- else inuuid notpresent key =<< getUUID
- else inuuid notpresent key =<< Remote.nameToUUID name
+addIn s = addLimit =<< mk
where
(name, date) = separate (== '@') s
- inuuid notpresent key u
+ mk
+ | name == "." = if null date
+ then use inhere
+ else use . inuuid =<< getUUID
+ | otherwise = use . inuuid =<< Remote.nameToUUID name
+ use a = return $ Right $ \notpresent -> checkKey (a notpresent)
+ inuuid u notpresent key
| null date = do
us <- Remote.keyLocations key
return $ u `elem` us && u `S.notMember` notpresent
@@ -121,8 +117,11 @@ limitIn s = Right $ \notpresent -> checkKey $ \key ->
else inAnnex key
{- Limit to content that is currently present on a uuid. -}
-limitPresent :: Maybe UUID -> MkLimit
-limitPresent u _ = Right $ const $ checkKey $ \key -> do
+limitPresent :: Maybe UUID -> MkLimit Annex
+limitPresent u _ = Right $ matchPresent u
+
+matchPresent :: Maybe UUID -> MatchFiles Annex
+matchPresent u _ = checkKey $ \key -> do
hereu <- getUUID
if u == Just hereu || isNothing u
then inAnnex key
@@ -131,7 +130,7 @@ limitPresent u _ = Right $ const $ checkKey $ \key -> do
return $ maybe False (`elem` us) u
{- Limit to content that is in a directory, anywhere in the repository tree -}
-limitInDir :: FilePath -> MkLimit
+limitInDir :: FilePath -> MkLimit Annex
limitInDir dir = const $ Right $ const go
where
go (MatchingFile fi) = return $ elem dir $ splitPath $ takeDirectory $ matchFile fi
@@ -142,7 +141,7 @@ limitInDir dir = const $ Right $ const go
addCopies :: String -> Annex ()
addCopies = addLimit . limitCopies
-limitCopies :: MkLimit
+limitCopies :: MkLimit Annex
limitCopies want = case split ":" want of
[v, n] -> case parsetrustspec v of
Just checker -> go n $ checktrust checker
@@ -168,7 +167,7 @@ limitCopies want = case split ":" want of
addLackingCopies :: Bool -> String -> Annex ()
addLackingCopies approx = addLimit . limitLackingCopies approx
-limitLackingCopies :: Bool -> MkLimit
+limitLackingCopies :: Bool -> MkLimit Annex
limitLackingCopies approx want = case readish want of
Just needed -> Right $ \notpresent mi -> flip checkKey mi $
handle mi needed notpresent
@@ -190,7 +189,7 @@ limitLackingCopies approx want = case readish want of
- This has a nice optimisation: When a file exists,
- its key is obviously not unused.
-}
-limitUnused :: MatchFiles
+limitUnused :: MatchFiles Annex
limitUnused _ (MatchingFile _) = return False
limitUnused _ (MatchingKey k) = S.member k <$> unusedKeys
@@ -201,7 +200,7 @@ addInAllGroup groupname = do
m <- groupMap
addLimit $ limitInAllGroup m groupname
-limitInAllGroup :: GroupMap -> MkLimit
+limitInAllGroup :: GroupMap -> MkLimit Annex
limitInAllGroup m groupname
| S.null want = Right $ const $ const $ return True
| otherwise = Right $ \notpresent -> checkKey $ check notpresent
@@ -218,7 +217,7 @@ limitInAllGroup m groupname
addInBackend :: String -> Annex ()
addInBackend = addLimit . limitInBackend
-limitInBackend :: MkLimit
+limitInBackend :: MkLimit Annex
limitInBackend name = Right $ const $ checkKey check
where
check key = pure $ keyBackendName key == name
@@ -230,7 +229,7 @@ addLargerThan = addLimit . limitSize (>)
addSmallerThan :: String -> Annex ()
addSmallerThan = addLimit . limitSize (<)
-limitSize :: (Maybe Integer -> Maybe Integer -> Bool) -> MkLimit
+limitSize :: (Maybe Integer -> Maybe Integer -> Bool) -> MkLimit Annex
limitSize vs s = case readSize dataUnits s of
Nothing -> Left "bad size"
Just sz -> Right $ go sz
@@ -248,7 +247,7 @@ limitSize vs s = case readSize dataUnits s of
addMetaData :: String -> Annex ()
addMetaData = addLimit . limitMetaData
-limitMetaData :: MkLimit
+limitMetaData :: MkLimit Annex
limitMetaData s = case parseMetaData s of
Left e -> Left e
Right (f, v) ->
diff --git a/Locations.hs b/Locations.hs
index 74cace156..5bff63eaf 100644
--- a/Locations.hs
+++ b/Locations.hs
@@ -41,6 +41,7 @@ module Locations (
gitAnnexMergeDir,
gitAnnexJournalDir,
gitAnnexJournalLock,
+ gitAnnexPreCommitLock,
gitAnnexIndex,
gitAnnexIndexStatus,
gitAnnexViewIndex,
@@ -257,6 +258,10 @@ gitAnnexJournalDir r = addTrailingPathSeparator $ gitAnnexDir r </> "journal"
gitAnnexJournalLock :: Git.Repo -> FilePath
gitAnnexJournalLock r = gitAnnexDir r </> "journal.lck"
+{- Lock file for the pre-commit hook. -}
+gitAnnexPreCommitLock :: Git.Repo -> FilePath
+gitAnnexPreCommitLock r = gitAnnexDir r </> "precommit.lck"
+
{- .git/annex/index is used to stage changes to the git-annex branch -}
gitAnnexIndex :: Git.Repo -> FilePath
gitAnnexIndex r = gitAnnexDir r </> "index"
diff --git a/Logs.hs b/Logs.hs
index 21908a9cf..c9d58157a 100644
--- a/Logs.hs
+++ b/Logs.hs
@@ -24,7 +24,7 @@ getLogVariety :: FilePath -> Maybe LogVariety
getLogVariety f
| f `elem` topLevelUUIDBasedLogs = Just UUIDBasedLog
| isRemoteStateLog f = Just NewUUIDBasedLog
- | isMetaDataLog f || f == numcopiesLog = Just OtherLog
+ | isMetaDataLog f || f `elem` otherLogs = Just OtherLog
| otherwise = PresenceLog <$> firstJust (presenceLogs f)
{- All the uuid-based logs stored in the top of the git-annex branch. -}
@@ -35,6 +35,7 @@ topLevelUUIDBasedLogs =
, trustLog
, groupLog
, preferredContentLog
+ , requiredContentLog
, scheduleLog
]
@@ -45,6 +46,13 @@ presenceLogs f =
, locationLogFileKey f
]
+{- Logs that are neither UUID based nor presence logs. -}
+otherLogs :: [FilePath]
+otherLogs =
+ [ numcopiesLog
+ , groupPreferredContentLog
+ ]
+
uuidLog :: FilePath
uuidLog = "uuid.log"
@@ -63,6 +71,12 @@ groupLog = "group.log"
preferredContentLog :: FilePath
preferredContentLog = "preferred-content.log"
+requiredContentLog :: FilePath
+requiredContentLog = "required-content.log"
+
+groupPreferredContentLog :: FilePath
+groupPreferredContentLog = "group-preferred-content.log"
+
scheduleLog :: FilePath
scheduleLog = "schedule.log"
diff --git a/Logs/FsckResults.hs b/Logs/FsckResults.hs
index 3538bdc40..619dd586c 100644
--- a/Logs/FsckResults.hs
+++ b/Logs/FsckResults.hs
@@ -23,25 +23,31 @@ writeFsckResults u fsckresults = do
logfile <- fromRepo $ gitAnnexFsckResultsLog u
liftIO $
case fsckresults of
- FsckFailed -> store S.empty logfile
- FsckFoundMissing s
+ FsckFailed -> store S.empty False logfile
+ FsckFoundMissing s t
| S.null s -> nukeFile logfile
- | otherwise -> store s logfile
+ | otherwise -> store s t logfile
where
- store s logfile = do
+ store s t logfile = do
createDirectoryIfMissing True (parentDir logfile)
- liftIO $ viaTmp writeFile logfile $ serialize s
- serialize = unlines . map fromRef . S.toList
+ liftIO $ viaTmp writeFile logfile $ serialize s t
+ serialize s t =
+ let ls = map fromRef (S.toList s)
+ in if t
+ then unlines ("truncated":ls)
+ else unlines ls
readFsckResults :: UUID -> Annex FsckResults
readFsckResults u = do
logfile <- fromRepo $ gitAnnexFsckResultsLog u
- liftIO $ catchDefaultIO (FsckFoundMissing S.empty) $
- deserialize <$> readFile logfile
+ liftIO $ catchDefaultIO (FsckFoundMissing S.empty False) $
+ deserialize . lines <$> readFile logfile
where
- deserialize l =
- let s = S.fromList $ map Ref $ lines l
- in if S.null s then FsckFailed else FsckFoundMissing s
+ deserialize ("truncated":ls) = deserialize' ls True
+ deserialize ls = deserialize' ls False
+ deserialize' ls t =
+ let s = S.fromList $ map Ref ls
+ in if S.null s then FsckFailed else FsckFoundMissing s t
clearFsckResults :: UUID -> Annex ()
clearFsckResults = liftIO . nukeFile <=< fromRepo . gitAnnexFsckResultsLog
diff --git a/Logs/MapLog.hs b/Logs/MapLog.hs
new file mode 100644
index 000000000..1725ef953
--- /dev/null
+++ b/Logs/MapLog.hs
@@ -0,0 +1,81 @@
+{- git-annex Map log
+ -
+ - This is used to store a Map, in a way that can be union merged.
+ -
+ - A line of the log will look like: "timestamp field value"
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.MapLog where
+
+import qualified Data.Map as M
+import Data.Time.Clock.POSIX
+import Data.Time
+import System.Locale
+
+import Common
+
+data TimeStamp = Unknown | Date POSIXTime
+ deriving (Eq, Ord, Show)
+
+data LogEntry v = LogEntry
+ { changed :: TimeStamp
+ , value :: v
+ } deriving (Eq, Show)
+
+type MapLog f v = M.Map f (LogEntry v)
+
+showMapLog :: (f -> String) -> (v -> String) -> MapLog f v -> String
+showMapLog fieldshower valueshower = unlines . map showpair . M.toList
+ where
+ showpair (f, LogEntry (Date p) v) =
+ unwords [show p, fieldshower f, valueshower v]
+ showpair (f, LogEntry Unknown v) =
+ unwords ["0", fieldshower f, valueshower v]
+
+parseMapLog :: Ord f => (String -> Maybe f) -> (String -> Maybe v) -> String -> MapLog f v
+parseMapLog fieldparser valueparser = M.fromListWith best . mapMaybe parse . lines
+ where
+ parse line = do
+ let (ts, rest) = splitword line
+ (sf, sv) = splitword rest
+ date <- Date . utcTimeToPOSIXSeconds <$> parseTime defaultTimeLocale "%s%Qs" ts
+ f <- fieldparser sf
+ v <- valueparser sv
+ Just (f, LogEntry date v)
+ splitword = separate (== ' ')
+
+changeMapLog :: Ord f => POSIXTime -> f -> v -> MapLog f v -> MapLog f v
+changeMapLog t f v = M.insert f $ LogEntry (Date t) v
+
+{- Only add an LogEntry if it's newer (or at least as new as) than any
+ - existing LogEntry for a field. -}
+addMapLog :: Ord f => f -> LogEntry v -> MapLog f v -> MapLog f v
+addMapLog = M.insertWith' best
+
+{- Converts a MapLog into a simple Map without the timestamp information.
+ - This is a one-way trip, but useful for code that never needs to change
+ - the log. -}
+simpleMap :: MapLog f v -> M.Map f v
+simpleMap = M.map value
+
+best :: LogEntry v -> LogEntry v -> LogEntry v
+best new old
+ | changed old > changed new = old
+ | otherwise = new
+
+-- Unknown is oldest.
+prop_TimeStamp_sane :: Bool
+prop_TimeStamp_sane = Unknown < Date 1
+
+prop_addMapLog_sane :: Bool
+prop_addMapLog_sane = newWins && newestWins
+ where
+ newWins = addMapLog ("foo") (LogEntry (Date 1) "new") l == l2
+ newestWins = addMapLog ("foo") (LogEntry (Date 1) "newest") l2 /= l2
+
+ l = M.fromList [("foo", LogEntry (Date 0) "old")]
+ l2 = M.fromList [("foo", LogEntry (Date 1) "new")]
diff --git a/Logs/MetaData.hs b/Logs/MetaData.hs
index 6702c3733..b682ca005 100644
--- a/Logs/MetaData.hs
+++ b/Logs/MetaData.hs
@@ -36,26 +36,54 @@ module Logs.MetaData (
import Common.Annex
import Types.MetaData
+import Annex.MetaData.StandardFields
import qualified Annex.Branch
import Logs
import Logs.SingleValue
import qualified Data.Set as S
+import qualified Data.Map as M
import Data.Time.Clock.POSIX
+import Data.Time.Format
+import System.Locale
instance SingleValueSerializable MetaData where
serialize = Types.MetaData.serialize
deserialize = Types.MetaData.deserialize
-getMetaData :: Key -> Annex (Log MetaData)
-getMetaData = readLog . metaDataLogFile
+getMetaDataLog :: Key -> Annex (Log MetaData)
+getMetaDataLog = readLog . metaDataLogFile
{- Go through the log from oldest to newest, and combine it all
- - into a single MetaData representing the current state. -}
+ - into a single MetaData representing the current state.
+ -
+ - Automatically generates a lastchanged metadata for each field that's
+ - currently set, based on timestamps in the log.
+ -}
getCurrentMetaData :: Key -> Annex MetaData
-getCurrentMetaData = currentMetaData . collect <$$> getMetaData
+getCurrentMetaData k = do
+ ls <- S.toAscList <$> getMetaDataLog k
+ let loggedmeta = currentMetaData $ combineMetaData $ map value ls
+ return $ currentMetaData $ unionMetaData loggedmeta
+ (lastchanged ls loggedmeta)
where
- collect = foldl' unionMetaData emptyMetaData . map value . S.toAscList
+ lastchanged [] _ = emptyMetaData
+ lastchanged ls (MetaData currentlyset) =
+ let m = foldl' (flip M.union) M.empty (map genlastchanged ls)
+ in MetaData $
+ -- Add a overall lastchanged using the oldest log
+ -- item (log is in ascending order).
+ M.insert lastChangedField (lastchangedval $ Prelude.last ls) $
+ M.mapKeys mkLastChangedField $
+ -- Only include fields that are currently set.
+ m `M.intersection` currentlyset
+ -- Makes each field have the timestamp as its value.
+ genlastchanged l =
+ let MetaData m = value l
+ ts = lastchangedval l
+ in M.map (const ts) m
+ lastchangedval l = S.singleton $ toMetaValue $ showts $ changed l
+ showts = formatTime defaultTimeLocale "%F@%H-%M-%S" . posixSecondsToUTCTime
{- Adds in some metadata, which can override existing values, or unset
- them, but otherwise leaves any existing metadata as-is. -}
@@ -67,10 +95,12 @@ addMetaData k metadata = addMetaData' k metadata =<< liftIO getPOSIXTime
- will tend to be generated across the different log files, and so
- git will be able to pack the data more efficiently. -}
addMetaData' :: Key -> MetaData -> POSIXTime -> Annex ()
-addMetaData' k metadata now = Annex.Branch.change (metaDataLogFile k) $
+addMetaData' k (MetaData m) now = Annex.Branch.change (metaDataLogFile k) $
showLog . simplifyLog
- . S.insert (LogEntry now metadata)
+ . S.insert (LogEntry now metadata)
. parseLog
+ where
+ metadata = MetaData $ M.filterWithKey (\f _ -> not (isLastChangedField f)) m
{- Simplify a log, removing historical values that are no longer
- needed.
@@ -148,7 +178,7 @@ copyMetaData :: Key -> Key -> Annex ()
copyMetaData oldkey newkey
| oldkey == newkey = noop
| otherwise = do
- l <- getMetaData oldkey
+ l <- getMetaDataLog oldkey
unless (S.null l) $
Annex.Branch.change (metaDataLogFile newkey) $
const $ showLog l
diff --git a/Logs/PreferredContent.hs b/Logs/PreferredContent.hs
index 4b25ea094..ead303f1f 100644
--- a/Logs/PreferredContent.hs
+++ b/Logs/PreferredContent.hs
@@ -1,19 +1,24 @@
{- git-annex preferred content matcher configuration
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Logs.PreferredContent (
- preferredContentLog,
preferredContentSet,
+ requiredContentSet,
+ groupPreferredContentSet,
isPreferredContent,
+ isRequiredContent,
preferredContentMap,
- preferredContentMapLoad,
preferredContentMapRaw,
+ requiredContentMap,
+ requiredContentMapRaw,
+ groupPreferredContentMapRaw,
checkPreferredContentExpression,
setStandardGroup,
+ preferredRequiredMapsLoad,
) where
import qualified Data.Map as M
@@ -26,70 +31,106 @@ import qualified Annex.Branch
import qualified Annex
import Logs
import Logs.UUIDBased
-import qualified Utility.Matcher
+import Utility.Matcher hiding (tokens)
import Annex.FileMatcher
import Annex.UUID
-import Types.Limit
import Types.Group
import Types.Remote (RemoteConfig)
import Logs.Group
import Logs.Remote
+import Types.FileMatcher
import Types.StandardGroups
+import Limit
{- Checks if a file is preferred content for the specified repository
- (or the current repository if none is specified). -}
isPreferredContent :: Maybe UUID -> AssumeNotPresent -> Maybe Key -> AssociatedFile -> Bool -> Annex Bool
-isPreferredContent mu notpresent mkey afile def = do
+isPreferredContent = checkMap preferredContentMap
+
+isRequiredContent :: Maybe UUID -> AssumeNotPresent -> Maybe Key -> AssociatedFile -> Bool -> Annex Bool
+isRequiredContent = checkMap requiredContentMap
+
+checkMap :: Annex (FileMatcherMap Annex) -> Maybe UUID -> AssumeNotPresent -> Maybe Key -> AssociatedFile -> Bool -> Annex Bool
+checkMap getmap mu notpresent mkey afile def = do
u <- maybe getUUID return mu
- m <- preferredContentMap
+ m <- getmap
case M.lookup u m of
Nothing -> return def
Just matcher -> checkMatcher matcher mkey afile notpresent def
-{- The map is cached for speed. -}
-preferredContentMap :: Annex Annex.PreferredContentMap
-preferredContentMap = maybe preferredContentMapLoad return
+preferredContentMap :: Annex (FileMatcherMap Annex)
+preferredContentMap = maybe (fst <$> preferredRequiredMapsLoad) return
=<< Annex.getState Annex.preferredcontentmap
-{- Loads the map, updating the cache. -}
-preferredContentMapLoad :: Annex Annex.PreferredContentMap
-preferredContentMapLoad = do
+requiredContentMap :: Annex (FileMatcherMap Annex)
+requiredContentMap = maybe (snd <$> preferredRequiredMapsLoad) return
+ =<< Annex.getState Annex.requiredcontentmap
+
+preferredRequiredMapsLoad :: Annex (FileMatcherMap Annex, FileMatcherMap Annex)
+preferredRequiredMapsLoad = do
groupmap <- groupMap
configmap <- readRemoteLog
- m <- simpleMap
- . parseLogWithUUID ((Just .) . makeMatcher groupmap configmap)
- <$> Annex.Branch.get preferredContentLog
- Annex.changeState $ \s -> s { Annex.preferredcontentmap = Just m }
- return m
+ let genmap l gm = simpleMap
+ . parseLogWithUUID ((Just .) . makeMatcher groupmap configmap gm)
+ <$> Annex.Branch.get l
+ pc <- genmap preferredContentLog =<< groupPreferredContentMapRaw
+ rc <- genmap requiredContentLog M.empty
+ -- Required content is implicitly also preferred content, so OR
+ let m = M.unionWith MOr pc rc
+ Annex.changeState $ \s -> s
+ { Annex.preferredcontentmap = Just m
+ , Annex.requiredcontentmap = Just rc
+ }
+ return (m, rc)
{- This intentionally never fails, even on unparsable expressions,
- because the configuration is shared among repositories and newer
- - versions of git-annex may add new features. Instead, parse errors
- - result in a Matcher that will always succeed. -}
-makeMatcher :: GroupMap -> M.Map UUID RemoteConfig -> UUID -> PreferredContentExpression -> FileMatcher
-makeMatcher groupmap configmap u expr
- | expr == "standard" = standardMatcher groupmap configmap u
- | null (lefts tokens) = Utility.Matcher.generate $ rights tokens
- | otherwise = matchAll
+ - versions of git-annex may add new features. -}
+makeMatcher
+ :: GroupMap
+ -> M.Map UUID RemoteConfig
+ -> M.Map Group PreferredContentExpression
+ -> UUID
+ -> PreferredContentExpression
+ -> FileMatcher Annex
+makeMatcher groupmap configmap groupwantedmap u = go True True
where
- tokens = exprParser groupmap configmap (Just u) expr
+ go expandstandard expandgroupwanted expr
+ | null (lefts tokens) = generate $ rights tokens
+ | otherwise = unknownMatcher u
+ where
+ tokens = exprParser matchstandard matchgroupwanted groupmap configmap (Just u) expr
+ matchstandard
+ | expandstandard = maybe (unknownMatcher u) (go False False)
+ (standardPreferredContent <$> getStandardGroup mygroups)
+ | otherwise = unknownMatcher u
+ matchgroupwanted
+ | expandgroupwanted = maybe (unknownMatcher u) (go True False)
+ (groupwanted mygroups)
+ | otherwise = unknownMatcher u
+ mygroups = fromMaybe S.empty (u `M.lookup` groupsByUUID groupmap)
+ groupwanted s = case M.elems $ M.filterWithKey (\k _ -> S.member k s) groupwantedmap of
+ [pc] -> Just pc
+ _ -> Nothing
-{- Standard matchers are pre-defined for some groups. If none is defined,
- - or a repository is in multiple groups with standard matchers, match all. -}
-standardMatcher :: GroupMap -> M.Map UUID RemoteConfig -> UUID -> FileMatcher
-standardMatcher groupmap configmap u =
- maybe matchAll (makeMatcher groupmap configmap u . preferredContent) $
- getStandardGroup =<< u `M.lookup` groupsByUUID groupmap
+{- When a preferred content expression cannot be parsed, but is already
+ - in the log (eg, put there by a newer version of git-annex),
+ - the fallback behavior is to match only files that are currently present.
+ -
+ - This avoid unwanted/expensive changes to the content, until the problem
+ - is resolved. -}
+unknownMatcher :: UUID -> FileMatcher Annex
+unknownMatcher u = generate [present]
+ where
+ present = Operation $ matchPresent (Just u)
{- Checks if an expression can be parsed, if not returns Just error -}
checkPreferredContentExpression :: PreferredContentExpression -> Maybe String
-checkPreferredContentExpression expr
- | expr == "standard" = Nothing
- | otherwise = case parsedToMatcher tokens of
- Left e -> Just e
- Right _ -> Nothing
+checkPreferredContentExpression expr = case parsedToMatcher tokens of
+ Left e -> Just e
+ Right _ -> Nothing
where
- tokens = exprParser emptyGroupMap M.empty Nothing expr
+ tokens = exprParser matchAll matchAll emptyGroupMap M.empty Nothing expr
{- Puts a UUID in a standard group, and sets its preferred content to use
- the standard expression for that group, unless something is already set. -}
diff --git a/Logs/PreferredContent/Raw.hs b/Logs/PreferredContent/Raw.hs
index 63f6118e4..bbf5a1edc 100644
--- a/Logs/PreferredContent/Raw.hs
+++ b/Logs/PreferredContent/Raw.hs
@@ -1,6 +1,6 @@
{- unparsed preferred content expressions
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -15,17 +15,48 @@ import qualified Annex.Branch
import qualified Annex
import Logs
import Logs.UUIDBased
+import Logs.MapLog
import Types.StandardGroups
+import Types.Group
{- Changes the preferred content configuration of a remote. -}
preferredContentSet :: UUID -> PreferredContentExpression -> Annex ()
-preferredContentSet uuid@(UUID _) val = do
+preferredContentSet = setLog preferredContentLog
+
+requiredContentSet :: UUID -> PreferredContentExpression -> Annex ()
+requiredContentSet = setLog requiredContentLog
+
+setLog :: FilePath -> UUID -> PreferredContentExpression -> Annex ()
+setLog logfile uuid@(UUID _) val = do
+ ts <- liftIO getPOSIXTime
+ Annex.Branch.change logfile $
+ showLog id
+ . changeLog ts uuid val
+ . parseLog Just
+ Annex.changeState $ \s -> s
+ { Annex.preferredcontentmap = Nothing
+ , Annex.requiredcontentmap = Nothing
+ }
+setLog _ NoUUID _ = error "unknown UUID; cannot modify"
+
+{- Changes the preferred content configuration of a group. -}
+groupPreferredContentSet :: Group -> PreferredContentExpression -> Annex ()
+groupPreferredContentSet g val = do
ts <- liftIO getPOSIXTime
- Annex.Branch.change preferredContentLog $
- showLog id . changeLog ts uuid val . parseLog Just
+ Annex.Branch.change groupPreferredContentLog $
+ showMapLog id id
+ . changeMapLog ts g val
+ . parseMapLog Just Just
Annex.changeState $ \s -> s { Annex.preferredcontentmap = Nothing }
-preferredContentSet NoUUID _ = error "unknown UUID; cannot modify"
preferredContentMapRaw :: Annex (M.Map UUID PreferredContentExpression)
preferredContentMapRaw = simpleMap . parseLog Just
<$> Annex.Branch.get preferredContentLog
+
+requiredContentMapRaw :: Annex (M.Map UUID PreferredContentExpression)
+requiredContentMapRaw = simpleMap . parseLog Just
+ <$> Annex.Branch.get requiredContentLog
+
+groupPreferredContentMapRaw :: Annex (M.Map Group PreferredContentExpression)
+groupPreferredContentMapRaw = simpleMap . parseMapLog Just Just
+ <$> Annex.Branch.get groupPreferredContentLog
diff --git a/Logs/Transfer.hs b/Logs/Transfer.hs
index 742bdc7b9..c96d9cd1e 100644
--- a/Logs/Transfer.hs
+++ b/Logs/Transfer.hs
@@ -88,108 +88,6 @@ percentComplete :: Transfer -> TransferInfo -> Maybe Percentage
percentComplete (Transfer { transferKey = key }) info =
percentage <$> keySize key <*> Just (fromMaybe 0 $ bytesComplete info)
-type RetryDecider = TransferInfo -> TransferInfo -> Bool
-
-noRetry :: RetryDecider
-noRetry _ _ = False
-
-{- Retries a transfer when it fails, as long as the failed transfer managed
- - to send some data. -}
-forwardRetry :: RetryDecider
-forwardRetry old new = bytesComplete old < bytesComplete new
-
-upload :: UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
-upload u key = runTransfer (Transfer Upload u key)
-
-download :: UUID -> Key -> AssociatedFile -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
-download u key = runTransfer (Transfer Download u key)
-
-{- Runs a transfer action. Creates and locks the lock file while the
- - action is running, and stores info in the transfer information
- - file.
- -
- - If the transfer action returns False, the transfer info is
- - left in the failedTransferDir.
- -
- - If the transfer is already in progress, returns False.
- -
- - An upload can be run from a read-only filesystem, and in this case
- - no transfer information or lock file is used.
- -}
-runTransfer :: Transfer -> Maybe FilePath -> RetryDecider -> (MeterUpdate -> Annex Bool) -> Annex Bool
-runTransfer t file shouldretry a = do
- info <- liftIO $ startTransferInfo file
- (meter, tfile, metervar) <- mkProgressUpdater t info
- mode <- annexFileMode
- (fd, inprogress) <- liftIO $ prep tfile mode info
- if inprogress
- then do
- showNote "transfer already in progress"
- return False
- else do
- ok <- retry info metervar $
- bracketIO (return fd) (cleanup tfile) (const $ a meter)
- unless ok $ recordFailedTransfer t info
- return ok
- where
-#ifndef mingw32_HOST_OS
- prep tfile mode info = do
- mfd <- catchMaybeIO $
- openFd (transferLockFile tfile) ReadWrite (Just mode)
- defaultFileFlags { trunc = True }
- case mfd of
- Nothing -> return (Nothing, False)
- Just fd -> do
- locked <- catchMaybeIO $
- setLock fd (WriteLock, AbsoluteSeek, 0, 0)
- if isNothing locked
- then return (Nothing, True)
- else do
- void $ tryIO $ writeTransferInfoFile info tfile
- return (mfd, False)
-#else
- prep tfile _mode info = do
- v <- catchMaybeIO $ lockExclusive (transferLockFile tfile)
- case v of
- Nothing -> return (Nothing, False)
- Just Nothing -> return (Nothing, True)
- Just (Just lockhandle) -> do
- void $ tryIO $ writeTransferInfoFile info tfile
- return (Just lockhandle, False)
-#endif
- cleanup _ Nothing = noop
- cleanup tfile (Just lockhandle) = do
- void $ tryIO $ removeFile tfile
-#ifndef mingw32_HOST_OS
- void $ tryIO $ removeFile $ transferLockFile tfile
- closeFd lockhandle
-#else
- {- Windows cannot delete the lockfile until the lock
- - is closed. So it's possible to race with another
- - process that takes the lock before it's removed,
- - so ignore failure to remove.
- -}
- dropLock lockhandle
- void $ tryIO $ removeFile $ transferLockFile tfile
-#endif
- retry oldinfo metervar run = do
- v <- tryAnnex run
- case v of
- Right b -> return b
- Left _ -> do
- b <- getbytescomplete metervar
- let newinfo = oldinfo { bytesComplete = Just b }
- if shouldretry oldinfo newinfo
- then retry newinfo metervar run
- else return False
- getbytescomplete metervar
- | transferDirection t == Upload =
- liftIO $ readMVar metervar
- | otherwise = do
- f <- fromRepo $ gitAnnexTmpObjectLocation (transferKey t)
- liftIO $ catchDefaultIO 0 $
- fromIntegral . fileSize <$> getFileStatus f
-
{- Generates a callback that can be called as transfer progresses to update
- the transfer info file. Also returns the file it'll be updating, and a
- MVar that can be used to read the number of bytesComplete. -}
diff --git a/Logs/UUIDBased.hs b/Logs/UUIDBased.hs
index 430c92d55..b403b6253 100644
--- a/Logs/UUIDBased.hs
+++ b/Logs/UUIDBased.hs
@@ -26,9 +26,6 @@ module Logs.UUIDBased (
changeLog,
addLog,
simpleMap,
-
- prop_TimeStamp_sane,
- prop_addLog_sane,
) where
import qualified Data.Map as M
@@ -38,21 +35,11 @@ import System.Locale
import Common
import Types.UUID
+import Logs.MapLog
-data TimeStamp = Unknown | Date POSIXTime
- deriving (Eq, Ord, Show)
-
-data LogEntry a = LogEntry
- { changed :: TimeStamp
- , value :: a
- } deriving (Eq, Show)
-
-type Log a = M.Map UUID (LogEntry a)
+type Log v = MapLog UUID v
-tskey :: String
-tskey = "timestamp="
-
-showLog :: (a -> String) -> Log a -> String
+showLog :: (v -> String) -> Log v -> String
showLog shower = unlines . map showpair . M.toList
where
showpair (k, LogEntry (Date p) v) =
@@ -60,14 +47,6 @@ showLog shower = unlines . map showpair . M.toList
showpair (k, LogEntry Unknown v) =
unwords [fromUUID k, shower v]
-showLogNew :: (a -> String) -> Log a -> String
-showLogNew shower = unlines . map showpair . M.toList
- where
- showpair (k, LogEntry (Date p) v) =
- unwords [show p, fromUUID k, shower v]
- showpair (k, LogEntry Unknown v) =
- unwords ["0", fromUUID k, shower v]
-
parseLog :: (String -> Maybe a) -> String -> Log a
parseLog = parseLogWithUUID . const
@@ -98,45 +77,17 @@ parseLogWithUUID parser = M.fromListWith best . mapMaybe parse . lines
Nothing -> Unknown
Just d -> Date $ utcTimeToPOSIXSeconds d
-parseLogNew :: (String -> Maybe a) -> String -> Log a
-parseLogNew parser = M.fromListWith best . mapMaybe parse . lines
- where
- parse line = do
- let (ts, rest) = splitword line
- (u, v) = splitword rest
- date <- Date . utcTimeToPOSIXSeconds <$> parseTime defaultTimeLocale "%s%Qs" ts
- val <- parser v
- Just (toUUID u, LogEntry date val)
- splitword = separate (== ' ')
-
-changeLog :: POSIXTime -> UUID -> a -> Log a -> Log a
-changeLog t u v = M.insert u $ LogEntry (Date t) v
-
-{- Only add an LogEntry if it's newer (or at least as new as) than any
- - existing LogEntry for a UUID. -}
-addLog :: UUID -> LogEntry a -> Log a -> Log a
-addLog = M.insertWith' best
+showLogNew :: (v -> String) -> Log v -> String
+showLogNew = showMapLog fromUUID
-{- Converts a Log into a simple Map without the timestamp information.
- - This is a one-way trip, but useful for code that never needs to change
- - the log. -}
-simpleMap :: Log a -> M.Map UUID a
-simpleMap = M.map value
+parseLogNew :: (String -> Maybe v) -> String -> Log v
+parseLogNew = parseMapLog (Just . toUUID)
-best :: LogEntry a -> LogEntry a -> LogEntry a
-best new old
- | changed old > changed new = old
- | otherwise = new
+changeLog :: POSIXTime -> UUID -> v -> Log v -> Log v
+changeLog = changeMapLog
--- Unknown is oldest.
-prop_TimeStamp_sane :: Bool
-prop_TimeStamp_sane = Unknown < Date 1
+addLog :: UUID -> LogEntry v -> Log v -> Log v
+addLog = addMapLog
-prop_addLog_sane :: Bool
-prop_addLog_sane = newWins && newestWins
- where
- newWins = addLog (UUID "foo") (LogEntry (Date 1) "new") l == l2
- newestWins = addLog (UUID "foo") (LogEntry (Date 1) "newest") l2 /= l2
-
- l = M.fromList [(UUID "foo", LogEntry (Date 0) "old")]
- l2 = M.fromList [(UUID "foo", LogEntry (Date 1) "new")]
+tskey :: String
+tskey = "timestamp="
diff --git a/Logs/Unused.hs b/Logs/Unused.hs
index d26d37dca..cadf7ed9d 100644
--- a/Logs/Unused.hs
+++ b/Logs/Unused.hs
@@ -67,7 +67,7 @@ updateUnusedLog prefix m = do
writeUnusedLog :: FilePath -> UnusedLog -> Annex ()
writeUnusedLog prefix l = do
logfile <- fromRepo $ gitAnnexUnusedLog prefix
- liftIO $ viaTmp writeFile logfile $ unlines $ map format $ M.toList l
+ liftIO $ viaTmp writeFileAnyEncoding logfile $ unlines $ map format $ M.toList l
where
format (k, (i, Just t)) = show i ++ " " ++ key2file k ++ " " ++ show t
format (k, (i, Nothing)) = show i ++ " " ++ key2file k
@@ -77,7 +77,7 @@ readUnusedLog prefix = do
f <- fromRepo $ gitAnnexUnusedLog prefix
ifM (liftIO $ doesFileExist f)
( M.fromList . mapMaybe parse . lines
- <$> liftIO (readFile f)
+ <$> liftIO (readFileStrictAnyEncoding f)
, return M.empty
)
where
@@ -99,7 +99,6 @@ dateUnusedLog prefix = do
f <- fromRepo $ gitAnnexUnusedLog prefix
liftIO $ catchMaybeIO $ getModificationTime f
#else
-#warning foo
-- old ghc's getModificationTime returned a ClockTime
dateUnusedLog _prefix = return Nothing
#endif
diff --git a/Makefile b/Makefile
index 50d1acd9a..45b9a578b 100644
--- a/Makefile
+++ b/Makefile
@@ -119,7 +119,7 @@ linuxstandalone-nobuild: Build/Standalone Build/LinuxMkLibs
strip "$(LINUXSTANDALONE_DEST)/bin/git-annex"
ln -sf git-annex "$(LINUXSTANDALONE_DEST)/bin/git-annex-shell"
zcat standalone/licences.gz > $(LINUXSTANDALONE_DEST)/LICENSE
- cp doc/favicon.png doc/logo.svg $(LINUXSTANDALONE_DEST)
+ cp doc/logo_16x16.png doc/logo.svg $(LINUXSTANDALONE_DEST)
./Build/Standalone "$(LINUXSTANDALONE_DEST)"
diff --git a/Remote.hs b/Remote.hs
index 5fc6d1c00..0f31b99b2 100644
--- a/Remote.hs
+++ b/Remote.hs
@@ -37,6 +37,7 @@ module Remote (
keyPossibilities,
keyPossibilitiesTrusted,
nameToUUID,
+ nameToUUID',
showTriedRemotes,
showLocations,
forceTrust,
@@ -48,7 +49,6 @@ module Remote (
import qualified Data.Map as M
import Text.JSON
import Text.JSON.Generic
-import Data.Tuple
import Data.Ord
import Common.Annex
@@ -121,23 +121,25 @@ noRemoteUUIDMsg r = "cannot determine uuid for " ++ name r
- and returns its UUID. Finds even repositories that are not
- configured in .git/config. -}
nameToUUID :: RemoteName -> Annex UUID
-nameToUUID "." = getUUID -- special case for current repo
-nameToUUID "here" = getUUID
-nameToUUID "" = error "no remote specified"
-nameToUUID n = byName' n >>= go
+nameToUUID = either error return <=< nameToUUID'
+
+nameToUUID' :: RemoteName -> Annex (Either String UUID)
+nameToUUID' "." = Right <$> getUUID -- special case for current repo
+nameToUUID' "here" = Right <$> getUUID
+nameToUUID' n = byName' n >>= go
where
- go (Right r) = case uuid r of
- NoUUID -> error $ noRemoteUUIDMsg r
- u -> return u
- go (Left e) = fromMaybe (error e) <$> bydescription
- bydescription = do
+ go (Right r) = return $ case uuid r of
+ NoUUID -> Left $ noRemoteUUIDMsg r
+ u -> Right u
+ go (Left e) = do
m <- uuidMap
- case M.lookup n $ transform swap m of
- Just u -> return $ Just u
- Nothing -> return $ byuuid m
- byuuid m = M.lookup (toUUID n) $ transform double m
- transform a = M.fromList . map a . M.toList
- double (a, _) = (a, a)
+ return $ case M.keys (M.filter (== n) m) of
+ [u] -> Right u
+ [] -> let u = toUUID n
+ in case M.keys (M.filterWithKey (\k _ -> k == u) m) of
+ [] -> Left e
+ _ -> Right u
+ _us -> Left "Found multiple repositories with that description"
{- Pretty-prints a list of UUIDs of remotes, for human display.
-
diff --git a/Remote/External.hs b/Remote/External.hs
index 50a0767ea..9be9175c7 100644
--- a/Remote/External.hs
+++ b/Remote/External.hs
@@ -11,6 +11,7 @@ import Remote.External.Types
import qualified Annex
import Common.Annex
import Types.Remote
+import Types.CleanupActions
import qualified Git
import Config
import Remote.Helper.Special
@@ -43,7 +44,7 @@ remote = RemoteType {
gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = do
external <- newExternal externaltype u c
- Annex.addCleanup (fromUUID u) $ stopExternal external
+ Annex.addCleanup (RemoteCleanup u) $ stopExternal external
cst <- getCost external r gc
avail <- getAvailability external r gc
return $ Just $ encryptableRemote c
diff --git a/Remote/Git.hs b/Remote/Git.hs
index 14157f498..209312d67 100644
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -24,7 +24,7 @@ import qualified Git.Command
import qualified Git.GCrypt
import qualified Annex
import Logs.Presence
-import Logs.Transfer
+import Annex.Transfer
import Annex.UUID
import Annex.Exception
import qualified Annex.Content
@@ -36,6 +36,7 @@ import Config
import Config.Cost
import Annex.Init
import Types.Key
+import Types.CleanupActions
import qualified CmdLine.GitAnnexShell.Fields as Fields
import Logs.Location
import Utility.Metered
@@ -320,7 +321,7 @@ copyFromRemote' r key file dest
case v of
Nothing -> return False
Just (object, checksuccess) ->
- upload u key file noRetry
+ runTransfer (Transfer Download u key) file noRetry
(rsyncOrCopyFile params object dest)
<&&> checksuccess
| Git.repoIsSsh (repo r) = feedprogressback $ \feeder -> do
@@ -417,7 +418,7 @@ copyToRemote r key file p
( return True
, do
ensureInitialized
- download u key file noRetry $ const $
+ runTransfer (Transfer Download u key) file noRetry $ const $
Annex.Content.saveState True `after`
Annex.Content.getViaTmpChecked (liftIO checksuccessio) key
(\d -> rsyncOrCopyFile params object d p)
@@ -510,7 +511,7 @@ rsyncOrCopyFile rsyncparams src dest p =
commitOnCleanup :: Remote -> Annex a -> Annex a
commitOnCleanup r a = go `after` a
where
- go = Annex.addCleanup (Git.repoLocation $ repo r) cleanup
+ go = Annex.addCleanup (RemoteCleanup $ uuid r) cleanup
cleanup
| not $ Git.repoIsUrl (repo r) = onLocal r $
doQuietSideAction $
diff --git a/Remote/Glacier.hs b/Remote/Glacier.hs
index fe6f53a77..eb274714b 100644
--- a/Remote/Glacier.hs
+++ b/Remote/Glacier.hs
@@ -82,7 +82,7 @@ glacierSetup' enabling u c = do
unless enabling $
genVault fullconfig u
gitConfigSpecialRemote u fullconfig "glacier" "true"
- return (c', u)
+ return (fullconfig, u)
where
remotename = fromJust (M.lookup "name" c)
defvault = remotename ++ "-" ++ fromUUID u
@@ -225,7 +225,8 @@ glacierParams :: RemoteConfig -> [CommandParam] -> [CommandParam]
glacierParams c params = datacenter:params
where
datacenter = Param $ "--region=" ++
- fromJust (M.lookup "datacenter" c)
+ fromMaybe (error "Missing datacenter configuration")
+ (M.lookup "datacenter" c)
glacierEnv :: RemoteConfig -> UUID -> Annex (Maybe [(String, String)])
glacierEnv c u = go =<< getRemoteCredPairFor "glacier" c creds
@@ -239,7 +240,8 @@ glacierEnv c u = go =<< getRemoteCredPairFor "glacier" c creds
(uk, pk) = credPairEnvironment creds
getVault :: RemoteConfig -> Vault
-getVault = fromJust . M.lookup "vault"
+getVault = fromMaybe (error "Missing vault configuration")
+ . M.lookup "vault"
archive :: Remote -> Key -> Archive
archive r k = fileprefix ++ key2file k
diff --git a/Remote/Helper/Hooks.hs b/Remote/Helper/Hooks.hs
index f876649f0..b7deae577 100644
--- a/Remote/Helper/Hooks.hs
+++ b/Remote/Helper/Hooks.hs
@@ -13,6 +13,7 @@ import qualified Data.Map as M
import Common.Annex
import Types.Remote
+import Types.CleanupActions
import qualified Annex
import Annex.LockPool
#ifndef mingw32_HOST_OS
@@ -74,7 +75,7 @@ runHooks r starthook stophook a = do
-- So, requiring idempotency is the right approach.
run starthook
- Annex.addCleanup (remoteid ++ "-stop-command") $ runstop lck
+ Annex.addCleanup (StopHook $ uuid r) $ runstop lck
runstop lck = do
-- Drop any shared lock we have, and take an
-- exclusive lock, without blocking. If the lock
diff --git a/Remote/Rsync.hs b/Remote/Rsync.hs
index 8f00a767e..7d051d6cd 100644
--- a/Remote/Rsync.hs
+++ b/Remote/Rsync.hs
@@ -28,6 +28,7 @@ import Annex.UUID
import Annex.Ssh
import Remote.Helper.Special
import Remote.Helper.Encryptable
+import Remote.Rsync.RsyncUrl
import Crypto
import Utility.Rsync
import Utility.CopyFile
@@ -40,16 +41,6 @@ import Types.Creds
import qualified Data.ByteString.Lazy as L
import qualified Data.Map as M
-type RsyncUrl = String
-
-data RsyncOpts = RsyncOpts
- { rsyncUrl :: RsyncUrl
- , rsyncOptions :: [CommandParam]
- , rsyncUploadOptions :: [CommandParam]
- , rsyncDownloadOptions :: [CommandParam]
- , rsyncShellEscape :: Bool
-}
-
remote :: RemoteType
remote = RemoteType {
typename = "rsync",
@@ -148,17 +139,6 @@ rsyncSetup mu _ c = do
gitConfigSpecialRemote u c' "rsyncurl" url
return (c', u)
-rsyncEscape :: RsyncOpts -> String -> String
-rsyncEscape o s
- | rsyncShellEscape o && rsyncUrlIsShell (rsyncUrl o) = shellEscape s
- | otherwise = s
-
-rsyncUrls :: RsyncOpts -> Key -> [String]
-rsyncUrls o k = map use annexHashes
- where
- use h = rsyncUrl o </> h k </> rsyncEscape o (f </> f)
- f = keyFile k
-
store :: RsyncOpts -> Key -> AssociatedFile -> MeterUpdate -> Annex Bool
store o k _f p = sendAnnex k (void $ remove o k) $ rsyncSend o p k False
diff --git a/Remote/Rsync/RsyncUrl.hs b/Remote/Rsync/RsyncUrl.hs
new file mode 100644
index 000000000..61bbe2f3f
--- /dev/null
+++ b/Remote/Rsync/RsyncUrl.hs
@@ -0,0 +1,46 @@
+{- Rsync urls.
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Remote.Rsync.RsyncUrl where
+
+import Types
+import Locations
+import Utility.Rsync
+import Utility.SafeCommand
+
+import System.FilePath.Posix
+#ifdef mingw32_HOST_OS
+import Data.String.Utils
+#endif
+
+type RsyncUrl = String
+
+data RsyncOpts = RsyncOpts
+ { rsyncUrl :: RsyncUrl
+ , rsyncOptions :: [CommandParam]
+ , rsyncUploadOptions :: [CommandParam]
+ , rsyncDownloadOptions :: [CommandParam]
+ , rsyncShellEscape :: Bool
+}
+
+rsyncEscape :: RsyncOpts -> RsyncUrl -> RsyncUrl
+rsyncEscape o u
+ | rsyncShellEscape o && rsyncUrlIsShell (rsyncUrl o) = shellEscape u
+ | otherwise = u
+
+rsyncUrls :: RsyncOpts -> Key -> [RsyncUrl]
+rsyncUrls o k = map use annexHashes
+ where
+ use h = rsyncUrl o </> hash h </> rsyncEscape o (f </> f)
+ f = keyFile k
+#ifndef mingw32_HOST_OS
+ hash h = h k
+#else
+ hash h = replace "\\" "/" (h k)
+#endif
diff --git a/Remote/Tahoe.hs b/Remote/Tahoe.hs
index 56a17eb62..d265d7ac1 100644
--- a/Remote/Tahoe.hs
+++ b/Remote/Tahoe.hs
@@ -216,7 +216,7 @@ readTahoe hdl command params = withTahoeConfigDir hdl $ \configdir ->
tahoeParams :: TahoeConfigDir -> String -> [CommandParam] -> [CommandParam]
tahoeParams configdir command params =
- Param command : Param "-d" : File configdir : params
+ Param "-d" : File configdir : Param command : params
storeCapability :: UUID -> Key -> Capability -> Annex ()
storeCapability u k cap = setRemoteState u k cap
diff --git a/Test.hs b/Test.hs
index 0f52abf6c..8fbaf1d94 100644
--- a/Test.hs
+++ b/Test.hs
@@ -17,12 +17,14 @@ import Test.Tasty.Ingredients.Rerun
import Data.Monoid
import Options.Applicative hiding (command)
+#if MIN_VERSION_optparse_applicative(0,8,0)
+import qualified Options.Applicative.Types as Opt
+#endif
import Control.Exception.Extensible
import qualified Data.Map as M
import System.IO.HVFS (SystemFS(..))
import qualified Text.JSON
import System.Path
-import qualified Data.ByteString.Lazy as L
import Common
@@ -43,7 +45,7 @@ import qualified Types.Backend
import qualified Types.TrustLevel
import qualified Types
import qualified Logs
-import qualified Logs.UUIDBased
+import qualified Logs.MapLog
import qualified Logs.Trust
import qualified Logs.Remote
import qualified Logs.Unused
@@ -104,8 +106,7 @@ main ps = do
-- parameters is "test".
let pinfo = info (helper <*> suiteOptionParser ingredients tests)
( fullDesc <> header "Builtin test suite" )
- opts <- either (\f -> error =<< errMessage f "git-annex test") return $
- execParserPure (prefs idm) pinfo ps
+ opts <- parseOpts (prefs idm) pinfo ps
case tryIngredients ingredients opts tests of
Nothing -> error "No tests found!?"
Just act -> ifM act
@@ -115,6 +116,18 @@ main ps = do
putStrLn " with utilities, such as git, installed on this system.)"
exitFailure
)
+ where
+ progdesc = "git-annex test"
+ parseOpts pprefs pinfo args =
+#if MIN_VERSION_optparse_applicative(0,8,0)
+ pure $ case execParserPure pprefs pinfo args of
+ Opt.Success v -> v
+ Opt.Failure f -> error $ fst $ Opt.execFailure f progdesc
+ Opt.CompletionInvoked _ -> error "completion not supported"
+#else
+ either (error <=< flip errMessage progdesc) return $
+ execParserPure pprefs pinfo args
+#endif
ingredients :: [Ingredient]
ingredients =
@@ -140,8 +153,8 @@ properties = localOption (QuickCheckTests 1000) $ testGroup "QuickCheck"
, testProperty "prop_cost_sane" Config.Cost.prop_cost_sane
, testProperty "prop_matcher_sane" Utility.Matcher.prop_matcher_sane
, testProperty "prop_HmacSha1WithCipher_sane" Crypto.prop_HmacSha1WithCipher_sane
- , testProperty "prop_TimeStamp_sane" Logs.UUIDBased.prop_TimeStamp_sane
- , testProperty "prop_addLog_sane" Logs.UUIDBased.prop_addLog_sane
+ , testProperty "prop_TimeStamp_sane" Logs.MapLog.prop_TimeStamp_sane
+ , testProperty "prop_addMapLog_sane" Logs.MapLog.prop_addMapLog_sane
, testProperty "prop_verifiable_sane" Utility.Verifiable.prop_verifiable_sane
, testProperty "prop_segment_regressionTest" Utility.Misc.prop_segment_regressionTest
, testProperty "prop_read_write_transferinfo" Logs.Transfer.prop_read_write_transferinfo
@@ -1272,7 +1285,7 @@ test_add_subdirs env = intmpclonerepo env $ do
{- Regression test for Windows bug where symlinks were not
- calculated correctly for files in subdirs. -}
git_annex env "sync" [] @? "sync failed"
- l <- annexeval $ encodeW8 . L.unpack <$> Annex.CatFile.catObject (Git.Types.Ref "HEAD:dir/foo")
+ l <- annexeval $ decodeBS <$> Annex.CatFile.catObject (Git.Types.Ref "HEAD:dir/foo")
"../.git/annex/" `isPrefixOf` l @? ("symlink from subdir to .git/annex is wrong: " ++ l)
createDirectory "dir2"
diff --git a/Types/CleanupActions.hs b/Types/CleanupActions.hs
new file mode 100644
index 000000000..498d5b4d7
--- /dev/null
+++ b/Types/CleanupActions.hs
@@ -0,0 +1,17 @@
+{- Enumeration of cleanup actions
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Types.CleanupActions where
+
+import Types.UUID
+
+data CleanupAction
+ = RemoteCleanup UUID
+ | StopHook UUID
+ | FsckCleanup
+ | SshCachingCleanup
+ deriving (Eq, Ord)
diff --git a/Types/DesktopNotify.hs b/Types/DesktopNotify.hs
new file mode 100644
index 000000000..f8494487d
--- /dev/null
+++ b/Types/DesktopNotify.hs
@@ -0,0 +1,27 @@
+{- git-annex DesktopNotify type
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Types.DesktopNotify where
+
+import Data.Monoid
+
+data DesktopNotify = DesktopNotify
+ { notifyStart :: Bool
+ , notifyFinish :: Bool
+ }
+ deriving (Show)
+
+instance Monoid DesktopNotify where
+ mempty = DesktopNotify False False
+ mappend (DesktopNotify s1 f1) (DesktopNotify s2 f2) =
+ DesktopNotify (s1 || s2) (f1 || f2)
+
+mkNotifyStart :: DesktopNotify
+mkNotifyStart = DesktopNotify True False
+
+mkNotifyFinish :: DesktopNotify
+mkNotifyFinish = DesktopNotify False True
diff --git a/Types/FileMatcher.hs b/Types/FileMatcher.hs
index e2d4eadc1..03a86a38c 100644
--- a/Types/FileMatcher.hs
+++ b/Types/FileMatcher.hs
@@ -7,7 +7,12 @@
module Types.FileMatcher where
+import Types.UUID (UUID)
import Types.Key (Key)
+import Utility.Matcher (Matcher, Token)
+
+import qualified Data.Map as M
+import qualified Data.Set as S
data MatchInfo
= MatchingFile FileInfo
@@ -17,3 +22,19 @@ data FileInfo = FileInfo
{ relFile :: FilePath -- may be relative to cwd
, matchFile :: FilePath -- filepath to match on; may be relative to top
}
+
+type FileMatcherMap a = M.Map UUID (Utility.Matcher.Matcher (S.Set UUID -> MatchInfo -> a Bool))
+
+type MkLimit a = String -> Either String (MatchFiles a)
+
+type AssumeNotPresent = S.Set UUID
+
+type MatchFiles a = AssumeNotPresent -> MatchInfo -> a Bool
+
+type FileMatcher a = Matcher (MatchFiles a)
+
+-- This is a matcher that can have tokens added to it while it's being
+-- built, and once complete is compiled to an unchangable matcher.
+data ExpandableMatcher a
+ = BuildingMatcher [Token (MatchInfo -> a Bool)]
+ | CompleteMatcher (Matcher (MatchInfo -> a Bool))
diff --git a/Types/Limit.hs b/Types/Limit.hs
deleted file mode 100644
index 2b009a758..000000000
--- a/Types/Limit.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-{- types for limits
- -
- - Copyright 2013 Joey Hess <joey@kitenet.net>
- -
- - Licensed under the GNU GPL version 3 or higher.
- -}
-
-{-# LANGUAGE CPP #-}
-
-module Types.Limit where
-
-import Common.Annex
-import Types.FileMatcher
-
-import qualified Data.Set as S
-
-type MkLimit = String -> Either String MatchFiles
-
-type AssumeNotPresent = S.Set UUID
-type MatchFiles = AssumeNotPresent -> MatchInfo -> Annex Bool
diff --git a/Types/MetaData.hs b/Types/MetaData.hs
index c37b31c51..8df56734d 100644
--- a/Types/MetaData.hs
+++ b/Types/MetaData.hs
@@ -28,6 +28,7 @@ module Types.MetaData (
emptyMetaData,
updateMetaData,
unionMetaData,
+ combineMetaData,
differenceMetaData,
isSet,
currentMetaData,
@@ -140,7 +141,7 @@ toMetaField f
- that would break views.
-
- So, require they have an alphanumeric first letter, with the remainder
- - being either alphanumeric or a small set of shitelisted common punctuation.
+ - being either alphanumeric or a small set of whitelisted common punctuation.
-}
legalField :: String -> Bool
legalField [] = False
@@ -188,6 +189,9 @@ unionMetaData :: MetaData -> MetaData -> MetaData
unionMetaData (MetaData old) (MetaData new) = MetaData $
M.unionWith S.union new old
+combineMetaData :: [MetaData] -> MetaData
+combineMetaData = foldl' unionMetaData emptyMetaData
+
differenceMetaData :: MetaData -> MetaData -> MetaData
differenceMetaData (MetaData m) (MetaData excludem) = MetaData $
M.differenceWith diff m excludem
@@ -260,7 +264,9 @@ parseMetaData p = (,)
instance Arbitrary MetaData where
arbitrary = do
size <- arbitrarySizedBoundedIntegral `suchThat` (< 500)
- MetaData . M.fromList <$> vector size
+ MetaData . M.filterWithKey legal . M.fromList <$> vector size
+ where
+ legal k _v = legalField $ fromMetaField k
instance Arbitrary MetaValue where
arbitrary = MetaValue <$> arbitrary <*> arbitrary
diff --git a/Types/StandardGroups.hs b/Types/StandardGroups.hs
index 2f5cd4b30..37ba6e9c6 100644
--- a/Types/StandardGroups.hs
+++ b/Types/StandardGroups.hs
@@ -8,6 +8,7 @@
module Types.StandardGroups where
import Types.Remote (RemoteConfig)
+import Types.Group
import qualified Data.Map as M
import Data.Maybe
@@ -27,7 +28,7 @@ data StandardGroup
| UnwantedGroup
deriving (Eq, Ord, Enum, Bounded, Show)
-fromStandardGroup :: StandardGroup -> String
+fromStandardGroup :: StandardGroup -> Group
fromStandardGroup ClientGroup = "client"
fromStandardGroup TransferGroup = "transfer"
fromStandardGroup BackupGroup = "backup"
@@ -39,7 +40,7 @@ fromStandardGroup ManualGroup = "manual"
fromStandardGroup PublicGroup = "public"
fromStandardGroup UnwantedGroup = "unwanted"
-toStandardGroup :: String -> Maybe StandardGroup
+toStandardGroup :: Group -> Maybe StandardGroup
toStandardGroup "client" = Just ClientGroup
toStandardGroup "transfer" = Just TransferGroup
toStandardGroup "backup" = Just BackupGroup
@@ -77,21 +78,21 @@ specialRemoteOnly PublicGroup = True
specialRemoteOnly _ = False
{- See doc/preferred_content.mdwn for explanations of these expressions. -}
-preferredContent :: StandardGroup -> PreferredContentExpression
-preferredContent ClientGroup = lastResort $
+standardPreferredContent :: StandardGroup -> PreferredContentExpression
+standardPreferredContent ClientGroup = lastResort $
"((exclude=*/archive/* and exclude=archive/*) or (" ++ notArchived ++ ")) and not unused"
-preferredContent TransferGroup = lastResort $
- "not (inallgroup=client and copies=client:2) and (" ++ preferredContent ClientGroup ++ ")"
-preferredContent BackupGroup = "include=* or unused"
-preferredContent IncrementalBackupGroup = lastResort
+standardPreferredContent TransferGroup = lastResort $
+ "not (inallgroup=client and copies=client:2) and (" ++ standardPreferredContent ClientGroup ++ ")"
+standardPreferredContent BackupGroup = "include=* or unused"
+standardPreferredContent IncrementalBackupGroup = lastResort
"(include=* or unused) and (not copies=incrementalbackup:1)"
-preferredContent SmallArchiveGroup = lastResort $
- "(include=*/archive/* or include=archive/*) and (" ++ preferredContent FullArchiveGroup ++ ")"
-preferredContent FullArchiveGroup = lastResort notArchived
-preferredContent SourceGroup = "not (copies=1)"
-preferredContent ManualGroup = "present and (" ++ preferredContent ClientGroup ++ ")"
-preferredContent PublicGroup = "inpreferreddir"
-preferredContent UnwantedGroup = "exclude=*"
+standardPreferredContent SmallArchiveGroup = lastResort $
+ "(include=*/archive/* or include=archive/*) and (" ++ standardPreferredContent FullArchiveGroup ++ ")"
+standardPreferredContent FullArchiveGroup = lastResort notArchived
+standardPreferredContent SourceGroup = "not (copies=1)"
+standardPreferredContent ManualGroup = "present and (" ++ standardPreferredContent ClientGroup ++ ")"
+standardPreferredContent PublicGroup = "inpreferreddir"
+standardPreferredContent UnwantedGroup = "exclude=*"
notArchived :: String
notArchived = "not (copies=archive:1 or copies=smallarchive:1)"
diff --git a/Utility/FileMode.hs b/Utility/FileMode.hs
index b17cadc3b..9c15da8c4 100644
--- a/Utility/FileMode.hs
+++ b/Utility/FileMode.hs
@@ -9,15 +9,18 @@
module Utility.FileMode where
-import Common
-
+import System.IO
+import Control.Monad
import Control.Exception (bracket)
import System.PosixCompat.Types
+import Utility.PosixFiles
#ifndef mingw32_HOST_OS
import System.Posix.Files
#endif
import Foreign (complement)
+import Utility.Exception
+
{- Applies a conversion function to a file's mode. -}
modifyFileMode :: FilePath -> (FileMode -> FileMode) -> IO ()
modifyFileMode f convert = void $ modifyFileMode' f convert
@@ -56,6 +59,12 @@ readModes = [ownerReadMode, groupReadMode, otherReadMode]
executeModes :: [FileMode]
executeModes = [ownerExecuteMode, groupExecuteMode, otherExecuteMode]
+otherGroupModes :: [FileMode]
+otherGroupModes =
+ [ groupReadMode, otherReadMode
+ , groupWriteMode, otherWriteMode
+ ]
+
{- Removes the write bits from a file. -}
preventWrite :: FilePath -> IO ()
preventWrite f = modifyFileMode f $ removeModes writeModes
@@ -99,13 +108,20 @@ noUmask :: FileMode -> IO a -> IO a
#ifndef mingw32_HOST_OS
noUmask mode a
| mode == stdFileMode = a
- | otherwise = bracket setup cleanup go
+ | otherwise = withUmask nullFileMode a
+#else
+noUmask _ a = a
+#endif
+
+withUmask :: FileMode -> IO a -> IO a
+#ifndef mingw32_HOST_OS
+withUmask umask a = bracket setup cleanup go
where
- setup = setFileCreationMask nullFileMode
+ setup = setFileCreationMask umask
cleanup = setFileCreationMask
go _ = a
#else
-noUmask _ a = a
+withUmask _ a = a
#endif
combineModes :: [FileMode] -> FileMode
@@ -127,14 +143,16 @@ setSticky f = modifyFileMode f $ addModes [stickyMode]
#endif
{- Writes a file, ensuring that its modes do not allow it to be read
- - by anyone other than the current user, before any content is written.
+ - or written by anyone other than the current user,
+ - before any content is written.
+ -
+ - When possible, this is done using the umask.
-
- On a filesystem that does not support file permissions, this is the same
- as writeFile.
-}
writeFileProtected :: FilePath -> String -> IO ()
-writeFileProtected file content = withFile file WriteMode $ \h -> do
- void $ tryIO $
- modifyFileMode file $
- removeModes [groupReadMode, otherReadMode]
- hPutStr h content
+writeFileProtected file content = withUmask 0o0077 $
+ withFile file WriteMode $ \h -> do
+ void $ tryIO $ modifyFileMode file $ removeModes otherGroupModes
+ hPutStr h content
diff --git a/Utility/FileSystemEncoding.hs b/Utility/FileSystemEncoding.hs
index ac105e73d..690942cba 100644
--- a/Utility/FileSystemEncoding.hs
+++ b/Utility/FileSystemEncoding.hs
@@ -1,14 +1,17 @@
{- GHC File system encoding handling.
-
- - Copyright 2012-2013 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Utility.FileSystemEncoding (
fileEncoding,
withFilePath,
md5FilePath,
+ decodeBS,
decodeW8,
encodeW8,
truncateFilePath,
@@ -22,13 +25,24 @@ import System.IO.Unsafe
import qualified Data.Hash.MD5 as MD5
import Data.Word
import Data.Bits.Utils
+import qualified Data.ByteString.Lazy as L
+#ifdef mingw32_HOST_OS
+import qualified Data.ByteString.Lazy.UTF8 as L8
+#endif
{- Sets a Handle to use the filesystem encoding. This causes data
- written or read from it to be encoded/decoded the same
- as ghc 7.4 does to filenames etc. This special encoding
- - allows "arbitrary undecodable bytes to be round-tripped through it". -}
+ - allows "arbitrary undecodable bytes to be round-tripped through it".
+ -}
fileEncoding :: Handle -> IO ()
+#ifndef mingw32_HOST_OS
fileEncoding h = hSetEncoding h =<< Encoding.getFileSystemEncoding
+#else
+{- The file system encoding does not work well on Windows,
+ - and Windows only has utf FilePaths anyway. -}
+fileEncoding h = hSetEncoding h Encoding.utf8
+#endif
{- Marshal a Haskell FilePath into a NUL terminated C string using temporary
- storage. The FilePath is encoded using the filesystem encoding,
@@ -60,6 +74,16 @@ _encodeFilePath fp = unsafePerformIO $ do
md5FilePath :: FilePath -> MD5.Str
md5FilePath = MD5.Str . _encodeFilePath
+{- Decodes a ByteString into a FilePath, applying the filesystem encoding. -}
+decodeBS :: L.ByteString -> FilePath
+#ifndef mingw32_HOST_OS
+decodeBS = encodeW8 . L.unpack
+#else
+{- On Windows, we assume that the ByteString is utf-8, since Windows
+ - only uses unicode for filenames. -}
+decodeBS = L8.toString
+#endif
+
{- Converts a [Word8] to a FilePath, encoding using the filesystem encoding.
-
- w82c produces a String, which may contain Chars that are invalid
@@ -84,6 +108,7 @@ decodeW8 = s2w8 . _encodeFilePath
- cost of efficiency when running on a large FilePath.
-}
truncateFilePath :: Int -> FilePath -> FilePath
+#ifndef mingw32_HOST_OS
truncateFilePath n = go . reverse
where
go f =
@@ -91,3 +116,17 @@ truncateFilePath n = go . reverse
in if length bytes <= n
then reverse f
else go (drop 1 f)
+#else
+{- On Windows, count the number of bytes used by each utf8 character. -}
+truncateFilePath n = reverse . go [] n . L8.fromString
+ where
+ go coll cnt bs
+ | cnt <= 0 = coll
+ | otherwise = case L8.decode bs of
+ Just (c, x) | c /= L8.replacement_char ->
+ let x' = fromIntegral x
+ in if cnt - x' < 0
+ then coll
+ else go (c:coll) (cnt - x') (L8.drop 1 bs)
+ _ -> coll
+#endif
diff --git a/Utility/Matcher.hs b/Utility/Matcher.hs
index e0a51ff6a..eabc585f4 100644
--- a/Utility/Matcher.hs
+++ b/Utility/Matcher.hs
@@ -19,7 +19,7 @@
module Utility.Matcher (
Token(..),
- Matcher,
+ Matcher(..),
token,
tokens,
generate,
diff --git a/Utility/QuickCheck.hs b/Utility/QuickCheck.hs
index e2539f3d6..7f7234c7c 100644
--- a/Utility/QuickCheck.hs
+++ b/Utility/QuickCheck.hs
@@ -28,10 +28,10 @@ instance (Arbitrary v, Eq v, Ord v) => Arbitrary (S.Set v) where
{- Times before the epoch are excluded. -}
instance Arbitrary POSIXTime where
- arbitrary = nonNegative arbitrarySizedIntegral
+ arbitrary = fromInteger <$> nonNegative arbitrarySizedIntegral
instance Arbitrary EpochTime where
- arbitrary = nonNegative arbitrarySizedIntegral
+ arbitrary = fromInteger <$> nonNegative arbitrarySizedIntegral
{- Pids are never negative, or 0. -}
instance Arbitrary ProcessID where
diff --git a/Utility/ThreadScheduler.hs b/Utility/ThreadScheduler.hs
index dbb6cb317..dd88dc879 100644
--- a/Utility/ThreadScheduler.hs
+++ b/Utility/ThreadScheduler.hs
@@ -10,10 +10,13 @@
module Utility.ThreadScheduler where
-import Common
-
+import Control.Monad
import Control.Concurrent
#ifndef mingw32_HOST_OS
+import Control.Monad.IfElse
+import System.Posix.IO
+#endif
+#ifndef mingw32_HOST_OS
import System.Posix.Signals
#ifndef __ANDROID__
import System.Posix.Terminal
diff --git a/Utility/Url.hs b/Utility/Url.hs
index 3ab14ebe4..eddcd0a5d 100644
--- a/Utility/Url.hs
+++ b/Utility/Url.hs
@@ -77,7 +77,8 @@ exists url uo = case parseURIRelaxed url of
Nothing -> dne
| otherwise -> if Build.SysConfig.curl
then do
- output <- readProcess "curl" $ toCommand curlparams
+ output <- catchDefaultIO "" $
+ readProcess "curl" $ toCommand curlparams
case lastMaybe (lines output) of
Just ('2':_:_) -> return (True, extractsize output)
_ -> dne
diff --git a/Utility/WebApp.hs b/Utility/WebApp.hs
index 31d3711f1..1a7698870 100644
--- a/Utility/WebApp.hs
+++ b/Utility/WebApp.hs
@@ -1,6 +1,6 @@
{- Yesod webapp
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -33,9 +33,12 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import Blaze.ByteString.Builder.Char.Utf8 (fromText)
import Blaze.ByteString.Builder (Builder)
-import Data.Monoid
import Control.Arrow ((***))
import Control.Concurrent
+#ifdef WITH_WEBAPP_SECURE
+import Data.SecureMem
+import Data.Byteable
+#endif
#ifdef __ANDROID__
import Data.Endian
#endif
@@ -74,14 +77,14 @@ browserProc url = proc "xdg-open" [url]
runWebApp :: Maybe TLSSettings -> Maybe HostName -> Wai.Application -> (SockAddr -> IO ()) -> IO ()
runWebApp tlssettings h app observer = withSocketsDo $ do
sock <- getSocket h
- void $ forkIO $ run webAppSettings sock app
+ void $ forkIO $ go webAppSettings sock app
sockaddr <- fixSockAddr <$> getSocketName sock
observer sockaddr
where
-#ifdef WITH_WEBAPP_HTTPS
- run = (maybe runSettingsSocket (\ts -> runTLSSocket ts) tlssettings)
+#ifdef WITH_WEBAPP_SECURE
+ go = (maybe runSettingsSocket (\ts -> runTLSSocket ts) tlssettings)
#else
- run = runSettingsSocket
+ go = runSettingsSocket
#endif
fixSockAddr :: SockAddr -> SockAddr
@@ -208,15 +211,35 @@ webAppSessionBackend _ = do
#endif
#endif
-{- Generates a random sha512 string, suitable to be used for an
- - authentication secret. -}
-genRandomToken :: IO String
-genRandomToken = do
+#ifdef WITH_WEBAPP_SECURE
+type AuthToken = SecureMem
+#else
+type AuthToken = T.Text
+#endif
+
+toAuthToken :: T.Text -> AuthToken
+#ifdef WITH_WEBAPP_SECURE
+toAuthToken = secureMemFromByteString . TE.encodeUtf8
+#else
+toAuthToken = id
+#endif
+
+fromAuthToken :: AuthToken -> T.Text
+#ifdef WITH_WEBAPP_SECURE
+fromAuthToken = TE.decodeLatin1 . toBytes
+#else
+fromAuthToken = id
+#endif
+
+{- Generates a random sha512 string, encapsulated in a SecureMem,
+ - suitable to be used for an authentication secret. -}
+genAuthToken :: IO AuthToken
+genAuthToken = do
g <- newGenIO :: IO SystemRandom
return $
case genBytes 512 g of
- Left e -> error $ "failed to generate secret token: " ++ show e
- Right (s, _) -> show $ sha512 $ L.fromChunks [s]
+ Left e -> error $ "failed to generate auth token: " ++ show e
+ Right (s, _) -> toAuthToken $ T.pack $ show $ sha512 $ L.fromChunks [s]
{- A Yesod isAuthorized method, which checks the auth cgi parameter
- against a token extracted from the Yesod application.
@@ -225,15 +248,15 @@ genRandomToken = do
- possibly leaking the auth token in urls on that page!
-}
#if MIN_VERSION_yesod(1,2,0)
-checkAuthToken :: (Monad m, Yesod.MonadHandler m) => (Yesod.HandlerSite m -> T.Text) -> m Yesod.AuthResult
+checkAuthToken :: (Monad m, Yesod.MonadHandler m) => (Yesod.HandlerSite m -> AuthToken) -> m Yesod.AuthResult
#else
-checkAuthToken :: forall t sub. (t -> T.Text) -> Yesod.GHandler sub t Yesod.AuthResult
+checkAuthToken :: forall t sub. (t -> AuthToken) -> Yesod.GHandler sub t Yesod.AuthResult
#endif
-checkAuthToken extractToken = do
+checkAuthToken extractAuthToken = do
webapp <- Yesod.getYesod
req <- Yesod.getRequest
let params = Yesod.reqGetParams req
- if lookup "auth" params == Just (extractToken webapp)
+ if (toAuthToken <$> lookup "auth" params) == Just (extractAuthToken webapp)
then return Yesod.Authorized
else Yesod.sendResponseStatus unauthorized401 ()
@@ -243,21 +266,21 @@ checkAuthToken extractToken = do
-
- A typical predicate would exclude files under /static.
-}
-insertAuthToken :: forall y. (y -> T.Text)
+insertAuthToken :: forall y. (y -> AuthToken)
-> ([T.Text] -> Bool)
-> y
-> T.Text
-> [T.Text]
-> [(T.Text, T.Text)]
-> Builder
-insertAuthToken extractToken predicate webapp root pathbits params =
+insertAuthToken extractAuthToken predicate webapp root pathbits params =
fromText root `mappend` encodePath pathbits' encodedparams
where
pathbits' = if null pathbits then [T.empty] else pathbits
encodedparams = map (TE.encodeUtf8 *** go) params'
go "" = Nothing
go x = Just $ TE.encodeUtf8 x
- authparam = (T.pack "auth", extractToken webapp)
+ authparam = (T.pack "auth", fromAuthToken (extractAuthToken webapp))
params'
| predicate pathbits = authparam:params
| otherwise = params
diff --git a/debian/changelog b/debian/changelog
index 7ff502ad3..2cb6290d7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,14 +1,79 @@
-git-annex (5.20140307) UNRELEASED; urgency=medium
+git-annex (5.20140402) unstable; urgency=medium
+
+ * unannex, uninit: Avoid committing after every file is unannexed,
+ for massive speedup.
+ * --notify-finish switch will cause desktop notifications after each
+ file upload/download/drop completes
+ (using the dbus Desktop Notifications Specification)
+ * --notify-start switch will show desktop notifications when each
+ file upload/download starts.
+ * webapp: Automatically install Nautilus integration scripts
+ to get and drop files.
+ * tahoe: Pass -d parameter before subcommand; putting it after
+ the subcommand no longer works with tahoe-lafs version 1.10.
+ (Thanks, Alberto Berti)
+ * forget --drop-dead: Avoid removing the dead remote from the trust.log,
+ so that if git remotes for it still exist anywhere, git annex info
+ will still know it's dead and not show it.
+ * git-annex-shell: Make configlist automatically initialize
+ a remote git repository, as long as a git-annex branch has
+ been pushed to it, to simplify setup of remote git repositories,
+ including via gitolite.
+ * add --include-dotfiles: New option, perhaps useful for backups.
+ * Version 5.20140227 broke creation of glacier repositories,
+ not including the datacenter and vault in their configuration.
+ This bug is fixed, but glacier repositories set up with the broken
+ version of git-annex need to have the datacenter and vault set
+ in order to be usable. This can be done using git annex enableremote
+ to add the missing settings. For details, see
+ http://git-annex.branchable.com/bugs/problems_with_glacier/
+ * Added required content configuration.
+ * assistant: Improve ssh authorized keys line generated in local pairing
+ or for a remote ssh server to set environment variables in an
+ alternative way that works with the non-POSIX fish shell, as well
+ as POSIX shells.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 02 Apr 2014 16:42:53 -0400
+
+git-annex (5.20140320) unstable; urgency=medium
* Fix zombie leak and general inneficiency when copying files to a
local git repo.
+ * Fix ssh connection caching stop method to work with openssh 6.5p1,
+ which broke the old method.
* webapp: Added a "Sync now" item to each repository's menu.
+ * webapp: Use securemem for constant time auth token comparisons.
+ * copy --fast --to remote: Avoid printing anything for files that
+ are already believed to be present on the remote.
+ * Commands that allow specifying which repository to act on using
+ the repository's description will now fail when multiple repositories
+ match, rather than picking a repository at random.
+ (So will --in=)
+ * Better workaround for problem umasks when eg, setting up ssh keys.
+ * "standard" can now be used as a first-class keyword in preferred content
+ expressions. For example "standard or (include=otherdir/*)"
+ * groupwanted can be used in preferred content expressions.
+ * vicfg: Allows editing preferred content expressions for groups.
+ * Improve behavior when unable to parse a preferred content expression
+ (thanks, ion).
+ * metadata: Add --get
+ * metadata: Support --key option (and some other ones like --all)
+ * For each metadata field, there's now an automatically maintained
+ "$field-lastchanged" that gives the date of the last change to that
+ field. Also the "lastchanged" field for the date of the last change
+ to any of a file's metadata.
* unused: In direct mode, files that are deleted from the work tree
- are no longer incorrectly detected as unused.
+ and so have no content present are no longer incorrectly detected as
+ unused.
+ * Avoid encoding errors when using the unused log file.
+ * map: Fix crash when one of the remotes of a repo is a local directory
+ that does not exist, or is not a git repo.
* repair: Improve memory usage when git fsck finds a great many broken
objects.
+ * Windows: Fix some filename encoding bugs.
+ * rsync special remote: Fix slashes when used on Windows.
- -- Joey Hess <joeyh@debian.org> Thu, 06 Mar 2014 16:17:01 -0400
+ -- Joey Hess <joeyh@debian.org> Thu, 20 Mar 2014 13:21:12 -0400
git-annex (5.20140306) unstable; urgency=high
diff --git a/debian/control b/debian/control
index 30840b34e..dd7eaa848 100644
--- a/debian/control
+++ b/debian/control
@@ -30,6 +30,7 @@ Build-Depends:
libghc-hinotify-dev [linux-any],
libghc-stm-dev (>= 2.3),
libghc-dbus-dev (>= 0.10.3) [linux-any],
+ libghc-fdo-notify-dev (>= 0.3) [linux-any],
libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
libghc-yesod-default-dev [i386 amd64 kfreebsd-amd64 powerpc sparc],
@@ -39,6 +40,8 @@ Build-Depends:
libghc-warp-tls-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
libghc-wai-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
libghc-wai-logger-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 powerpc sparc],
+ libghc-securemem-dev,
+ libghc-byteable-dev,
libghc-dns-dev,
libghc-case-insensitive-dev,
libghc-http-types-dev,
diff --git a/doc/Android/oldcomments/comment_1_cc9caa5dd22dd67e5c1d22d697096dd2._comment b/doc/Android/oldcomments/comment_1_cc9caa5dd22dd67e5c1d22d697096dd2._comment
index 7fb38058c..44b1a5d70 100644
--- a/doc/Android/oldcomments/comment_1_cc9caa5dd22dd67e5c1d22d697096dd2._comment
+++ b/doc/Android/oldcomments/comment_1_cc9caa5dd22dd67e5c1d22d697096dd2._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="http://yarikoptic.myopenid.com/"
nickname="site-myopenid"
subject="Does it require the device to be rooted?"
diff --git a/doc/assistant/downloadnotification.png b/doc/assistant/downloadnotification.png
new file mode 100644
index 000000000..32b04f122
--- /dev/null
+++ b/doc/assistant/downloadnotification.png
Binary files differ
diff --git a/doc/assistant/nautilusmenu.png b/doc/assistant/nautilusmenu.png
new file mode 100644
index 000000000..d7926e34f
--- /dev/null
+++ b/doc/assistant/nautilusmenu.png
Binary files differ
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_6_770c4f1802fc40d76bbaf7783bb3b4ac._comment b/doc/assistant/remote_sharing_walkthrough/comment_6_770c4f1802fc40d76bbaf7783bb3b4ac._comment
new file mode 100644
index 000000000..69ae139b2
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_6_770c4f1802fc40d76bbaf7783bb3b4ac._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="severo"
+ ip="88.182.182.135"
+ subject="git-assistant and transfer repository"
+ date="2014-03-16T17:05:43Z"
+ content="""
+In your comment http://git-annex.branchable.com/assistant/remote_sharing_walkthrough/#comment-f97efe1d05c0101232684b4e4edc4866, you describe a way to synchronize two devices using an intermediate USB drive configured as a \"transfer repository\".
+
+I understand that in that case, the USB drive can only be used as a \"transmitter\", in a git repository form, not as a copy of the files structure. This means the files contained by the USB drive cannot be accessed without git/git-annnex.
+
+Is there a way to use the USB drive as a \"client repository\" in order to allow synchronization, as described earlier, but also as a simple copy of the files, in order to access them from any device (opening them with windows in a cyber coffee for example).
+
+Thanks
+"""]]
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_7_61c1f5b00381b2fa891a8578267881ab._comment b/doc/assistant/remote_sharing_walkthrough/comment_7_61c1f5b00381b2fa891a8578267881ab._comment
new file mode 100644
index 000000000..e34a462da
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_7_61c1f5b00381b2fa891a8578267881ab._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 7"
+ date="2014-03-17T19:50:48Z"
+ content="""
+@severo the web app does not support setting up that use case. However, you can make a non-bare clone of your repository onto a removable drive, and if you do the assistant will use it just the same as if you'd set up a removable drive using the webapp. Note that you will need to run `git annex sync` inside that repository in order to update the tree it displays.
+"""]]
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_8_35e00cd10e89ae4bcc66af7dadf6bb5c._comment b/doc/assistant/remote_sharing_walkthrough/comment_8_35e00cd10e89ae4bcc66af7dadf6bb5c._comment
new file mode 100644
index 000000000..994d969e6
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_8_35e00cd10e89ae4bcc66af7dadf6bb5c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="severo"
+ ip="95.152.107.168"
+ subject="comment 8"
+ date="2014-03-18T10:06:50Z"
+ content="""
+Thansk @joeyh.name for your answer. Do you think this feature could be integrated into the git-annex assistant ?
+"""]]
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_9_c900e4ef49388826c87cadef4235c073._comment b/doc/assistant/remote_sharing_walkthrough/comment_9_c900e4ef49388826c87cadef4235c073._comment
new file mode 100644
index 000000000..1766fcf63
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_9_c900e4ef49388826c87cadef4235c073._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="severo"
+ ip="95.152.107.168"
+ subject="comment 9"
+ date="2014-03-18T11:16:19Z"
+ content="""
+Some explanations in French on how to do: http://seenthis.net/messages/237648#message238202
+"""]]
diff --git a/doc/automatic_conflict_resolution/comment_1_307898855f91a2a189d4fa5eae62cce1._comment b/doc/automatic_conflict_resolution/comment_1_307898855f91a2a189d4fa5eae62cce1._comment
index 69e136b44..57a8c45f8 100644
--- a/doc/automatic_conflict_resolution/comment_1_307898855f91a2a189d4fa5eae62cce1._comment
+++ b/doc/automatic_conflict_resolution/comment_1_307898855f91a2a189d4fa5eae62cce1._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawnJTqmRu1YCKS2Hsm4vtOflLhP4fU-k98w"
nickname="Ahmed"
subject="Customise conflict resolution behaviour"
diff --git a/doc/automatic_conflict_resolution/comment_2_0a8ea42764dde1a33d2112197b961c51._comment b/doc/automatic_conflict_resolution/comment_2_0a8ea42764dde1a33d2112197b961c51._comment
new file mode 100644
index 000000000..8c50ec4e2
--- /dev/null
+++ b/doc/automatic_conflict_resolution/comment_2_0a8ea42764dde1a33d2112197b961c51._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn3p4i4lk_zMilvjnJ9sS6g2nerpgz0Fjc"
+ nickname="Matthias"
+ subject="Use automatic merge without syncing"
+ date="2014-03-20T10:03:41Z"
+ content="""
+Is there a possibility to use the automatic merge logic without using \"git annex sync\"? I don't want to have the \"synced\"-branches, but the auto-conflict-resolution is very nice.
+"""]]
diff --git a/doc/automatic_conflict_resolution/comment_3_5c587c6633cae1c8547ca970d55ee97e._comment b/doc/automatic_conflict_resolution/comment_3_5c587c6633cae1c8547ca970d55ee97e._comment
new file mode 100644
index 000000000..58bdc5631
--- /dev/null
+++ b/doc/automatic_conflict_resolution/comment_3_5c587c6633cae1c8547ca970d55ee97e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 3"
+ date="2014-03-20T16:10:10Z"
+ content="""
+@Matthias `git annex merge` will do what you want, as long as you have git-annex 4.20130709 or newer.
+"""]]
diff --git a/doc/automatic_conflict_resolution/comment_4_80539e11e36a0b64cee83b6b373bd843._comment b/doc/automatic_conflict_resolution/comment_4_80539e11e36a0b64cee83b6b373bd843._comment
new file mode 100644
index 000000000..d67514452
--- /dev/null
+++ b/doc/automatic_conflict_resolution/comment_4_80539e11e36a0b64cee83b6b373bd843._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn3p4i4lk_zMilvjnJ9sS6g2nerpgz0Fjc"
+ nickname="Matthias"
+ subject="merge for master branch?"
+ date="2014-03-23T23:02:23Z"
+ content="""
+As far as I observed, \"git annex merge\" only merges the \"git-annex\" branch. My wish is to have the conflict resolution from \"git annex sync\" in the \"master\" branch, but no automatic commit, such that the user can verify and possibly correct the merge. The proposed merge could go to the index. Consider the following scenario:
+
+1. We have repo A, B, and CENTRAL
+2. All three start with a root commit in \"master\" branch
+3. Then A commits a file \"test.txt\" with content \"a\" and syncs with CENTRAL
+4. Meanwhile, B commits \"test.txt\" with content \"b\"
+5. When B tries to sync with CENTRAL, the proposed conflict resolution having two files \"test.txt-variantXXXX\" and \"test.txt-variantYYYY\" should be staged in the index, but not committed yet.
+6. B can now commit a custom merge, e.g. with file content \"ab\".
+
+The point is that I really like the conflict resolution, but still want to force the user to check the result.
+"""]]
diff --git a/doc/automatic_conflict_resolution/comment_5_00ac9e4a47ce9a886dbf573480f151bd._comment b/doc/automatic_conflict_resolution/comment_5_00ac9e4a47ce9a886dbf573480f151bd._comment
new file mode 100644
index 000000000..4d1e7c4bc
--- /dev/null
+++ b/doc/automatic_conflict_resolution/comment_5_00ac9e4a47ce9a886dbf573480f151bd._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 5"
+ date="2014-03-26T18:56:30Z"
+ content="""
+@Matthias you need to install git-annex 4.20130709 or newer. Then `git-annex merge` will do what you want. As I said before.
+
+As for committing the merge, you can always adjust the result after the fact and use `git commit --amend`.
+"""]]
diff --git a/doc/bugs/Android_:_handling_DCIM__47__Camera_not_being_configurable.mdwn b/doc/bugs/Android_:_handling_DCIM__47__Camera_not_being_configurable.mdwn
index ee73cbeb6..a52857d1f 100644
--- a/doc/bugs/Android_:_handling_DCIM__47__Camera_not_being_configurable.mdwn
+++ b/doc/bugs/Android_:_handling_DCIM__47__Camera_not_being_configurable.mdwn
@@ -12,5 +12,5 @@ In the log, there are many "too many open files" errors like these :
git:createProcess: runInteractiveProcess: pipe: resource exhausted (Too many open files)
-[[!moreinfo]]
+[[!tag moreinfo]]
[[!meta title="too many open files on android"]]
diff --git a/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory.mdwn b/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory.mdwn
new file mode 100644
index 000000000..954d26ec2
--- /dev/null
+++ b/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory.mdwn
@@ -0,0 +1,520 @@
+I have a git annex assistant process using 1.2 gigabytes of RAM and a git cat-file --batch child consuming CPU time constantly. I am running 5.20140320 on Ubuntu 12.04.
+
+[[!format sh """
+ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
+11775 ion 20 0 1350m 1.2g 12m S 48 62.4 425:56.85 git-annex
+11787 ion 20 0 9856 1484 1232 R 54 0.1 366:16.14 git
+"""]]
+
+The assistant UI looks perfectly normal and does not indicate it is doing anything. daemon.log is empty and the assistant process seems to be logging into a rotated and deleted log file.
+
+[[!format sh """
+COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
+git-annex 11775 ion 1w REG 9,127 80841 55181369 /storage/ion/media/video/.git/annex/daemon.log.10 (deleted)
+git-annex 11775 ion 2w REG 9,127 80841 55181369 /storage/ion/media/video/.git/annex/daemon.log.10 (deleted)
+"""]]
+
+strace -s10000 -e trace=read,write -p 11787 indicates that the assistant is having the cat-file process cat same objects over and over again.
+
+[[!format sh """
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "d95950acebb5c4318329d7b989d36d01b76b7801 blob 232\n", 50) = 50
+write(1, "1396057825.366657s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.538068s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.560144s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.538542s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:ee2/2ee/SHA256E-s106800355--c70e31d511e7eec4881a15dfba521ea3d1fe14694968f81ae1819f1a2a93f9be.mp4.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "977039ea431522e6e27a78bdec2c1299f883eb85 blob 232\n", 50) = 50
+write(1, "1396057823.999737s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057835.133409s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057835.215084s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.468307s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:a84/f1f/SHA256E-s47051987--dcfd0413db883506ccb8c45e3b2d60cb3ff5c83cc55c9c7e44818d7556dbc07f.mp4.log\n", 4096) = 121
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "6c0ff555a1a34337c9379d8856c8283429bef973 blob 231\n", 50) = 50
+write(1, "1396057829.505426s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057839.859236s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057839.875213s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.77741s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:50a/5fc/SHA256E-s275654757--52823cd2061375910ccbd8de38865eca91511d9b4621243d2ef96a974d7546aa.flv.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "cdbc7ce6b426dfcce9d718387b6c412e870a2d12 blob 232\n", 50) = 50
+write(1, "1396057828.887576s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.117938s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.197196s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.687354s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 232) = 232
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:9b5/545/SHA256E-s32710--6005b5faf1a6d42d499053f8cca87d080536abfa8442b33c87f7966e86726e4f.fin.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+read(3, "", 214) = 0
+write(1, "82a98cbfe8f24d336a537cecea2182922c4681e1 blob 231\n", 50) = 50
+write(1, "1396057825.390306s 1 3f89d0d8-6162-4362-852a-cb688d6c0696\n1396057866.37922s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396057866.386029s 1 161c3d7f-eb60-4294-84d2-eb611786c91e\n1396058160.588219s 0 3f89d0d8-6162-4362-852a-cb688d6c0696\n", 231) = 231
+write(1, "\n", 1) = 1
+read(0, "refs/heads/git-annex:d28/166/SHA256E-s59188--9c04581bd67ea7c78b537a164d104bea5ac91a4a69f06b477cf07892a2d9b852.fih.srt.log\n", 4096) = 122
+read(3, "0936a1fdd849b8b46abb879d7cf82cc758b367e3\n", 255) = 41
+"""]]
diff --git a/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory/comment_1_ac8c39e362e6c806b9d68befc0199ccd._comment b/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory/comment_1_ac8c39e362e6c806b9d68befc0199ccd._comment
new file mode 100644
index 000000000..e9c5d3fff
--- /dev/null
+++ b/doc/bugs/Assistant_having_a_child_git_cat-file_--batch_do_the_same_thing_over_and_over_and_using_a_lot_of_memory/comment_1_ac8c39e362e6c806b9d68befc0199ccd._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T18:48:51Z"
+ content="""
+All I can tell from the strace is that it's looking at location logs, and it's looking at the same few keys, but not a single on in a tight loop.
+
+It would probably help a lot to run the assistant with --debug and get a debug log while this is going on. We need to pinpoint the part of the assistant that is affected, and there may be other activity too.
+"""]]
diff --git a/doc/bugs/Assistant_lost_dbus_connection_spamming_log.mdwn b/doc/bugs/Assistant_lost_dbus_connection_spamming_log.mdwn
index 3b50742fd..a4a0b0221 100644
--- a/doc/bugs/Assistant_lost_dbus_connection_spamming_log.mdwn
+++ b/doc/bugs/Assistant_lost_dbus_connection_spamming_log.mdwn
@@ -76,3 +76,13 @@ accept: unsupported operation (Function not implemented)
lost dbus connection; falling back to polling (SocketError {socketErrorMessage = "connect: does not exist (No such file or directory)", socketErrorFatal = True, socketErrorAddress = Just (Address "unix:path=/var/run/dbus/system_bus_socket")})
"""]]
+
+> [[done]]; This turned out to not be dbus related, but the http server failing,
+> and I fixed that bug.
+>
+> AFAICS the user running git-annex did not have their own dbus daemon
+> running, and that's why the low-volume dbus messages come up.
+> Probably because this is an embedded device, and so no desktop
+> environment. git-annex only uses dbus for detecting network connection
+> changes and removable media mounts. None of which probably matter in an
+> embedded environment. --[[Joey]]
diff --git a/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_12_1cfdd76e751ee3726bd80359cfc85c47._comment b/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_12_1cfdd76e751ee3726bd80359cfc85c47._comment
new file mode 100644
index 000000000..fe19bf87e
--- /dev/null
+++ b/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_12_1cfdd76e751ee3726bd80359cfc85c47._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="ping?"
+ date="2014-03-19T20:29:12Z"
+ content="""
+Could either greg or Schnouki please test with the current arm autobuild and see if you can connect to the webapp?
+"""]]
diff --git a/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_13_37aa5274874242861dc128efa1d29486._comment b/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_13_37aa5274874242861dc128efa1d29486._comment
new file mode 100644
index 000000000..5a99e0f55
--- /dev/null
+++ b/doc/bugs/Assistant_lost_dbus_connection_spamming_log/comment_13_37aa5274874242861dc128efa1d29486._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://schnouki.net/"
+ nickname="Schnouki"
+ subject="comment 13"
+ date="2014-03-20T23:54:51Z"
+ content="""
+Sorry for the delay (my laptop hard drive died so I was offline for a few days).
+
+Just tested git-annex 5.20140320 on my NAS and it works just fine! The webapp is running, I can connect to it, and there's no more spam in the daemon.log (except for the dbus message every minute, but that's not really a problem).
+
+Thanks a lot Joey!
+"""]]
diff --git a/doc/bugs/Bug_Report_doesn__39__t_work.mdwn b/doc/bugs/Bug_Report_doesn__39__t_work.mdwn
new file mode 100644
index 000000000..cbf4a481d
--- /dev/null
+++ b/doc/bugs/Bug_Report_doesn__39__t_work.mdwn
@@ -0,0 +1,20 @@
+### Please describe the problem.
+Bug Report doesn't work
+
+### What steps will reproduce the problem?
+
+
+### What version of git-annex are you using? On what operating system?
+
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
+
+[[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/Can__39__t_access_files_from___39__Removable_drive__39___repo_even_if_set_as_client.mdwn b/doc/bugs/Can__39__t_access_files_from___39__Removable_drive__39___repo_even_if_set_as_client.mdwn
index ef59954b7..941ac9e5a 100644
--- a/doc/bugs/Can__39__t_access_files_from___39__Removable_drive__39___repo_even_if_set_as_client.mdwn
+++ b/doc/bugs/Can__39__t_access_files_from___39__Removable_drive__39___repo_even_if_set_as_client.mdwn
@@ -19,3 +19,4 @@ I'm using 9e57edff287ac53fc4b1cefef7271e9ed17f2285 (Fri Feb 22 15:19:25 2013 +00
Ubuntu 12.10 x86_64
[[!tag /design/assistant]]
+[[!meta title="assistant should set up non-bare repos on removable drives, and update them when syncing with them"]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn
index de879f522..b6c9691ea 100644
--- a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn
@@ -31,3 +31,6 @@ I noticed the problem yesterday afternoon (Thu 24 Oct).
# End of transcript or log.
"""]]
+
+> [[moreinfo]]; either I don't have enough information to work on this,
+> or it might have just been user error. --[[Joey]]
diff --git a/doc/bugs/Could_not_read_from_remote_repository/comment_3_95d16045dc238dba19a98808de2eeedf._comment b/doc/bugs/Could_not_read_from_remote_repository/comment_3_95d16045dc238dba19a98808de2eeedf._comment
new file mode 100644
index 000000000..a8d2705a6
--- /dev/null
+++ b/doc/bugs/Could_not_read_from_remote_repository/comment_3_95d16045dc238dba19a98808de2eeedf._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnvVfFLW4CTKs7UjdiLIsOn_cxj1Jnh64I"
+ nickname="Charl"
+ subject="Could it be gmail.com XMPP throttling?"
+ date="2014-03-23T19:26:08Z"
+ content="""
+I was seeing similar error messages, until I registered for a different XMPP account at jabber.de and started using that instead of my gmail.com account.
+
+My current suspicion is that it could be Google performing throttling on their XMPP service. See here: http://stackoverflow.com/questions/1843837/what-is-the-throttling-rate-that-gtalk-applies-to-xmpp-messages
+
+"""]]
diff --git a/doc/bugs/Crash_when_disabling_syncing_in_the_webapp.mdwn b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp.mdwn
new file mode 100644
index 000000000..e69a145a6
--- /dev/null
+++ b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp.mdwn
@@ -0,0 +1,23 @@
+### Please describe the problem.
+The watcher crashes.
+
+I only need to restart the thread in the pop-up to get everything to work again, but I'm reporting just in case that this issue has any other implications.
+
+
+### What steps will reproduce the problem?
+I open the webapp and in the minutes before it starts syncing (syncing is enabled) I disable it (clicking in the 'syncing enabled' text).
+
+This produces a crash every time.
+
+
+### What version of git-annex are you using? On what operating system?
+5.20140320 in Debian sid and testing
+
+
+### Please provide any additional information below.
+This is all I can see in the logs
+
+[[!format sh """
+Watcher crashed: PauseWatcher
+[2014-03-26 08:54:57 CET] Watcher: warning Watcher crashed: PauseWatcher
+"""]]
diff --git a/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_1_e25dd80370820782f9c6a877101d8703._comment b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_1_e25dd80370820782f9c6a877101d8703._comment
new file mode 100644
index 000000000..ce4af5caa
--- /dev/null
+++ b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_1_e25dd80370820782f9c6a877101d8703._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T17:36:00Z"
+ content="""
+How did you install git-annex? Is this Debian Linux?
+
+I have not been able to reproduce a crash. It's indeed the case that a PauseWatcher exception is thrown, but the Watcher explicitly catches that exception.
+"""]]
diff --git a/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_2_4031c16362137747717e9595cb5c8a15._comment b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_2_4031c16362137747717e9595cb5c8a15._comment
new file mode 100644
index 000000000..07efa451d
--- /dev/null
+++ b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_2_4031c16362137747717e9595cb5c8a15._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk9nck8WX8-ADF3Fdh5vFo4Qrw1I_bJcR8"
+ nickname="Jon Ander"
+ subject="comment 2"
+ date="2014-04-01T08:04:51Z"
+ content="""
+Yes, this is Debian Linux and I've been able to reproduce it in i386 and amd64. git-annex is installed from the Debian repositories.
+
+I'll try to continue testing the issue and will report back if I can find any useful info.
+"""]]
diff --git a/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_3_0667f39f60bdaba6670f5b8304a8a77c._comment b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_3_0667f39f60bdaba6670f5b8304a8a77c._comment
new file mode 100644
index 000000000..60f82a5b3
--- /dev/null
+++ b/doc/bugs/Crash_when_disabling_syncing_in_the_webapp/comment_3_0667f39f60bdaba6670f5b8304a8a77c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 3"
+ date="2014-04-02T20:38:12Z"
+ content="""
+So we have the same version of git-annex from the same build, and only you see the problem. Hmm..
+
+You mentioned that you see the problem if you disable syncing at a particular time. Does it only crash at that time, or at any time?
+
+If you create a brand new empty repository and run the webapp in it, can you reporoduce the problem there? Ie, \"mkdir test; cd test; git init; git annex init; git annex webapp\"
+"""]]
diff --git a/doc/bugs/Disconcerting_warning_from_git-annex.mdwn b/doc/bugs/Disconcerting_warning_from_git-annex.mdwn
index 169dc26d1..ef662441c 100644
--- a/doc/bugs/Disconcerting_warning_from_git-annex.mdwn
+++ b/doc/bugs/Disconcerting_warning_from_git-annex.mdwn
@@ -4,3 +4,5 @@ I did a "git annex add" of a bunch of files on a storage server with low IOPS, a
failed
How is that even possible, when the server is doing nothing else?
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/Disconcerting_warning_from_git-annex/comment_3_13999207f4ddac2f9c345415f25f7ada._comment b/doc/bugs/Disconcerting_warning_from_git-annex/comment_3_13999207f4ddac2f9c345415f25f7ada._comment
new file mode 100644
index 000000000..142e6ecd1
--- /dev/null
+++ b/doc/bugs/Disconcerting_warning_from_git-annex/comment_3_13999207f4ddac2f9c345415f25f7ada._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="moreinfo"
+ date="2014-03-19T20:49:47Z"
+ content="""
+What I don't understand about this is, how does `open` fail due to a file being locked? This is Linux, it doesn't have mandatory locking that I know of, and git-annex certianly doesn't use such a thing.
+
+I really need a way to reproduce this and/or a strace. As it is, I've never seen this reported by anyone else and don't understand the failure mode at all.
+
+The relevant part of the code seems to be here:
+
+[[!format haskell \"\"\"
+setJournalFile :: JournalLocked -> FilePath -> String -> Annex ()
+setJournalFile _jl file content = do
+ tmp <- fromRepo gitAnnexTmpMiscDir
+ createAnnexDirectory =<< fromRepo gitAnnexJournalDir
+ createAnnexDirectory tmp
+ -- journal file is written atomically
+ jfile <- fromRepo $ journalFile file
+ let tmpfile = tmp </> takeFileName jfile
+ liftIO $ do
+ writeBinaryFile tmpfile content
+ moveFile tmpfile jfile
+\"\"\"]]
+
+While there is some ctnl locking going on, it locks a special sentinal file, not the file it's writing to.
+"""]]
diff --git a/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles.mdwn b/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles.mdwn
new file mode 100644
index 000000000..686bf1887
--- /dev/null
+++ b/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles.mdwn
@@ -0,0 +1,14 @@
+When using git annex as part of an automated backup system, it's sometimes important that we archive all files, including dotfiles.
+
+AFAICT there's no way to tell git annex add to add all dotfiles in a given directory; the only way to do it is to list every dotfile individually. (git annex add --force doesn't seem to do it.)
+
+This can be worked around with find and xargs, but this is more work than it should be, I think.
+
+It might also be nice if git annex add displayed a warning when adding a directory with dotfiles; something like "Warning, N files ignored; pass --whatever to add them."
+
+> [[!commit 34abd7bca80a8cc012f92d64116014449b1b2392]] explains
+> the rationalle for dotfiles to be skipped. Such as it was.
+>
+> I don't think it makes sense for --force to be the flag to override
+> this, because you may want to add dotfiles, but not .gitignored
+> files. So, made a new --include-dotfiles option. [[done]] --[[Joey]]
diff --git a/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles/comment_1_c258016dd545b0426e75a7c0132154d8._comment b/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles/comment_1_c258016dd545b0426e75a7c0132154d8._comment
new file mode 100644
index 000000000..c591e7643
--- /dev/null
+++ b/doc/bugs/Feature_request:_Flag_to_make_git_annex_add_not_ignore_dotfiles/comment_1_c258016dd545b0426e75a7c0132154d8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmUJBh1lYmvfCCiGr3yrdx-QhuLCSRnU5c"
+ nickname="Justin"
+ subject="comment 1"
+ date="2014-03-24T07:03:42Z"
+ content="""
+Maybe the right solution is to make --force not ignore dotfiles, although perhaps that would break people who rely on its current behavior.
+"""]]
diff --git a/doc/bugs/Fix_to_thaoe_remote_to_work_with_latest_tahoe-lafs___40__v._1.10.0__41__.mdwn b/doc/bugs/Fix_to_thaoe_remote_to_work_with_latest_tahoe-lafs___40__v._1.10.0__41__.mdwn
new file mode 100644
index 000000000..d4392ff6a
--- /dev/null
+++ b/doc/bugs/Fix_to_thaoe_remote_to_work_with_latest_tahoe-lafs___40__v._1.10.0__41__.mdwn
@@ -0,0 +1,62 @@
+### Please describe the problem.
+Just a small patch to Tahoe.hs which fixes "initremote repo
+type=thaoe" when using the latest tahoe-lafs release available for
+download.
+
+I'm trying to add an attachment here but the UI says "prohibited by
+allowed_attachments (user is not an admin)" so please have a look also
+here: <https://github.com/joeyh/git-annex/pull/21>
+
+### What steps will reproduce the problem?
+
+1. Install latest tahoe-lafs
+2. run "TAHOE_FURL=... git annex initremote repo type=tahoe"
+
+### What version of git-annex are you using? On what operating system?
+
+OS: Debian Sid updated to latest packages
+git-annex: version 5.20140306
+
+> Thanks, I've fixed this. [[done]] --[[Joey]]
+
+### Please provide any additional information below.
+
+I would like to add few things if i'm able (it's my first time for
+haskell, and I'm a bit lost as now):
+
+1. add an optional parameter or envvar for a root dir cap and switch
+from storing anonymous files to saving a tree of dirs and files
+(much like the webdav back-end) so that i can later renew the
+leases on the files to prevent tahoe's garbage collection process
+expiration (for details see
+<https://tahoe-lafs.org/trac/tahoe-lafs/browser/docs/garbage-collection.rst#client-side-renewal>)
+
+The poor man way to that without touching git-annex is to in some
+way collect the caps of the files from annex metadatas and to link
+them to a directory, which where i can then run "tahoe deep-check
+--add-lease" on;
+
+> When I talked this over with Zooko before, he
+> thought it was better for git-annex to not use tahoe's directories,
+> which is why it doesn't. See [[todo/tahoe_lfs_for_reals]].
+>
+> This is the first I have heard about tahoe garbage collection.
+> It sounds like it's an optional process.
+>
+> It would certainly be possible to pull the caps for files out of
+> git-annex's remote state log.
+> --[[Joey]]
+
+2. add convergence as an optional parameter. As of now many of the
+files that i'm willing to manage with git-annex are already on my
+grid, mostly because i've used tahoe's backup command to upload
+them in the past. By using the same convergence value that i've
+already setup on my other tahoe client installation i would be able
+to save much time and space by avoiding duplicates.
+
+Do you have any good pointers to pieces code of git-annex that i can
+read and hack to try to implement this or any other suggestion?
+
+> It was not documented, but you can already pass
+> `shared-convergence-secret=xxx` to `initremote`.
+> I have documented it. --[[Joey]]
diff --git a/doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.txt b/doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.mdwn
index e4eef758a..e4eef758a 100644
--- a/doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.txt
+++ b/doc/bugs/Linux_stand_alone_build_20130723_breaks_support_for_glibc_2.13_debian_stable.mdwn
diff --git a/doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn b/doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn
index f5962b81b..7401d79fb 100644
--- a/doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn
+++ b/doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp.mdwn
@@ -8,3 +8,5 @@ git annex version for OS X,
remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
whereas on my Linux box build flags include webapp. On os x when I run git annex webapp it does nothing, just prints the help info.
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment b/doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment
index b13eab08f..b13eab08f 100644
--- a/doc/forum/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment
+++ b/doc/bugs/Mac_OS_X_Build_doesn__39__t_include_webapp/comment_1_b918a741f2397b6588e7a9f1feca7e66._comment
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn
index e01310336..0d442437d 100644
--- a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn
@@ -228,3 +228,13 @@ Everything up-to-date
"""]]
Well, I see that thing about "failed to lock". I can imagine that my 'killall git-annex' to kill a leftover process that was hanging around after I'd done git-annex assistant --stop might have left stale lock files, somewhere... but of course I only got as far as doing that because I was already encountering problems, just trying to return to the webapp.
+
+> The original bug report seems to be a case of user confusion,
+> and not a bug. (Although perhaps the UI is confusing?)
+>
+> The "resource exhausted" that came up later is quite likely the problem
+> fixed in [[!commit 4d06037fdd44ba38fcd4c118d1e6330f06e22366]],
+> which affected local git remotes.
+>
+> [[closing|done]]; I don't see any value keeping this open, I'm afraid.
+> --[[Joey]]
diff --git a/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl.mdwn b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl.mdwn
new file mode 100644
index 000000000..1fee43928
--- /dev/null
+++ b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl.mdwn
@@ -0,0 +1,195 @@
+Addurl can fail due to an apparent race condition when watch or assistant is running and the repository is in direct mode. The following stress test script encounters the bug consistently on my system. I am running git-annex 5.20140320 on on Ubuntu 13.10.
+
+[[!format sh """
+#!/bin/sh
+set -eu
+
+cleanup() {
+ local dir
+ dir="$1"; shift
+ if [ -d "$dir" ]; then
+ (
+ set -x
+ fuser -k -w "$dir/annex/.git/annex/daemon.log" || :
+ find "$dir" -type d -exec chmod 700 '{}' '+'
+ find "$dir" -type f -exec chmod 600 '{}' '+'
+ rm -fr "$dir"
+ )
+ fi
+}
+
+go() {
+ local dir
+ dir="$(mktemp -d "${TMP:-/tmp}/stress-annex.XXXXXXXXXX")"
+ trap "cleanup '$dir'" 0 1 2 13 15
+
+ (
+ cd "$dir"
+ mkdir annex
+ cd annex
+ set -x
+
+ git init
+ git annex init
+ git annex direct
+ git annex watch
+
+ for n in $(seq 100); do
+ git annex addurl --file=foo http://heh.fi/robots.txt
+ git annex sync
+ rm -f foo
+ git annex sync
+ done
+
+ git annex watch --stop
+ git annex uninit
+ )
+
+ cleanup "$dir"
+ trap - 0 1 2 13 14
+}
+
+go
+"""]]
+
+Script output:
+
+[[!format sh """
+% ./stress-annex
++ git init
+Initialized empty Git repository in /tmp/stress-annex.OKj6D8kVmV/annex/.git/
++ git annex init
+init ok
+(Recording state in git...)
++ git annex direct
+commit
+On branch master
+
+Initial commit
+
+nothing to commit
+ok
+direct ok
++ git annex watch
++ seq 100
++ git annex addurl --file=foo http://heh.fi/robots.txt
+addurl foo (downloading http://heh.fi/robots.txt ...)
+--2014-03-27 03:14:29-- http://heh.fi/robots.txt
+Resolving heh.fi (heh.fi)... 83.145.237.222
+Connecting to heh.fi (heh.fi)|83.145.237.222|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 0 [text/plain]
+Saving to: ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’
+
+ [ <=> ] 0 --.-K/s in 0s
+
+2014-03-27 03:14:29 (0.00 B/s) - ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’ saved [0/0]
+
+(Recording state in git...)
+ok
+(Recording state in git...)
++ git annex sync
+commit ok
++ rm -f foo
++ git annex sync
+commit (Recording state in git...)
+ok
+(Recording state in git...)
++ git annex addurl --file=foo http://heh.fi/robots.txt
+addurl foo (downloading http://heh.fi/robots.txt ...)
+--2014-03-27 03:14:29-- http://heh.fi/robots.txt
+Resolving heh.fi (heh.fi)... 83.145.237.222
+Connecting to heh.fi (heh.fi)|83.145.237.222|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 0 [text/plain]
+Saving to: ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’
+
+ [ <=> ] 0 --.-K/s in 0s
+
+2014-03-27 03:14:29 (0.00 B/s) - ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’ saved [0/0]
+
+(Recording state in git...)
+ok
+(Recording state in git...)
++ git annex sync
+commit ok
++ rm -f foo
++ git annex sync
+commit (Recording state in git...)
+ok
+(Recording state in git...)
++ git annex addurl --file=foo http://heh.fi/robots.txt
+addurl foo (downloading http://heh.fi/robots.txt ...)
+--2014-03-27 03:14:29-- http://heh.fi/robots.txt
+Resolving heh.fi (heh.fi)... 83.145.237.222
+Connecting to heh.fi (heh.fi)|83.145.237.222|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 0 [text/plain]
+Saving to: ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’
+
+ [ <=> ] 0 --.-K/s in 0s
+
+2014-03-27 03:14:29 (0.00 B/s) - ‘/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’ saved [0/0]
+
+
+git-annex: /tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/objects/pX/ZJ/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/: openTempFile: permission denied (Permission denied)
+failed
+git-annex: addurl: 1 failed
++ fuser -k -w /tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/daemon.log
+/tmp/stress-annex.OKj6D8kVmV/annex/.git/annex/daemon.log: 30704 30709 30735 30738 30778
++ find /tmp/stress-annex.OKj6D8kVmV -type d -exec chmod 700 {} +
++ find /tmp/stress-annex.OKj6D8kVmV -type f -exec chmod 600 {} +
++ rm -fr /tmp/stress-annex.OKj6D8kVmV
+"""]]
+
+The script also seems to encounter another issue. The output when seq 100 is changed to seq 1 and addurl happens to succeed:
+
+[[!format sh """
++ git init
+Initialized empty Git repository in /tmp/stress-annex.QEs0pNyS9z/annex/.git/
++ git annex init
+init ok
+(Recording state in git...)
++ git annex direct
+commit
+On branch master
+
+Initial commit
+
+nothing to commit
+ok
+direct ok
++ git annex watch
++ seq 1
++ git annex addurl --file=foo http://heh.fi/robots.txt
+addurl foo (downloading http://heh.fi/robots.txt ...)
+--2014-03-27 03:17:20-- http://heh.fi/robots.txt
+Resolving heh.fi (heh.fi)... 83.145.237.222
+Connecting to heh.fi (heh.fi)|83.145.237.222|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 0 [text/plain]
+Saving to: ‘/tmp/stress-annex.QEs0pNyS9z/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’
+
+ [ <=> ] 0 --.-K/s in 0s
+
+2014-03-27 03:17:20 (0.00 B/s) - ‘/tmp/stress-annex.QEs0pNyS9z/annex/.git/annex/tmp/URL--http&c%%heh.fi%robots.txt’ saved [0/0]
+
+(Recording state in git...)
+ok
+(Recording state in git...)
++ git annex sync
+commit ok
++ rm -f foo
++ git annex sync
+commit (Recording state in git...)
+ok
+(Recording state in git...)
++ git annex watch --stop
++ git annex uninit
+git-annex: /tmp/stress-annex.QEs0pNyS9z/annex/.git/annex/objects/pX/ZJ/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.map: removeLink: permission denied (Permission denied)
++ fuser -k -w /tmp/stress-annex.QEs0pNyS9z/annex/.git/annex/daemon.log
++ :
++ find /tmp/stress-annex.QEs0pNyS9z -type d -exec chmod 700 {} +
++ find /tmp/stress-annex.QEs0pNyS9z -type f -exec chmod 600 {} +
++ rm -fr /tmp/stress-annex.QEs0pNyS9z
+"""]]
diff --git a/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_1_8f56b8661a600729d7a9d569e8a0ba70._comment b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_1_8f56b8661a600729d7a9d569e8a0ba70._comment
new file mode 100644
index 000000000..cf010cd25
--- /dev/null
+++ b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_1_8f56b8661a600729d7a9d569e8a0ba70._comment
@@ -0,0 +1,55 @@
+[[!comment format=mdwn
+ username="http://johan.kiviniemi.name/"
+ nickname="Johan"
+ subject="Another race condition"
+ date="2014-03-31T03:42:42Z"
+ content="""
+Here’s another race condition which seems related:
+
+[[!format sh \"\"\"
+% git annex addurl 'quvi:http://youtu.be/-CbFj9K9AQg'
+addurl David_Raymond_Christiansen___Dependently_Typed_Programming_in_Idris___A_Demo.webm
+--2014-03-31 05:45:49-- http://r4---sn-oxc0a5-ixae.googlevideo.com/videoplayback?<cut>
+Resolving r4---sn-oxc0a5-ixae.googlevideo.com (r4---sn-oxc0a5-ixae.googlevideo.com)... 83.145.196.143, 2001:1bc8:100:1b::f
+Connecting to r4---sn-oxc0a5-ixae.googlevideo.com (r4---sn-oxc0a5-ixae.googlevideo.com)|83.145.196.143|:80... connected.
+HTTP request sent, awaiting response... 302 Found
+Location: http://r13---sn-5go7dn7s.googlevideo.com/videoplayback?<cut> [following]
+--2014-03-31 05:45:49-- http://r13---sn-5go7dn7s.googlevideo.com/videoplayback?<cut>
+Resolving r13---sn-5go7dn7s.googlevideo.com (r13---sn-5go7dn7s.googlevideo.com)... 173.194.48.18, 2a00:1450:400f::12
+Connecting to r13---sn-5go7dn7s.googlevideo.com (r13---sn-5go7dn7s.googlevideo.com)|173.194.48.18|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 320557466 (306M) [video/webm]
+Saving to: ‘/home/ion/nobackup/media/video/.git/annex/tmp/URL--quvi&chttp&c%%youtu.be%-CbFj9K9AQg’
+
+100%[======================================>] 320,557,466 895KB/s in 6m 14s
+
+2014-03-31 05:52:04 (837 KB/s) - ‘/home/ion/nobackup/media/video/.git/annex/tmp/URL--quvi&chttp&c%%youtu.be%-CbFj9K9AQg’ saved [320557466/320557466]
+
+(Recording state in git...)
+fatal: Unable to create '/home/ion/nobackup/media/video/.git/index.lock': File exists.
+
+If no other git process is currently running, this probably means a
+git process crashed in this repository earlier. Make sure no other git
+process is running and remove the file manually to continue.
+
+git-annex: user error (xargs [\"-0\",\"git\",\"--git-dir=/home/ion/nobackup/media/video/.git\",\"--work-tree=/home/ion/nobackup/media/video\",\"-c\",\"core.bare=false\",\"add\",\"--\"] exited 123)
+failed
+git-annex: addurl: 1 failed
+
+% ls -l /home/ion/nobackup/media/video/.git/index.lock
+ls: cannot access /home/ion/nobackup/media/video/.git/index.lock: No such file or directory
+\"\"\"]]
+
+The only lines in daemon.log from that time:
+
+[[!format sh \"\"\"
+[2014-03-31 05:52:04 EEST] Committer: Committing changes to git
+[2014-03-31 05:52:04 EEST] Pusher: Syncing with heh.fi
+Already up-to-date.
+To heh.fi:/storage/ion/media/video
+ 3df241b..095d6c3 git-annex -> synced/git-annex
+ 10b3166..98074c1 annex/direct/master -> synced/master
+Already up-to-date.
+\"\"\"]]
+
+"""]]
diff --git a/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_2_46dc67bdcd174cd50ccc421ec56735ad._comment b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_2_46dc67bdcd174cd50ccc421ec56735ad._comment
new file mode 100644
index 000000000..ec3c974d9
--- /dev/null
+++ b/doc/bugs/Race_condition_between_watch__47__assistant_and_addurl/comment_2_46dc67bdcd174cd50ccc421ec56735ad._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 2"
+ date="2014-04-02T20:17:19Z"
+ content="""
+These races look beniegn, as far as I can see it doesn't cause any data to be lost, or indeed anything to happen that wouldn't have happened if addurl had been run without the assistant running.
+
+The first race probably has addurl and the assistant both trying to move the file object into the annex at the same time. One wins and moves it; the other loses and sulks.
+
+The second race has addurl trying to `git add` the file, while the assistant has already noticed the file appeared, `git add`ed it, and committed the add.
+
+The only way to really avoid these races would be to add a lot of lock checking. Or just make `git annex addurl` and presumably also `git annex add` and maybe several other commands refuse to run when the assistant is running.
+"""]]
diff --git a/doc/bugs/Share_with_friends_crash_in_osx.mdwn b/doc/bugs/Share_with_friends_crash_in_osx.mdwn
index 21e385c60..d7ed801e7 100644
--- a/doc/bugs/Share_with_friends_crash_in_osx.mdwn
+++ b/doc/bugs/Share_with_friends_crash_in_osx.mdwn
@@ -366,3 +366,5 @@ Here is the crash report osx creates
# End of transcript or log.
"""]]
+
+> Apparently this is [[fixed|done]] in the latest release. --[[Joey]]
diff --git a/doc/bugs/Share_with_friends_crash_in_osx/comment_13_65de2b5dd3af89c2f0f6508ffddda3b5._comment b/doc/bugs/Share_with_friends_crash_in_osx/comment_13_65de2b5dd3af89c2f0f6508ffddda3b5._comment
new file mode 100644
index 000000000..3a02f2f8c
--- /dev/null
+++ b/doc/bugs/Share_with_friends_crash_in_osx/comment_13_65de2b5dd3af89c2f0f6508ffddda3b5._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 13"
+ date="2014-03-12T17:01:12Z"
+ content="""
+Well that's good and unexpected news!
+
+I did make some changes on the OSX autobuilder recently. For one thing, I updated and rebuilt all the homebrew stuff, and remembered to pass --build-bottle when doing so. Which I think I had always done before.. Homebrew also removed some dependencies on gnutls in wget, and perhaps they also made other changes -- I'd not be surprised if a change to homebrew made --build-bottle start disabling some optimisations.
+
+In any case, I suppose I can close this bug now..
+"""]]
diff --git a/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.txt b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.mdwn
index 7eaf2a71b..7eaf2a71b 100644
--- a/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.txt
+++ b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.mdwn
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows.mdwn b/doc/bugs/Unicode_file_names_ignored_on_Windows.mdwn
new file mode 100644
index 000000000..5d0b73b17
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows.mdwn
@@ -0,0 +1,41 @@
+### Please describe the problem.
+
+The "add" command silently ignores all files and directories with non-ascii characters.
+
+### What steps will reproduce the problem?
+
+I created empty repository (git init, git annex init). I created some files with ascii and nonascii file names (hacky.txt, háčky.txt).
+
+git annex add . correctly adds only hacky.txt.
+
+git annex add "háčky.txt" does nothing.
+
+### What version of git-annex are you using? On what operating system?
+
+git 1.9.0,
+git-annex installer from 2014-03-06
+
+Windows XP and 7 with czech localization. CP1250 is used for czech characters on windows.
+
+### Please provide any additional information below.
+
+ $ ls
+ hacky.txt h????ky.txt
+ $ git annex add .
+ add hacky.txt ok
+ (Recording state in git...)
+ $ git annex status
+ D h├í─Źky.txt
+
+According to https://github.com/msysgit/msysgit/wiki/Git-for-Windows-Unicode-Support ls prints junk, but only to console.
+
+ D:\anntest>git annex add "háčky.txt" --debug
+ [2014-03-18 14:28:03 Central Europe Standard Time] read: git ["--git-dir=D:\\anntest\\.git","--work-tree=D:\\anntest","-c","core.bare=false","ls-files","--others","--exclude-standard","-z","--","h\225\269ky.txt"]
+ [2014-03-18 14:28:03 Central Europe Standard Time] chat: git ["--git-dir=D:\\anntest\\.git","--work-tree=D:\\anntest","-c","core.bare=false","cat-file","--batch"]
+ [2014-03-18 14:28:03 Central Europe Standard Time] read: git ["--git-dir=D:\\anntest\\.git","--work-tree=D:\\anntest","-c","core.bare=false","ls-files","--modified","-z","--","h\225\269ky.txt"]
+
+I can provide additional information, just tell me what you need.
+
+> [[fixed|done]], although this is not the end of encoding issues
+> on Windows. Updating [[todo/windows_support]] to discuss some other ones.
+> --[[Joey]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_1_3dfa4559dceec50c08ba180f41b4c220._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_1_3dfa4559dceec50c08ba180f41b4c220._comment
new file mode 100644
index 000000000..c1778db78
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_1_3dfa4559dceec50c08ba180f41b4c220._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="analysis"
+ date="2014-03-18T17:54:09Z"
+ content="""
+The `git ls-files --others -z output` is fine; the mojibake seems to occur in git-annex's reading of that output, which uses GHC's filesystem encoding. On Linux it reads \"h\225\269ky.txt\" but on Windows, \"h\195\161\196\56461ky.txt\".
+
+So, it's failing to compose the multibyte characters, and it seems to have escaped the last byte (which should be \"\141\" based on the other 3) out into the high code plane used for undecodable bytes.
+
+Note that on Linux with LANG=C, the add works, and it sees \"h\56515\56481\56516\56461ky.txt\" -- in this case, all 4 bytes are represented in the high code plane, and so round-trip through ok despite the locale not supporting the utf8 encoding.
+
+Interestingly, while both `[readFile \"h\225\269ky.txt\", readFile \"h\56515\56481\56516\56461ky.txt\"]` work on Linux, only the former does on Windows.
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_2_4dafea4367d455c2e63b0f7b1cc39559._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_2_4dafea4367d455c2e63b0f7b1cc39559._comment
new file mode 100644
index 000000000..97d7012a1
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_2_4dafea4367d455c2e63b0f7b1cc39559._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 2"
+ date="2014-03-18T18:09:08Z"
+ content="""
+One approach might be to not use the GHC FileSystemEncoding on Windows, and assume that Windows filenames are always in a unicode encoding. After all, the FileSystemEncoding is only used by git-annex on Unix because Unix has no canonical encoding that will work for all filenames.
+
+Hmm, nope, I tried this and it just causes an \"invalid byte sequence\" crash when reading from git-ls-files.
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_3_bdde68a990a330ee0cf626be44b1c132._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_3_bdde68a990a330ee0cf626be44b1c132._comment
new file mode 100644
index 000000000..1f35dc9dd
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_3_bdde68a990a330ee0cf626be44b1c132._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-18T18:14:57Z"
+ content="""
+ghc docs on FileSystemEncoding: \"On Windows, this encoding *should not* be used if possible because the use of code pages is deprecated: Strings should be retrieved via the wide W-family of UTF-16 APIs instead\"
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_4_9140fb8034b1449ee2f4762093bc1f89._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_4_9140fb8034b1449ee2f4762093bc1f89._comment
new file mode 100644
index 000000000..e40a6ab33
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_4_9140fb8034b1449ee2f4762093bc1f89._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 4"
+ date="2014-03-18T18:42:57Z"
+ content="""
+As well as the default encoding, I've tried `utf8`, `utf16`, `utf16le`, and `utf16be` encodings, and none of them is able to successfully read the git ls-files output, all fail with encoding error. (I also tried `mkUTF16 RoundtripFailure` but it completely broke git-annex.)
+
+Unsure where to go from here..
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_5_661ca15b68bc0e3fbe85f11400570446._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_5_661ca15b68bc0e3fbe85f11400570446._comment
new file mode 100644
index 000000000..ccafb635e
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_5_661ca15b68bc0e3fbe85f11400570446._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk5aY0oBmuQtnoTNtji-dPgDw9p7J24YeY"
+ nickname="Jiří"
+ subject="further info"
+ date="2014-03-18T23:46:08Z"
+ content="""
+On my windows 7 machine, ls-files does return something better
+
+ c:\JSH\antest>git --work-tree=c:\JSH\antest ls-files --others
+ \"h\303\241\304\215ky.txt\"
+
+If I am correct, it is unicode 225 269, but as octal utf-8. ls-files -z return correct utf-8 (68 C3 A1 C4 8D 6B ...)
+
+I will test that tomorrow also on windows xp on my work pc.
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_6_0e8820169c0300d296c697154fd05dc4._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_6_0e8820169c0300d296c697154fd05dc4._comment
new file mode 100644
index 000000000..4f7ec51fa
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_6_0e8820169c0300d296c697154fd05dc4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk5aY0oBmuQtnoTNtji-dPgDw9p7J24YeY"
+ nickname="Jiří"
+ subject="further info 2"
+ date="2014-03-19T11:53:17Z"
+ content="""
+And on my windows xp computer, git ls-files returns valid utf-8 too.
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_7_b23a2bf106053f105798b270536057e5._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_7_b23a2bf106053f105798b270536057e5._comment
new file mode 100644
index 000000000..b5cf90ef0
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_7_b23a2bf106053f105798b270536057e5._comment
@@ -0,0 +1,38 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk5aY0oBmuQtnoTNtji-dPgDw9p7J24YeY"
+ nickname="Jiří"
+ subject="further info 3"
+ date="2014-03-19T16:23:58Z"
+ content="""
+Also ghc doesn't seem to do any weird transformations with that string
+
+ import System.Process
+ import qualified Data.ByteString as S
+ import qualified Data.ByteString.UTF8 as U
+ import GHC.IO.Handle
+
+ files :: S.ByteString -> [S.ByteString]
+ files ps
+ | S.null ps = []
+ | otherwise = case search ps of
+ Nothing -> [ps]
+ Just n -> S.take n ps : files (S.drop (n+1) ps)
+ where search = S.elemIndex 0
+
+ main = do
+ let prc = CreateProcess {
+ cmdspec = RawCommand \"git\" [\"--work-tree=D:\\antest\",\"ls-files\",\"--others\",\"-z\",\"--\",\"h\225\269ky.txt\"],
+ cwd = Nothing,
+ env = Nothing,
+ std_in = Inherit,
+ std_out = CreatePipe,
+ std_err = Inherit,
+ close_fds = False,
+ create_group = False }
+ (_,Just out,_,_) <- createProcess prc
+ hSetBinaryMode out True
+ str <- S.hGetContents out
+ print $ map U.toString $ files str
+
+prints correctly [\"h\225\269ky.txt\"] I don't think that FilesystemEncoding will do any good on windows, since git seems to use utf-8 instead of normal windows console encoding.
+"""]]
diff --git a/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_8_7f23911705eaa58a9230f19ab890e87f._comment b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_8_7f23911705eaa58a9230f19ab890e87f._comment
new file mode 100644
index 000000000..2cd4b346e
--- /dev/null
+++ b/doc/bugs/Unicode_file_names_ignored_on_Windows/comment_8_7f23911705eaa58a9230f19ab890e87f._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 8"
+ date="2014-03-19T19:57:00Z"
+ content="""
+Windows & haskell? I'd only be more surprised if spj wandered in here. ;)
+
+So, that works because you're using ByteStrings. But git-annex mostly does not use ByteStrings, and it would be a lot of work to switch to them everywhere it reads FilePaths from git.
+
+But it seems my test yesterday using `hSetEncoding h Encoding.utf8` went wrong somehow. That does work. git-annex can operate on the file with that change.
+"""]]
diff --git a/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_8_35c949aca52de83af4881a9da6340185._comment b/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_8_35c949aca52de83af4881a9da6340185._comment
new file mode 100644
index 000000000..7a59e296b
--- /dev/null
+++ b/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_8_35c949aca52de83af4881a9da6340185._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk_QeJTzgCJj2ZC8EAJEODsLvxJ7dCOCVM"
+ nickname="Sindre"
+ subject="Non-ASCII Hostname fails"
+ date="2014-04-02T05:36:54Z"
+ content="""
+This bug still persists when specifying non-ascii hostnames.
+"""]]
diff --git a/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_9_9100031689eaa460791191d9bfb746d8._comment b/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_9_9100031689eaa460791191d9bfb746d8._comment
new file mode 100644
index 000000000..6fa440f23
--- /dev/null
+++ b/doc/bugs/Use_a_git_repository_on_the_server_don__39__t_work/comment_9_9100031689eaa460791191d9bfb746d8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 9"
+ date="2014-04-02T19:46:36Z"
+ content="""
+Sorry, but this bug report is closed. If you think you have a bug in git-annex, file a *new* bug report with full details for how I can reproduce it.
+"""]]
diff --git a/doc/bugs/__92____92___instead_of___47___on_rsync_special_remote_on_linux_accessed_from_a_windows_git-annex.mdwn b/doc/bugs/__92____92___instead_of___47___on_rsync_special_remote_on_linux_accessed_from_a_windows_git-annex.mdwn
new file mode 100644
index 000000000..5f6d35fad
--- /dev/null
+++ b/doc/bugs/__92____92___instead_of___47___on_rsync_special_remote_on_linux_accessed_from_a_windows_git-annex.mdwn
@@ -0,0 +1,27 @@
+### Please describe the problem.
+
+Getting file from a linux rsync special remote from a windows machine is impossible.
+
+### What steps will reproduce the problem?
+git annex get .
+
+### What version of git-annex are you using? On what operating system?
+5.20140316-gbe47273 on windows 8.
+
+### Please provide any additional information below.
+
+Launching in debug mode, we see the wrong \\ used instead of / used. Syntax that rsync doesn't understand on a linux box.
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+read: rsync ["-e","'ssh' '-l' 'git' '-T'
+","--progress","--inplace","git@strasser-family.ch:~/files/G5\\jj\\'SHA256E-s675
+--1112f74fc9ebea01460efe26e447171a1aacf8e551f06f62ef6fe683df02e03c.mat\\SHA256E-
+s675--1112f74fc9ebea01460efe26e447171a1aacf8e551f06f62ef6fe683df02e03c.mat'","/c
+ygdrive/c/Users/pablo/Desktop/Nouveau dossier/InnerResult/.git/annex/tmp/SHA256E
+-s675--1112f74fc9ebea01460efe26e447171a1aacf8e551f06f62ef6fe683df02e03c.mat"]
+
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories.mdwn b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories.mdwn
new file mode 100644
index 000000000..ef0f85662
--- /dev/null
+++ b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories.mdwn
@@ -0,0 +1,88 @@
+As per topic, `git annex forget --drop-dead --force` does not behave as expected. Instead of getting rid of dead repositories, it actually revives them.
+
+I messed up the initial setup of the S3 special remote and instead of risking manual intervention, I figured it would be cleanest to nuke the old special remotes, using a new one instead.
+And yes, I should have used a test repo :(
+
+As this is apu.debconf.org, you could get access to the repo if that helps.
+
+
+[[!format sh """
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex info
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 4
+ 00000000-0000-0000-0000-000000000001 -- web
+ 070cff8a-6302-4aa7-a63c-3fdd34e598a2 -- amazon_s3_us_east--SHA512E
+ 0bae683f-bede-43dd-a815-c4f8fb6db32d -- aws_s3_us_east--SHA512E
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: 4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: 4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex dead 070cff8a-6302-4aa7-a63c-3fdd34e598a2
+dead 070cff8a-6302-4aa7-a63c-3fdd34e598a2 ok
+(Recording state in git...)
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex dead 0bae683f-bede-43dd-a815-c4f8fb6db32d
+dead 0bae683f-bede-43dd-a815-c4f8fb6db32d ok
+(Recording state in git...)
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex initremote amazon_aws_s3-us_east_1--SHA512E type=S3 encryption='none' embedcreds='no' fileprefix='SHA512E/' bucket='debian-video'
+initremote amazon_aws_s3-us_east_1--SHA512E (checking bucket...) git-annex: This bucket is already in use by a different S3 special remote, with UUID: 0bae683f-bede-43dd-a815-c4f8fb6db32d
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex info
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 2
+ 00000000-0000-0000-0000-000000000001 -- web
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: 4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: 4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex forget --drop-dead --force
+forget git-annex (Recording state in git...)
+ok
+(Recording state in git...)
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex info
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 4
+ 00000000-0000-0000-0000-000000000001 -- web
+ 070cff8a-6302-4aa7-a63c-3fdd34e598a2 -- amazon_s3_us_east--SHA512E
+ 0bae683f-bede-43dd-a815-c4f8fb6db32d -- aws_s3_us_east--SHA512E
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: 4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: 4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu (git)-[master] /srv/video/video.debian.net % git annex version
+git-annex version: 5.20140117~bpo70+2
+build flags: Assistant Webapp Pairing S3 Inotify DBus XMPP Feeds Quvi TDFA
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+remote types: git gcrypt S3 bup directory rsync web tahoe glacier hook external
+local repository version: 5
+supported repository version: 5
+upgrade supported from repository versions: 0 1 2 4
+richih@apu (git)-[master] /srv/video/video.debian.net % cat /etc/issue
+Debian GNU/Linux 7 \n \l
+
+richih@apu (git)-[master] /srv/video/video.debian.net %
+"""]]
+
+> [[fixed|done]] via not removing from trust.log --[[Joey]]
diff --git a/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_1_930b40e0f68da95d335eea5bd4216126._comment b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_1_930b40e0f68da95d335eea5bd4216126._comment
new file mode 100644
index 000000000..05aa545ef
--- /dev/null
+++ b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_1_930b40e0f68da95d335eea5bd4216126._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T17:19:58Z"
+ content="""
+You still have git remotes configured with the uuid of the remote, so `git annex info` pulls that data in. Since --drop-dead removes all mention of the remote from the git-annex branch, including that its trust level is dead, the remaining info from the .git/config takes effect.
+
+--drop-dead could `git remote rm` but that won't help other clones of the repo that also have the dead remote. Instead, I think it may make sense for --drop-dead to avoid removing the uuid from trust.log, so it will still know this remote is dead.
+
+(Of course, you can easily deal with this locally by `git remote rm` yourself.)
+"""]]
diff --git a/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_2_5397d488bc337cb3d7cb46ed774d0437._comment b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_2_5397d488bc337cb3d7cb46ed774d0437._comment
new file mode 100644
index 000000000..8bdde8972
--- /dev/null
+++ b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_2_5397d488bc337cb3d7cb46ed774d0437._comment
@@ -0,0 +1,90 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 2"
+ date="2014-03-26T22:39:34Z"
+ content="""
+Sorry, I had to remove the fixed tag.
+
+
+The bug makes sense, as does your fix. I didn't even consider that this may be the cause. Still, `git remote rm` and `git annex forget --drop-dead --force` does not seem to be enough to truly get rid of the repo (and its UUID & state):
+
+[[!format sh \"\"\"
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex info
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 4
+ 00000000-0000-0000-0000-000000000001 -- web
+ 070cff8a-6302-4aa7-a63c-3fdd34e598a2 -- amazon_s3_us_east--SHA512E
+ 0bae683f-bede-43dd-a815-c4f8fb6db32d -- aws_s3_us_east--SHA512E
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: git4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: am4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex dead amazon_s3_us_east--SHA512E
+dead amazon_s3_us_east--SHA512E ok
+(Recording state in git...)
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex dead aws_s3_us_east--SHA512E
+dead aws_s3_us_east--SHA512E ok
+(Recording state in git...)
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git remote rm amazon_s3_us_east--SHA512E
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git remote rm aws_s3_us_east--SHA512E
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex forget --drop-dead --force
+forget git-annex (Recording state in git...)
+ok
+(Recording state in git...)
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex info
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 2
+ 00000000-0000-0000-0000-000000000001 -- web
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: 4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: 4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex initremote amazon_aws_s3-us_east_1--SHA512E type=S3 encryption='none' embedcreds='no' fileprefix='SHA512E/' bucket='debian-video'
+initremote amazon_aws_s3-us_east_1--SHA512E (checking bucket...) git-annex: This bucket is already in use by a different S3 special remote, with UUID: 0bae683f-bede-43dd-a815-c4f8fb6db32d
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % cat .git/annex
+cat: .git/annex: Ist ein Verzeichnis
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % cat .git/config
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[annex]
+ uuid = 92e9fac9-97ec-401f-a421-33f6b4f43e47
+ version = 5
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net % git annex info 537 23:33:37 Mi 26.03.2014
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 2
+ 00000000-0000-0000-0000-000000000001 -- web
+ 92e9fac9-97ec-401f-a421-33f6b4f43e47 -- here (apu.debconf.org/srv/video/conference_videos.annex)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 136.3 gigabytes (+1 megabyte reserved)
+local annex keys: 4392
+local annex size: 884.64 gigabytes
+annexed files in working tree: 4628
+size of annexed files in working tree: 885.68 gigabytes
+bloom filter size: 16 mebibytes (0.9% full)
+backend usage:
+ SHA512E: 9020
+richih@apu [2] [0] (git)-[master] /srv/video/video.debian.net %
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_3_1b30e7611ec824dc6e79ef35e43ac740._comment b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_3_1b30e7611ec824dc6e79ef35e43ac740._comment
new file mode 100644
index 000000000..5b5784012
--- /dev/null
+++ b/doc/bugs/__96__git_annex_forget_--drop-dead_--force__96_____95__revives__95___repositories/comment_3_1b30e7611ec824dc6e79ef35e43ac740._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 3"
+ date="2014-03-27T17:40:51Z"
+ content="""
+git-annex stores the uuid of a S3 remote inside the bucket for various reasons. Now that you have removed all knowledge of the remote from the repository, when you attempt to reuse the same bucket for some reason, git-annex has no way to know that this is a remote it used to use with that bucket.
+
+I think this behavior is entirely reasonable. Also, it's not what you filed the original bug report about; I fixed that bug. I'm going to re-close this.
+"""]]
diff --git a/doc/bugs/__96__minimal_build__39____fails_due_to_missing_stm_dependency/comment_1_86e26ee9ec90aa00f25392052737f0f0._comment b/doc/bugs/__96__minimal_build__39____fails_due_to_missing_stm_dependency/comment_1_86e26ee9ec90aa00f25392052737f0f0._comment
index 7b86c07cc..a1f52dc5e 100644
--- a/doc/bugs/__96__minimal_build__39____fails_due_to_missing_stm_dependency/comment_1_86e26ee9ec90aa00f25392052737f0f0._comment
+++ b/doc/bugs/__96__minimal_build__39____fails_due_to_missing_stm_dependency/comment_1_86e26ee9ec90aa00f25392052737f0f0._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawnlotDRSLW2JVXY3SLSwhrcHteqUHhTtoY"
nickname="Péter"
subject="Not fixed."
diff --git a/doc/bugs/_impossible_to_switch_repositories_on_android__in_webapp/comment_3_9ffafbeb572e110b3e072029d1ce177c._comment b/doc/bugs/_impossible_to_switch_repositories_on_android__in_webapp/comment_3_9ffafbeb572e110b3e072029d1ce177c._comment
new file mode 100644
index 000000000..b181a4fa1
--- /dev/null
+++ b/doc/bugs/_impossible_to_switch_repositories_on_android__in_webapp/comment_3_9ffafbeb572e110b3e072029d1ce177c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="yasin.zaehringer"
+ ip="90.218.200.128"
+ subject="comment 3"
+ date="2014-04-02T11:43:52Z"
+ content="""
+The bug still exists. It is not possible to change the repository in the WebApp.
+"""]]
diff --git a/doc/bugs/copy_to_--fast_should_not_mention_every_file_it_checks.mdwn b/doc/bugs/copy_to_--fast_should_not_mention_every_file_it_checks.mdwn
index 7c0137fb1..81d84b300 100644
--- a/doc/bugs/copy_to_--fast_should_not_mention_every_file_it_checks.mdwn
+++ b/doc/bugs/copy_to_--fast_should_not_mention_every_file_it_checks.mdwn
@@ -23,3 +23,6 @@ No information whatsoever is printed during upload when ran without `--quite` it
"""]]
[[!meta title="copy --fast --to remote should be quiet when nothing to do"]]
+
+> [[fixed|done]]; Avoided the unnecessary output in this situation.
+> --[[Joey]]
diff --git a/doc/bugs/enormous_fsck_output_OOM.mdwn b/doc/bugs/enormous_fsck_output_OOM.mdwn
index 975674b5c..b06655354 100644
--- a/doc/bugs/enormous_fsck_output_OOM.mdwn
+++ b/doc/bugs/enormous_fsck_output_OOM.mdwn
@@ -18,3 +18,13 @@ So I tried to follow your advice here and increase the stack:
git-annex: Most RTS options are disabled. Link with -rtsopts to enable them.
I wasn't sure what to do next, so any help would be appreciated.
+
+> Now only 20k problem shas max (more likely 10k) are collected from fsck,
+> so it won't use much memory (60 mb or so). If it had to truncate
+> shas from fsck, it will re-run fsck after the repair process,
+> which should either find no problems left (common when eg when all missing shas
+> were able to be fetched from remotes), or find a new set of problem
+> shas, which it can feed back through the repair process.
+>
+> If the repository is very large, this means more work, but it shouldn't
+> run out of memory now. [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/git-annex_fails_to_initialize_under_Windows.mdwn b/doc/bugs/git-annex_fails_to_initialize_under_Windows.mdwn
new file mode 100644
index 000000000..589ec562d
--- /dev/null
+++ b/doc/bugs/git-annex_fails_to_initialize_under_Windows.mdwn
@@ -0,0 +1,212 @@
+### Please describe the problem.
+Git-annex fails to initialize and fails tests.
+
+### What steps will reproduce the problem?
+Attempted initialization:
+
+ C:\Users\Andrew\Documents\GitHub\git-annex-test [master]> git annex init
+ init
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+ fatal: index file open failed: Invalid argument
+ git-annex: git [Param "checkout",Param "-q",Param "-B",Param "annex/direct/master"] failed
+
+Tests:
+
+ C:\Users\Andrew\Documents\GitHub\git-annex-test [master]> git annex test
+ Tests
+ QuickCheck
+ prop_idempotent_deencode_git: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_deencode: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_fileKey: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_key_encode: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_key_decode: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_shellEscape: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_shellEscape_multiword: OK
+ +++ OK, passed 1000 tests.
+ prop_logs_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_idempotent_configEscape: OK
+ +++ OK, passed 1000 tests.
+ prop_parse_show_Config: OK
+ +++ OK, passed 1000 tests.
+ prop_parentDir_basics: OK
+ +++ OK, passed 1000 tests.
+ prop_relPathDirToFile_basics: OK
+ +++ OK, passed 1000 tests.
+ prop_relPathDirToFile_regressionTest: OK
+ +++ OK, passed 1000 tests.
+ prop_cost_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_matcher_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_HmacSha1WithCipher_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_TimeStamp_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_addLog_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_verifiable_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_segment_regressionTest: OK
+ +++ OK, passed 1000 tests.
+ prop_read_write_transferinfo: OK
+ +++ OK, passed 1000 tests.
+ prop_read_show_inodecache: OK
+ +++ OK, passed 1000 tests.
+ prop_parse_show_log: OK
+ +++ OK, passed 1000 tests.
+ prop_read_show_TrustLevel: OK
+ +++ OK, passed 1000 tests.
+ prop_parse_show_TrustLog: OK
+ +++ OK, passed 1000 tests.
+ prop_hashes_stable: OK
+ +++ OK, passed 1000 tests.
+ prop_schedule_roundtrips: OK
+ +++ OK, passed 1000 tests.
+ prop_duration_roundtrips: OK
+ +++ OK, passed 1000 tests.
+ prop_metadata_sane: OK
+ +++ OK, passed 1000 tests.
+ prop_metadata_serialize: OK
+ +++ OK, passed 1000 tests.
+ prop_branchView_legal: OK
+ +++ OK, passed 1000 tests.
+ prop_view_roundtrips: OK
+ +++ OK, passed 1000 tests.
+ prop_viewedFile_rountrips: I n i t TOeKs
+ ts
+ i n+i+t+: OK, passed 1000 tests.
+ Unit Tests
+ add sha1dup: git-annex: System.PosixCompat.User.getEffectiveUserID: not support
+ ed: illegal operation
+ FAIL
+ init failed
+ add: git-annex: System.PosixCompat.User.getEffectiveUserID: not supported: illegal operation
+ FAIL
+ add failed
+
+ 2 out of 2 tests failed
+ FAIL
+ Exception: init tests failed! cannot continue
+ add extras: FAIL
+ Exception: init tests failed! cannot continue
+ reinject: FAIL
+ Exception: init tests failed! cannot continue
+ unannex (no copy): FAIL
+ Exception: init tests failed! cannot continue
+ unannex (with copy): FAIL
+ Exception: init tests failed! cannot continue
+ drop (no remote): FAIL
+ Exception: init tests failed! cannot continue
+ drop (with remote): FAIL
+ Exception: init tests failed! cannot continue
+ drop (untrusted remote): FAIL
+ Exception: init tests failed! cannot continue
+ get: FAIL
+ Exception: init tests failed! cannot continue
+ move: FAIL
+ Exception: init tests failed! cannot continue
+ copy: FAIL
+ Exception: init tests failed! cannot continue
+ lock: FAIL
+ Exception: init tests failed! cannot continue
+ edit (no pre-commit): FAIL
+ Exception: init tests failed! cannot continue
+ edit (pre-commit): FAIL
+ Exception: init tests failed! cannot continue
+ fix: FAIL
+ Exception: init tests failed! cannot continue
+ trust: FAIL
+ Exception: init tests failed! cannot continue
+ fsck (basics): FAIL
+ Exception: init tests failed! cannot continue
+ fsck (bare): FAIL
+ Exception: init tests failed! cannot continue
+ fsck (local untrusted): FAIL
+ Exception: init tests failed! cannot continue
+ fsck (remote untrusted): FAIL
+ Exception: init tests failed! cannot continue
+ migrate: FAIL
+ Exception: init tests failed! cannot continue
+ migrate (via gitattributes): FAIL
+ Exception: init tests failed! cannot continue
+ unused: FAIL
+ Exception: init tests failed! cannot continue
+ describe: FAIL
+ Exception: init tests failed! cannot continue
+ find: FAIL
+ Exception: init tests failed! cannot continue
+ merge: FAIL
+ Exception: init tests failed! cannot continue
+ info: FAIL
+ Exception: init tests failed! cannot continue
+ version: FAIL
+ Exception: init tests failed! cannot continue
+ sync: FAIL
+ Exception: init tests failed! cannot continue
+ union merge regression: FAIL
+ Exception: init tests failed! cannot continue
+ conflict resolution: FAIL
+ Exception: init tests failed! cannot continue
+ conflict_resolution (mixed directory and file): FAIL
+ Exception: init tests failed! cannot continue
+ conflict_resolution (mixed directory and file) 2: FAIL
+ Exception: init tests failed! cannot continue
+ map: FAIL
+ Exception: init tests failed! cannot continue
+ uninit: FAIL
+ Exception: init tests failed! cannot continue
+ uninit (in git-annex branch): FAIL
+ Exception: init tests failed! cannot continue
+ upgrade: FAIL
+ Exception: init tests failed! cannot continue
+ whereis: FAIL
+ Exception: init tests failed! cannot continue
+ hook remote: FAIL
+ Exception: init tests failed! cannot continue
+ directory remote: FAIL
+ Exception: init tests failed! cannot continue
+ rsync remote: FAIL
+ Exception: init tests failed! cannot continue
+ bup remote: FAIL
+ Exception: init tests failed! cannot continue
+ crypto: FAIL
+ Exception: init tests failed! cannot continue
+ preferred content: FAIL
+ Exception: init tests failed! cannot continue
+ add subdirs: FAIL
+ Exception: init tests failed! cannot continue
+
+ 45 out of 78 tests failed
+ (This could be due to a bug in git-annex, or an incompatability
+ with utilities, such as git, installed on this system.)
+
+### What version of git-annex are you using? On what operating system?
+ C:\Users\Andrew\Documents\GitHub\git-annex-test [master]> git --version
+ git version 1.8.4.msysgit.0
+ C:\Users\Andrew\Documents\GitHub\git-annex-test [master]> git annex version
+ git-annex version: 5.20140227-gd872677
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV DNS Feeds Quvi TDFA CryptoHash
+ key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256
+ SKEIN512 WORM URL
+ remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+ local repository version: 5
+ supported repository version: 5
+ upgrade supported from repository versions: 2 3 4
+ C:\Users\Andrew\Documents\GitHub\git-annex-test [master]> (Get-WmiObject -class Win32_OperatingSystem).Caption
+ Microsoft Windows 8.1
+
+### Please provide any additional information below.
+^^^ See above
diff --git a/doc/bugs/git-annex_fails_to_initialize_under_Windows/comment_1_082277b9b906a2cc0fcace6790f5cfad._comment b/doc/bugs/git-annex_fails_to_initialize_under_Windows/comment_1_082277b9b906a2cc0fcace6790f5cfad._comment
new file mode 100644
index 000000000..781528bcb
--- /dev/null
+++ b/doc/bugs/git-annex_fails_to_initialize_under_Windows/comment_1_082277b9b906a2cc0fcace6790f5cfad._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T20:50:55Z"
+ content="""
+That's a fairly old version of git-annex, so you could try upgrading.
+
+This might happen if your shell environment you're using to run git-annex does not have either USERPROFILE or HOME envorironment variable set, or does not have one of USERNAME, USER, and LOGNAME set.
+"""]]
diff --git a/doc/bugs/git_annex_content_fails_with_a_parse_error.txt b/doc/bugs/git_annex_content_fails_with_a_parse_error.mdwn
index 38c8fa28d..38c8fa28d 100644
--- a/doc/bugs/git_annex_content_fails_with_a_parse_error.txt
+++ b/doc/bugs/git_annex_content_fails_with_a_parse_error.mdwn
diff --git a/doc/bugs/git_annex_dead_does_not_work_as_expected_when_multiple_repos_exist_with_the_same_name___40__notably_including_dead_ones__41__.mdwn b/doc/bugs/git_annex_dead_does_not_work_as_expected_when_multiple_repos_exist_with_the_same_name___40__notably_including_dead_ones__41__.mdwn
index 7e26f63df..72a0c9cc3 100644
--- a/doc/bugs/git_annex_dead_does_not_work_as_expected_when_multiple_repos_exist_with_the_same_name___40__notably_including_dead_ones__41__.mdwn
+++ b/doc/bugs/git_annex_dead_does_not_work_as_expected_when_multiple_repos_exist_with_the_same_name___40__notably_including_dead_ones__41__.mdwn
@@ -40,3 +40,5 @@ Now, git annex dead somecopy will randomly (based on the order of the UUIDs?) ch
### What version of git-annex are you using? On what operating system?
git-annex 4.20131024 on linux. Also occurs on OSX.
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/git_annex_fsck_in_direct_mode_does_not_checksum_files/comment_2_4ac3b87ec0bc0514c4eff9f5a75b9f5d._comment b/doc/bugs/git_annex_fsck_in_direct_mode_does_not_checksum_files/comment_2_4ac3b87ec0bc0514c4eff9f5a75b9f5d._comment
index 1eb8b18e7..3befccd39 100644
--- a/doc/bugs/git_annex_fsck_in_direct_mode_does_not_checksum_files/comment_2_4ac3b87ec0bc0514c4eff9f5a75b9f5d._comment
+++ b/doc/bugs/git_annex_fsck_in_direct_mode_does_not_checksum_files/comment_2_4ac3b87ec0bc0514c4eff9f5a75b9f5d._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
nickname="Michael"
subject="comment 2"
diff --git a/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__.mdwn b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__.mdwn
index 2fb3d970b..619e8e5b8 100644
--- a/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__.mdwn
+++ b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__.mdwn
@@ -38,3 +38,5 @@ upgrade supported from repository versions: 0 1 2 4
# End of transcript or log.
"""]]
+
+> [[closing|done]], not a bug based on the limited description. --[[Joey]]
diff --git a/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_3_a234e4f58d2cc3b0110e4e65aceeb2c3._comment b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_3_a234e4f58d2cc3b0110e4e65aceeb2c3._comment
new file mode 100644
index 000000000..edf2b26a8
--- /dev/null
+++ b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_3_a234e4f58d2cc3b0110e4e65aceeb2c3._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawno-jcsScu4CK6k2QLZqxMros1PQHf1NQY"
+ nickname="Hugo"
+ subject="comment 3"
+ date="2014-03-13T14:36:20Z"
+ content="""
+> My conclusion is that some repository, perhaps the usb drive, made a commit that deleted those files. You should be able to find this commit with git log --stat, and can just git revert it if you want to.
+
+It would be surprising if I did that.
+
+Anyway, I was not able to find which commit deleted the ~600 files. I just decided to re-start completely with git annex :-/
+
+The good thing is that I did not lose any file, so in that regard git annex is great ;^)
+
+However, one thing that is quite confusing to me is the way git annex [sync] works. Am I supposed to run git annex sync in every repository? Because if I just run it once in 1 repo, then I usually don't get all the syncing done. Maybe I just don't understand something.
+
+Thanks for replying,
+
+[sync]: http://git-annex.branchable.com/sync/
+"""]]
diff --git a/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_4_a01a867500fd94e6b317e74a0b0b1401._comment b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_4_a01a867500fd94e6b317e74a0b0b1401._comment
new file mode 100644
index 000000000..6c519e632
--- /dev/null
+++ b/doc/bugs/git_annex_sync_deleted_a_bunch_of_files___40__not_expected__41__/comment_4_a01a867500fd94e6b317e74a0b0b1401._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 4"
+ date="2014-03-13T15:54:28Z"
+ content="""
+Did you run `git log --stat` and look for a commit that deleted a lot of files?
+"""]]
diff --git a/doc/bugs/git_annex_sync_in_direct_mode_does_not_honor_skip-worktree/comment_4_a7eab4171af7e46bcc637aacf630e9db._comment b/doc/bugs/git_annex_sync_in_direct_mode_does_not_honor_skip-worktree/comment_4_a7eab4171af7e46bcc637aacf630e9db._comment
new file mode 100644
index 000000000..c593d41e1
--- /dev/null
+++ b/doc/bugs/git_annex_sync_in_direct_mode_does_not_honor_skip-worktree/comment_4_a7eab4171af7e46bcc637aacf630e9db._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="ping?"
+ date="2014-03-19T20:54:57Z"
+ content="""
+You had a patch, but never shared it. I'm curious to see it..
+"""]]
diff --git a/doc/bugs/git_annex_test_under_windows_8.1.mdwn b/doc/bugs/git_annex_test_under_windows_8.1.mdwn
new file mode 100644
index 000000000..2ca64eb61
--- /dev/null
+++ b/doc/bugs/git_annex_test_under_windows_8.1.mdwn
@@ -0,0 +1,67 @@
+### Please describe the problem.
+I installed git and git annex under Windows (8.1) and ran git annex test. All except one tests passed with "ok"
+
+### What steps will reproduce the problem?
+git annex test
+under Windows 8.1
+
+### What version of git-annex are you using? On what operating system?
+$ git --version
+git version 1.9.0.msysgit.0
+
+$ git annex version
+git-annex version: 5.20140320-g63535e3
+build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV DNS Feeds Quvi TDFA CryptoHash key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external local repository version: 5 supported repository version: 5 upgrade supported from repository versions: 2 3 4
+
+Windows 8.1
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+ prop_view_roundtrips: FAIL
+ *** Failed! Falsifiable (after 814 tests and 5 shrinks):
+ "a"
+ IMneitta DTaetsat s(
+fr o miLniistt: [(MetaField "1\194",fromList [MetaValue (CurrentlySet True) "\r
++\231Gb\157\227\ETB\bG",MetaValue (CurrentlySet True) "\DEL\239~\243_p\DC2."]),(
+MetaField "EG",fromList [MetaValue (CurrentlySet True) "",MetaValue (CurrentlySe
+t True) "\v\205] .T(",MetaValue (CurrentlySet False) "\NAK\128lo\169w",MetaValue
+ (CurrentlySet True) "\SYN\STX\ENQ\n#u\ETXv\CANP<F)",MetaValue (CurrentlySet Fal
+se) "\US\213~",MetaValue (CurrentlySet False) "K\r3\v\165\&0\RSqk#\141",MetaValu
+e (CurrentlySet False) "Kx\b\231\156\220?+\216\v\146",MetaValue (CurrentlySet Tr
+ue) "j.\189\150\FS3{\233S\STX\SItg",MetaValue (CurrentlySet True) "\242\248\134\
+206\bal\174\135A\SI"]),(MetaField "k",fromList [MetaValue (CurrentlySet True) "\
+FS\150\129\b\fhjV\DC3\203",MetaValue (CurrentlySet False) "V.&sZ\245\f\a_\227\14
+0",MetaValue (CurrentlySet True) "\136r\ENQK{/\SI'\SYNN\235Q?",MetaValue (Curren
+tlySet True) "\179\255\233\227v\SUB]\n8",MetaValue (CurrentlySet True) "\238S\DC
+1"]),(MetaField "\179",fromList [MetaValue (CurrentlySet True) "\SOH+\ENQ",MetaV
+alue (CurrentlySet True) "\ACK{\140\248I\DLEw^\\\ENQF4",MetaValue (CurrentlySet
+False) "\FSc\239\r)HL\STX#V\DC1",MetaValue (CurrentlySet True) "Hc\219\146\230\1
+79\207",MetaValue (CurrentlySet False) "I]",MetaValue (CurrentlySet False) "P\19
+6\&0o\214\&8iH\251",MetaValue (CurrentlySet True) "`X",MetaValue (CurrentlySet F
+alse) "u\DEL\DC3Q\200",MetaValue (CurrentlySet True) "\128?",MetaValue (Currentl
+ySet True) "\225\135\f>\128\US~p",MetaValue (CurrentlySet False) "\250C\b\DC1\17
+6\154KT\191\SOf?\SI"]),(MetaField "\225a",fromList [MetaValue (CurrentlySet True
+) "",MetaValue (CurrentlySet True) "\b\ETB\b",MetaValue (CurrentlySet True) "\f\
+161\FS\176h-\ta\169\t",MetaValue (CurrentlySet False) "4",MetaValue (CurrentlySe
+t True) "A\FS\244V:\249kl5\ETX\SOH\SI)",MetaValue (CurrentlySet False) "Z",MetaV
+alue (CurrentlySet True) "\\Lt~\235v\"\211\DLE\NAK\210",MetaValue (CurrentlySet
+False) "a\SYNN",MetaValue (CurrentlySet True) "g:init test repo U5j\167G\ap-\ETX
+",MetaValue (CurrentlySet False) "l\NULoW\238rD",MetaValue (CurrentlySet True) "
+}\202\141\183Nxr",MetaValue (CurrentlySet False) "\170=\216S\ETB\187\SUB+!\DC3",
+MetaValue (CurrentlySet True) "\240H\GS\NAK\ETB\SYNRq\153\&4\204\EOT"])])
+ True
+ Use --quickcheck-replay '13 347062936 40785707' to reproduce.
+ prop_viewedFile_rountrips: OK
+ +++ OK, passed 1000 t
+e s tDse.t
+
+# End of transcript or log.
+"""]]
+
+> A sort of windows-specific bug in the test suite. I've fixed it. [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/id__95__rsa_on_android/comment_3_cbe24ed08a7ef91c8c0c20ab9b7d25b7._comment b/doc/bugs/id__95__rsa_on_android/comment_3_cbe24ed08a7ef91c8c0c20ab9b7d25b7._comment
new file mode 100644
index 000000000..b972139a6
--- /dev/null
+++ b/doc/bugs/id__95__rsa_on_android/comment_3_cbe24ed08a7ef91c8c0c20ab9b7d25b7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-12T19:45:24Z"
+ content="""
+Well, that would simplify the ssh patching.
+
+Putting a git repository on /sdcard also allows other apps to do things with .git/config. I don't know if git-annex has permissions other apps might want to exploit.. Maybe the ability to use the network?
+"""]]
diff --git a/doc/bugs/issues_with_non-posix_compatible_shells.mdwn b/doc/bugs/issues_with_non-posix_compatible_shells.mdwn
new file mode 100644
index 000000000..34fb72a1c
--- /dev/null
+++ b/doc/bugs/issues_with_non-posix_compatible_shells.mdwn
@@ -0,0 +1,41 @@
+### Please describe the problem.
+Some internals of git annex does not check if the shell it is running is Posix-compatible, ie. bash.
+
+I am using fish, and after setting up local pairing, and working, I switched back the login-shell to fish, and when syncing a file, I got this error, read from daemon.log:
+
+fish: Unknown command 'GIT_ANNEX_SHELL_DIRECTORY=/home/s/annex'. Did you mean to run ~/.ssh/git-annex-shell with a modified environment? Try 'env GIT_ANNEX_SHELL_DIRECTORY=/home/s/annex ~/.ssh/git-annex-shell...'. See the help section on the set command by typing 'help set'.
+Standard input: GIT_ANNEX_SHELL_DIRECTORY='/home/s/annex' ~/.ssh/git-annex-shell
+ ^
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+
+### What steps will reproduce the problem?
+Set up local pairing ( I believe having sh/bash as login terminal is necessary for this).
+Switch back to fish as login-shell with chsh -s /usr/bin/fish
+Add a file to either repository.
+
+### What version of git-annex are you using? On what operating system?
+[s@b ~]$ git annex version
+git-annex version: 5.20140320-g63535e3
+build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi TDFA CryptoHash
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] so
+>
+> I have not tried to make the assistant go back and fix up existing
+> `authorized_keys` lines. So if someone had been using a posix shell and
+> switched to fish, they'll hit this and need to fix it themselves. I judge
+> this is pretty small number of users. --[[Joey]]
diff --git a/doc/bugs/issues_with_non-posix_compatible_shells/comment_1_076948499a9d581a50da52b7690e5d4e._comment b/doc/bugs/issues_with_non-posix_compatible_shells/comment_1_076948499a9d581a50da52b7690e5d4e._comment
new file mode 100644
index 000000000..72b3e48e9
--- /dev/null
+++ b/doc/bugs/issues_with_non-posix_compatible_shells/comment_1_076948499a9d581a50da52b7690e5d4e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://johan.kiviniemi.name/"
+ nickname="Johan"
+ subject="comment 1"
+ date="2014-04-02T08:40:17Z"
+ content="""
+FWIW, `env foo=bar cmd` would probably work on every system on which the `foo=bar cmd` invocation works now.
+"""]]
diff --git a/doc/bugs/map_error_after_forget/comment_1_81001ecda65d882ea946611d1e18d59f._comment b/doc/bugs/map_error_after_forget/comment_1_81001ecda65d882ea946611d1e18d59f._comment
new file mode 100644
index 000000000..96d4bbffb
--- /dev/null
+++ b/doc/bugs/map_error_after_forget/comment_1_81001ecda65d882ea946611d1e18d59f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-15T15:53:17Z"
+ content="""
+This is a bit tricky because I'm not sure which repository the map is failing on. Probably the one that comes after /media/archive/annex in the `git remote list` output.
+
+If you go to each of the remotes and run `git config --null --list`, does it exit nonzero in any of them?
+"""]]
diff --git a/doc/bugs/map_error_after_forget/comment_2_24f3b6699f646ec0c20f3d4ca010e345._comment b/doc/bugs/map_error_after_forget/comment_2_24f3b6699f646ec0c20f3d4ca010e345._comment
new file mode 100644
index 000000000..6ac154ac1
--- /dev/null
+++ b/doc/bugs/map_error_after_forget/comment_2_24f3b6699f646ec0c20f3d4ca010e345._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkBEmz5XoJVzN0u-0nOtpn7BBBDHsiLmxY"
+ nickname="Eric"
+ subject="comment 2"
+ date="2014-03-15T16:17:18Z"
+ content="""
+actually i removed .../xubuntu/... from the initial bug report, here is the text scraped directly from xterm.
+
+
+xubuntu@tab:/media/xubuntu/archive/annex$ git annex map --debug
+map /media/xubuntu/archive/annex ok
+[2014-03-15 11:10:17 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2014-03-15 11:10:17 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2014-03-15 11:10:17 CDT] read: git [\"config\",\"--null\",\"--list\"]
+
+git-annex: user error (git [\"config\",\"--null\",\"--list\"] exited 126)
+failed
+git-annex: map: 1 failed
+xubuntu@tab:/media/xubuntu/archive/annex$ git remote
+archive-backup
+bkup06-a81d-1000
+bkup08-da84-1000
+bkup19-0064
+master
+master-backup
+...
+no obvious errors on non-zero return codes from running `git config --null --list` on all remotes
+"""]]
diff --git a/doc/bugs/map_error_after_forget/comment_3_950e735c6d618e60cffffd1aebf06fd3._comment b/doc/bugs/map_error_after_forget/comment_3_950e735c6d618e60cffffd1aebf06fd3._comment
new file mode 100644
index 000000000..c6c56a326
--- /dev/null
+++ b/doc/bugs/map_error_after_forget/comment_3_950e735c6d618e60cffffd1aebf06fd3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-15T21:41:13Z"
+ content="""
+Since this is map, it could be one of the remotes of /media/xubuntu/archive/annex, or one of the remotes of one of the remotes, etc. Pretty sure it's a local repository it's choking on, and not a ssh remote though.
+"""]]
diff --git a/doc/bugs/map_error_after_forget/comment_4_39327211f3fd1f9ed196a1f09cf68bdc._comment b/doc/bugs/map_error_after_forget/comment_4_39327211f3fd1f9ed196a1f09cf68bdc._comment
new file mode 100644
index 000000000..2795a9962
--- /dev/null
+++ b/doc/bugs/map_error_after_forget/comment_4_39327211f3fd1f9ed196a1f09cf68bdc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkBEmz5XoJVzN0u-0nOtpn7BBBDHsiLmxY"
+ nickname="Eric"
+ subject="comment 4"
+ date="2014-03-16T04:52:19Z"
+ content="""
+i don't have any ssh remotes yet. these are all local. so if it is one of the remotes, then what do i do to get it un-choked?
+"""]]
diff --git a/doc/bugs/map_error_after_forget/comment_6_471a2f5792dfc7cde4f1eb793984abf1._comment b/doc/bugs/map_error_after_forget/comment_6_471a2f5792dfc7cde4f1eb793984abf1._comment
new file mode 100644
index 000000000..3825b2e54
--- /dev/null
+++ b/doc/bugs/map_error_after_forget/comment_6_471a2f5792dfc7cde4f1eb793984abf1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 6"
+ date="2014-03-17T19:30:37Z"
+ content="""
+I was able to easily reproduce this kind of failure by making a git repository have a remote that did not exist.
+"""]]
diff --git a/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames.mdwn b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames.mdwn
new file mode 100644
index 000000000..7715a6f28
--- /dev/null
+++ b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames.mdwn
@@ -0,0 +1,29 @@
+### Please describe the problem.
+Filenames for the *include* statement for [preferred content](http://git-annex.branchable.com/preferred_content/) can not contain spaces.
+
+### What steps will reproduce the problem?
+
+* Create an annex repo
+* Run `git annex vicfg`
+* Enter expression *include='pictures/dir with spaces'*
+* git annex complains: # ** Parse error in next line: Parse failure: near "with" Parse failure: near "spaces'"
+
+(The *'* is interpreted as part of the filepath.)
+
+### What version of git-annex are you using? On what operating system?
+
+I am using the current binaries from Debian stable amd64.
+
+<pre>
+git-annex version: 5.20140320~bpo70+1
+build flags: Assistant Webapp Pairing S3 Inotify DBus XMPP Feeds Quvi TDFA
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+remote types: git gcrypt S3 bup directory rsync web tahoe glacier hook external
+local repository version: 5
+supported repository version: 5
+upgrade supported from repository versions: 0 1 2 4
+</pre>
+
+### Please provide any additional information below.
+
+The only workaround I found is to use a glob for the filepath which only works for the first space: *include='pictures/dir\*'*.
diff --git a/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_1_ca10638d4b4b178cfd0de8736542c4dc._comment b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_1_ca10638d4b4b178cfd0de8736542c4dc._comment
new file mode 100644
index 000000000..a7438c559
--- /dev/null
+++ b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_1_ca10638d4b4b178cfd0de8736542c4dc._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T18:45:36Z"
+ content="""
+A better workaround is:
+
+include='pictures/dir?with?spaces'
+
+Tokenizing text with embedded quotes is a bit of a PITA, certianly doable I suppose..
+"""]]
diff --git a/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_2_986a393a512229d35e529ba242b77b1e._comment b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_2_986a393a512229d35e529ba242b77b1e._comment
new file mode 100644
index 000000000..7dbeb3d08
--- /dev/null
+++ b/doc/bugs/preferred_content:_include_statement_does_not_allow_spaces_in_filenames/comment_2_986a393a512229d35e529ba242b77b1e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://ypid.wordpress.com/"
+ ip="213.153.84.215"
+ subject="comment 2"
+ date="2014-04-02T21:29:54Z"
+ content="""
+Thanks for your workaround ... Works for me after removing the single quote signs.
+
+With this workaround on hand one could include/match any filename. Works for me ;)
+"""]]
diff --git a/doc/bugs/problem_to_addurl_--file_with_ftp.mdwn b/doc/bugs/problem_to_addurl_--file_with_ftp.mdwn
new file mode 100644
index 000000000..99381b961
--- /dev/null
+++ b/doc/bugs/problem_to_addurl_--file_with_ftp.mdwn
@@ -0,0 +1,67 @@
+### Please describe the problem.
+I want to addurl using ftp protocol.
+`git annex addurl ftp://...` works fine, but `git annex addurl --file` fails with an error "failed to verify url exists".
+
+### What steps will reproduce the problem?
+
+setting up a new repo
+
+ % alias ga
+ ga=/home/applis/git-annex.linux/git-annex
+ % ga init
+ init ok
+ (Recording state in git...)
+
+addurl --file works with http
+
+ % wget http://downloads.kitenet.net/git-annex/linux/current/git-annex-standalone-amd64.tar.gz
+ [...]
+ 2014-03-27 15:25:06 (10,1 MB/s) - ‘git-annex-standalone-amd64.tar.gz’ saved [30689438/30689438]
+ % ga add git-annex-standalone-amd64.tar.gz
+ add git-annex-standalone-amd64.tar.gz ok
+ (Recording state in git...)
+ % ga addurl http://downloads.kitenet.net/git-annex/linux/current/git-annex-standalone-amd64.tar.gz --file git-annex-standalone-amd64.tar.gz
+ addurl git-annex-standalone-amd64.tar.gz ok
+ (Recording state in git...)
+
+addurl works with ftp:
+
+ % ga addurl ftp://ftp.belnet.be/debian-cd/7.4.0-live/i386/iso-hybrid/debian-live-7.4-i386-lxde-desktop.iso.log
+ addurl ftp.belnet.be_debian_cd_7.4.0_live_i386_iso_hybrid_debian_live_7.4_i386_lxde_desktop.iso.log (downloading ftp://ftp.belnet.be/debian-cd/7.4.0-live/i386/iso-hybrid/debian-live-7.4-i386-lxde-desktop.iso.log ...)
+ [...]
+ 2014-03-27 15:27:47 (11,1 MB/s) - ‘/data/annex/.git/annex/tmp/URL--ftp&c%%ftp.belnet.be%debian-cd%7.4.0-live%i386%iso-hybrid%debian-live-7.4-i386-lxde-desktop.iso.log’ saved [1235181]
+ ok
+ (Recording state in git...)
+
+addurl --file doesn't work with ftp
+
+ % wget ftp://ftp.belnet.be/debian-cd/7.4.0-live/i386/iso-hybrid/debian-live-7.4-i386-standard.iso.zsync
+ [...]
+ 2014-03-27 15:29:32 (19,4 MB/s) - ‘debian-live-7.4-i386-standard.iso.zsync’ saved [1932014]
+ % ga add debian-live-7.4-i386-standard.iso.zsync
+ add debian-live-7.4-i386-standard.iso.zsync ok
+ (Recording state in git...)
+ % ga addurl ftp://ftp.belnet.be/debian-cd/7.4.0-live/i386/iso-hybrid/debian-live-7.4-i386-standard.iso.zsync --file debian-live-7.4-i386-standard.iso.zsync
+ addurl debian-live-7.4-i386-standard.iso.zsync
+ failed to verify url exists: ftp://ftp.belnet.be/debian-cd/7.4.0-live/i386/iso-hybrid/debian-live-7.4-i386-standard.iso.zsync
+ failed
+ git-annex: addurl: 1 failed
+
+### What version of git-annex are you using? On what operating system?
+
+I am using current git-annex binary linux version on Fedora 19.
+
+ % which git ; git --version
+ /usr/bin/git
+ git version 1.8.3.1
+ % which ga ; ga version
+ ga=/home/applis/git-annex.linux/git-annex
+ git-annex version: 5.20140320-g63535e3
+ build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi TDFA CryptoHash
+ key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+ remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+ local repository version: 5
+ supported repository version: 5
+ upgrade supported from repository versions: 0 1 2 4
+
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/problem_to_addurl_--file_with_ftp/comment_1_2bf44f1653069fb2ed0b124cf8581a48._comment b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_1_2bf44f1653069fb2ed0b124cf8581a48._comment
new file mode 100644
index 000000000..f4e98a621
--- /dev/null
+++ b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_1_2bf44f1653069fb2ed0b124cf8581a48._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-27T17:27:58Z"
+ content="""
+--file does not change git-annex addurl's network communication in any way. I think this ftp server is sometimes working, and other times failing. It seems to be returning a 350 result code. The FTP spec is not clear what that means, but it does not seem to indicate success.
+"""]]
diff --git a/doc/bugs/problem_to_addurl_--file_with_ftp/comment_2_c85266a9359a9f45e632f31c016a45dc._comment b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_2_c85266a9359a9f45e632f31c016a45dc._comment
new file mode 100644
index 000000000..bab883611
--- /dev/null
+++ b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_2_c85266a9359a9f45e632f31c016a45dc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmdbVIGiDH8KarAGAy8y2FHJD_F990JzXI"
+ nickname="François"
+ subject="comment 2"
+ date="2014-04-01T08:55:29Z"
+ content="""
+Ok, it works when adding option --relaxed. For some reason there seems to be a problem when checking file size.
+"""]]
diff --git a/doc/bugs/problem_to_addurl_--file_with_ftp/comment_3_5bba62e1dd4118bcf7e1c990c7009239._comment b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_3_5bba62e1dd4118bcf7e1c990c7009239._comment
new file mode 100644
index 000000000..11265f6db
--- /dev/null
+++ b/doc/bugs/problem_to_addurl_--file_with_ftp/comment_3_5bba62e1dd4118bcf7e1c990c7009239._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 3"
+ date="2014-04-02T19:18:19Z"
+ content="""
+Yes, --relaxed bypasses the code that uses curl to check the file size.
+
+Ok, I have figured out what's going on.
+
+git annex addurl --file foo ftp://host # this succeeds
+
+run the command a second time, and it fails. Why? Because the file is already present in the annex, and you are running addurl in a different mode. In this mode, it is adding a *new* url to the file in the annex. (In this particular case, the new and old url are the same, but it's possible to see this bug in cases where they are not, too.)
+
+As a sanity check, when adding a new url to an existing file, git-annex wants to check that the new url has the same size as the file. Otherwise it surely has different content. However, as I noted this ftp server is returning a weird 350 response when curl is used to try to get the size of the url. So that fails, and git-annex cannot add the new url to the file. Which would be pointless in this case anyway, since it's the same as the old url.
+
+So, I can fix two things. I can make it detect when the url it's adding to an existing file in the annex is already a known url of that file, and skip doing anything in this case since it would be a no-op anyway. Done that.
+
+And, I can improve the error message so the user is not confused about what they're asking git-annex to do, and why it's unable to. Fixed that.
+
+This leaves the question of why curl sees a 350 code from this ftp server. But since it doesn't cause problems when using addurl, with or without --file to download the file from it, I think it's best to punt on that one.
+"""]]
diff --git a/doc/bugs/problems_with_glacier.mdwn b/doc/bugs/problems_with_glacier.mdwn
new file mode 100644
index 000000000..60e2f7e69
--- /dev/null
+++ b/doc/bugs/problems_with_glacier.mdwn
@@ -0,0 +1,65 @@
+### Please describe the problem.
+Annex errors when copying to glacier.
+
+### What version of git-annex are you using? On what operating system?
+
+OS X 10.9.2 Build 13C64
+
+ git-annex version: 5.20140318-gdcf93d0
+ build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi TDFA CryptoHash
+ key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+ remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+ local repository version: 5
+ supported repository version: 5
+ upgrade supported from repository versions: 0 1 2 4
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+> git annex initremote glacier type=glacier encryption=hybrid keyid=E9053BDA datacenter=us-west-1 ║██████████╠ ∞ ∞
+initremote glacier (encryption setup) (hybrid cipher with gpg key B608B8F6E9053BDA) ok
+(Recording state in git...)
+> git annex copy Cobalt\ Strike\ Tradecraft --to=glacier --debug
+[2014-03-27 07:27:39 PDT] read: git ["--git-dir=/Users/akraut/Desktop/annexes/media/.git","--work-tree=/Users/akraut/Desktop/annexes/media","show-ref","git-annex"]
+[2014-03-27 07:27:39 PDT] read: git ["--git-dir=/Users/akraut/Desktop/annexes/media/.git","--work-tree=/Users/akraut/Desktop/annexes/media","show-ref","--hash","refs/heads/git-annex"]
+[2014-03-27 07:27:39 PDT] read: git ["--git-dir=/Users/akraut/Desktop/annexes/media/.git","--work-tree=/Users/akraut/Desktop/annexes/media","log","refs/heads/git-annex..9f59057d857784e6ae6b3dcd6793092264375913","--oneline","-n1"]
+[2014-03-27 07:27:39 PDT] chat: git ["--git-dir=/Users/akraut/Desktop/annexes/media/.git","--work-tree=/Users/akraut/Desktop/annexes/media","cat-file","--batch"]
+[2014-03-27 07:27:39 PDT] read: git ["config","--null","--list"]
+[2014-03-27 07:27:39 PDT] read: git ["--git-dir=/Users/akraut/Desktop/annexes/media/.git","--work-tree=/Users/akraut/Desktop/annexes/media","ls-files","--cached","-z","--","Cobalt Strike Tradecraft"]
+copy Cobalt Strike Tradecraft/Tradecraft__1_of_9____Introduction.mp4 (gpg) [2014-03-27 07:27:39 PDT] chat: gpg ["--quiet","--trust-model","always","--decrypt"]
+
+You need a passphrase to unlock the secret key for
+user: "Andrew Mark Kraut <akraut@gmail.com>"
+4096-bit ELG-E key, ID 353E49B9, created 2008-11-11 (main key ID E9053BDA)
+
+(checking glacier...) [2014-03-27 07:27:46 PDT] read: glacier ["--region=us-west-1","archive","checkpresent","git-annex: Maybe.fromJust: Nothing
+
+# End of transcript or log.
+"""]]
+
+> This was a bug introduced last month, it forgot to receord the
+> datacenter and vault used when initializing the glacier repository.
+>
+> I've fixed the bug, but this does not fix repositories created with
+> the broken version. I considered just making it use the default
+> datacenter and vault for such a repository, but
+> a) those may change in the future
+> and I don't want to have to worry about breaking such a repository
+> going forward and b) someone may have overridden it to use another
+> datacenter or vault name and so it shouldn't blindly assume the defaults.
+>
+> Instead, there's a manual fix up step you need to do. Luckily quite easy.
+> For example:
+>
+> git annex enableremote myglacier datacenter=us-east-1 vault=myglacier-fae9be57-8eb4-47af-932f-136b9b40e669
+>
+> The default datacenter is us-east-1, and the default vault name is
+> "$remotename-$uuid". So you just have to tell it these values
+> once with an enableremote command, and it will then work.
+
+> You don't even need to get the fixed version of git-annex to work
+> around the bug this way.. Although it does have better error messages
+> too. [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/problems_with_glacier/comment_1_8d233428a16ae4276d9c69b329e8216b._comment b/doc/bugs/problems_with_glacier/comment_1_8d233428a16ae4276d9c69b329e8216b._comment
new file mode 100644
index 000000000..e4556dc82
--- /dev/null
+++ b/doc/bugs/problems_with_glacier/comment_1_8d233428a16ae4276d9c69b329e8216b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmRFKwny4rArBaz-36xTcsJYqKIgdDaw5Q"
+ nickname="Andrew"
+ subject="comment 1"
+ date="2014-03-27T14:46:19Z"
+ content="""
+I just updated to the latest glacier-cli and boto and have confirmed that those are working properly and that the vault has been created on glacier:
+[[!format sh \"\"\"
+> glacier --region=us-west-1 vault list
+glacier-571d1ec3-8870-46cb-977e-15830a2b474d
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/set_metadata_on_wrong_files.mdwn b/doc/bugs/set_metadata_on_wrong_files.mdwn
new file mode 100644
index 000000000..e31714784
--- /dev/null
+++ b/doc/bugs/set_metadata_on_wrong_files.mdwn
@@ -0,0 +1,90 @@
+### Please describe the problem.
+
+For an example I wanted to add different metadata to some test files,
+but the outcome is that the last metadata gets applied to all three files. see transcript below.
+
+
+
+### What steps will reproduce the problem?
+
+1. Create a git annex repository
+2. add a few files
+3. add some metadata to the files, same keys, differnt values
+4. watch the metadata, only the last added one is shown for all files
+
+
+### What version of git-annex are you using? On what operating system?
+ $cat /etc/debian_version; uname -a; git annex version
+ 7.4
+ Linux jupiter 3.13.0ct #33 SMP PREEMPT Tue Jan 21 05:04:01 CET 2014 x86_64 GNU/Linux
+ git-annex version: 5.20140306~bpo70+1
+ build flags: Assistant Webapp Pairing S3 Inotify DBus XMPP Feeds Quvi TDFA
+ key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+ remote types: git gcrypt S3 bup directory rsync web tahoe glacier hook external
+ local repository version: 5
+ supported repository version: 5
+ upgrade supported from repository versions: 0 1 2 4
+
+
+### Please provide any additional information below.
+
+Debian/Wheezy with git annex from backports. The test was done in /tmp which is a tmpfs.
+
+
+[[!format sh """
+$export LC_ALL=C
+$mkdir /tmp/annextest
+$cd /tmp/annextest
+$git init
+Initialized empty Git repository in /tmp/annextest/.git/
+$git annex init
+init ok
+(Recording state in git...)
+
+$touch a.txt b.txt c.txt
+$git annex add a.txt b.txt c.txt
+add a.txt ok
+add b.txt ok
+add c.txt ok
+(Recording state in git...)
+$git commit -m init
+[master (root-commit) 5470bdb] init
+ 3 files changed, 3 insertions(+)
+ create mode 120000 a.txt
+ create mode 120000 b.txt
+ create mode 120000 c.txt
+
+$git annex metadata a.txt -s foo=bar -s num=1
+metadata a.txt
+ foo=bar
+ num=1
+ok
+(Recording state in git...)
+$git annex metadata b.txt -s foo=baz -s num=2
+metadata b.txt
+ foo=baz
+ num=2
+ok
+(Recording state in git...)
+$git annex metadata c.txt -s foo=barf -s num=3
+metadata c.txt
+ foo=barf
+ num=3
+ok
+(Recording state in git...)
+$git annex metadata
+metadata a.txt
+ foo=barf
+ num=3
+ok
+metadata b.txt
+ foo=barf
+ num=3
+ok
+metadata c.txt
+ foo=barf
+ num=3
+ok
+"""]]
+
+> [[fixed|done]]; documentation improved --[[Joey]]
diff --git a/doc/bugs/set_metadata_on_wrong_files/comment_1_074f124e5d313e90b3e9217325799587._comment b/doc/bugs/set_metadata_on_wrong_files/comment_1_074f124e5d313e90b3e9217325799587._comment
new file mode 100644
index 000000000..f7a47d2fe
--- /dev/null
+++ b/doc/bugs/set_metadata_on_wrong_files/comment_1_074f124e5d313e90b3e9217325799587._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T20:55:07Z"
+ content="""
+This is because metadata applies to the contents of files, and all 3 of your files have the same single content. I will update the documentation to make it more clear metadata works this way.
+"""]]
diff --git a/doc/bugs/ssh:_unprotected_private_key_file.mdwn b/doc/bugs/ssh:_unprotected_private_key_file.mdwn
new file mode 100644
index 000000000..207ef76d1
--- /dev/null
+++ b/doc/bugs/ssh:_unprotected_private_key_file.mdwn
@@ -0,0 +1,62 @@
+### Please describe the problem.
+
+When pairing two machines with git-annex assistant, the assistant kept asking for the ssh password. Checking the git-annex daemon logs, I saw that ssh was refusing to use the key the assistant had created because it was group readable (see below for the log extract).
+
+### What steps will reproduce the problem?
+
+The assistant was installed from the ubuntu precise ppa backport on an up-to-date copy of ubuntu precise.
+It was started using "git-annex webapp --listen=XYZ".
+This was done on two machines on the same network.
+Created a repository using the web-app, the same on both machines.
+Did a pair request. This initially worked fine, until it got to the point of using ssh, when it started asking for the password many many times.
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 5.20140306
+build flags: Assistant Webapp Pairing S3 WebDAV Inotify DBus XMPP Feeds Quvi TDFA CryptoHash
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+local repository version: 5
+supported repository version: 5
+upgrade supported from repository versions: 0 1 2 4
+
+Ubuntu 12.04.4 LTS
+
+### Please provide any additional information below.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+(started...) Generating public/private rsa key pair.
+Your identification has been saved in /tmp/git-annex-keygen.0/key.
+Your public key has been saved in /tmp/git-annex-keygen.0/key.pub.
+The key fingerprint is:
+2b:f4:28:35:72:2c:9e:5b:d3:1d:d1:a1:b7:c7:a5:34 ABC@XYZ
+The key's randomart image is:
++--[ RSA 2048]----+
+| . |
+| o . |
+| o o E .|
+| . o + + |
+| o * S . . + |
+| . B = o . . |
+| + = + . |
+| + o |
+| . |
++-----------------+
+[2014-03-14 13:35:45 GMT] main: Pairing in progress
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+Permissions 0620 for 'ABC/.ssh/git-annex/key.git-annex-XYZ_annex' are too open.
+It is required that your private key files are NOT accessible by others.
+This private key will be ignored.
+bad permissions: ignore key: ABC/.ssh/git-annex/key.git-annex-XYZ_annex
+(merging XYZ_annex/git-annex into git-annex...)
+
+# End of transcript or log.
+"""]]
+
+> [[Fixed|done]]; the code made sure the file did not have any group or
+> world read bits, but did not clear write bits. --[[Joey]]
diff --git a/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__.mdwn b/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__.mdwn
new file mode 100644
index 000000000..d03943da6
--- /dev/null
+++ b/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__.mdwn
@@ -0,0 +1,10 @@
+### Please describe the problem.
+git annex webapp created SSH keys for remote directory. SSH keys have wrong permission (chmod 600 fixed it) and thus the key-based login to the remote fails.
+
+### What steps will reproduce the problem?
+Creating a SSH remote using the git annex webapp.
+
+### What version of git-annex are you using? On what operating system?
+'current linux build for amd64', downloaded Mar 6th 2014, on Ubuntu 12.04.4 LTS.
+
+> [[done]]
diff --git a/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__/comment_1_462c377dca2484e5598a0b71d91ab64a._comment b/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__/comment_1_462c377dca2484e5598a0b71d91ab64a._comment
new file mode 100644
index 000000000..92dbf283c
--- /dev/null
+++ b/doc/bugs/ssh_keys_have_wrong_permissions___40__Ubuntu_12.04_LTS__44___current_linux_build_as_of_Mar_6th___39__14__41__/comment_1_462c377dca2484e5598a0b71d91ab64a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T19:53:04Z"
+ content="""
+This is a duplicate of [[bugs/ssh:_unprotected_private_key_file]], which was fixed on March 14th.
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument.mdwn b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument.mdwn
new file mode 100644
index 000000000..cc9a4c57f
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument.mdwn
@@ -0,0 +1,87 @@
+### Please describe the problem.
+
+#### git annex unused fails with the message:
+
+...
+ 86731 SHA256E-s13243--a6c5fe9710975e0b0ca01ec0b7eca6068a01b1b1c06adbd8ad7921e26d3b076d.h
+
+ 86732 SHA256E-s12872--f50b73d313a116ea21649d684f601840dbc8ed3c264165dd77fa5d54a1c57464.c
+
+ 86733 SHA256E-s6557264--6b502d56378b9919fd3c54c3bb2dc2906a326be8e9d477a8f3518419929f4706.dll
+
+ 86734 SHA256E-s141--c6227fe715dab2b4447b6e43af2b170ac66d82043aa81a14013c56be922e11db.out
+
+ 86735 SHA256E-s6564--ec4bcd833d071fff7d8cc81b908558acdeae2c9ba62f7d65b584effe6b36a8c6.c
+
+git-annex: /bluepool/data/.git/annex/unused32594.tmp: commitBuffer: invalid argument (invalid character)
+failed
+
+git-annex: unused: 1 failed
+
+#### A subsequent git annex dropunused does not work (there are 86735 files unused). A simple:
+"git annex dropunused 1-10" produces:
+
+git-annex: 1 not valid (run git annex unused for list)
+
+#### It seems that the list of unused files was not saved (committed)
+
+### What steps will reproduce the problem?
+
+I suspect it can be reproduced by having files with non-english characters.
+This should be the sequence of commands to reproduce if one knew the invalid character:
+
+git init .
+
+git annex init .
+
+touch "Invalid character in file name"
+
+git annex add "Invalid character in file name"
+
+git commit
+
+git rm "Invalid character in file name"
+
+git commit
+
+git unused
+
+However, I usually have "git annex watch" running so this might also have an influence on how (maybe not-escaped) filenames are added.
+
+### What version of git-annex are you using? On what operating system?
+
+git annex standalone:
+
+git-annex version: 5.20140306-g6e2e021
+
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi TDFA CryptoHash
+
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+
+local repository version: 5
+
+supported repository version: 5
+
+upgrade supported from repository versions: 0 1 2 4
+
+
+
+Ubuntu Raring: Linux i3 3.11.4-031104-generic
+
+
+### Please provide any additional information below.
+
+I guess I could provide the full output of git annex unused but I would rather not put it into this bug report for privacy reasons.
+
+[[!format sh """
+# If you can, paste a complete transcript of the problem occurring here.
+# If the problem is with the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
+
+> [[closing|done]], would still be nice to have verification my fix worked.
+> --[[Joey]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_1_004cb3015895ad67386276f3e1f0de0d._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_1_004cb3015895ad67386276f3e1f0de0d._comment
new file mode 100644
index 000000000..e1db22b2e
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_1_004cb3015895ad67386276f3e1f0de0d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-15T16:01:53Z"
+ content="""
+I see the problem, although I have not quite managed to reproduce it. I think this would probably only happen if you have the unusual character in the extension of the file (or are using the WORM backend).
+
+I've put a fix in git. It will be available in the next autobuild, in half an hour or so.
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_2_3fe298ebb3ff04d12f2528aa982d7084._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_2_3fe298ebb3ff04d12f2528aa982d7084._comment
new file mode 100644
index 000000000..ed5733d04
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_2_3fe298ebb3ff04d12f2528aa982d7084._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmp1ThsNNAbSn46ju-gwFELfStlhl8usJo"
+ nickname="donkeyicydragon"
+ subject="Problem still occurs but maybe my update did not work"
+ date="2014-03-16T18:01:24Z"
+ content="""
+Hi Joey, thanks for the quick response.
+
+I tried to update and retry my \"git annex unused\" but it gave the same error. Maybe my updating did not work (see below). But is there a way I can retry it without running \"git annex unused\" again? The problem is that each run takes several hours with my amount of files.
+It would be nice, if git annex recognized some error in the last approach and recovered.
+The tmp files that are created by \"git annex unused\" are still in .git/annex/.
+
+
+Regarding the updating:
+I tried to obtain the autobuild version but on this website I could not find a link to download the latest autobuild. I could only find the build reports. But I used the git annex installer script from https://github.com/zerodogg/scriptbucket/blob/master/gitannex-install
+and it apparently knows the location of the daily build. Is this the autobuild or is git annex autobuilt more often?
+
+This is my version after installing it yesterday evening approx. 2h hours after your answer to the bug description.
+
+git-annex version: 5.20140314-g48e0f18
+build flags: Assistant Webapp Webapp-secure Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi TDFA CryptoHash
+key/value backends: SHA256E SHA1E SHA512E SHA224E SHA384E SKEIN256E SKEIN512E SHA256 SHA1 SHA512 SHA224 SHA384 SKEIN256 SKEIN512 WORM URL
+remote types: git gcrypt S3 bup directory rsync web webdav tahoe glacier hook external
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_3_9302536d1577c12337d714fa3a9ea7a1._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_3_9302536d1577c12337d714fa3a9ea7a1._comment
new file mode 100644
index 000000000..e74ccba1c
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_3_9302536d1577c12337d714fa3a9ea7a1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-17T19:28:05Z"
+ content="""
+No, your version is from before I fixed it.
+
+You can get an autobuild from [[install/Linux_standalone]]
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_4_c1c8de66192957b7026d99b9ff90589c._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_4_c1c8de66192957b7026d99b9ff90589c._comment
new file mode 100644
index 000000000..b229545f6
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_4_c1c8de66192957b7026d99b9ff90589c._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmp1ThsNNAbSn46ju-gwFELfStlhl8usJo"
+ nickname="donkeyicydragon"
+ subject="Maybe the autobuild is broken?"
+ date="2014-03-17T20:32:19Z"
+ content="""
+The latest autobuild log for amd64 says:
+Starting at: Fri Mar 14 21:42:07 UTC 2014
+
+I downloaded the amd64 autobuild from https://git-annex.branchable.com/install/Linux_standalone/
+
+and it indeed is from Friday.
+
+Cheers,
+Marek
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_5_8c2dad766e4115073d49b698919b5ed5._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_5_8c2dad766e4115073d49b698919b5ed5._comment
new file mode 100644
index 000000000..360003fba
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_5_8c2dad766e4115073d49b698919b5ed5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 5"
+ date="2014-03-18T19:07:25Z"
+ content="""
+cron was not running them for some reason, but they are up-to-date now.
+"""]]
diff --git a/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_6_8da2a73381309ecef4b2796d8f2bb0bb._comment b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_6_8da2a73381309ecef4b2796d8f2bb0bb._comment
new file mode 100644
index 000000000..8532afaf7
--- /dev/null
+++ b/doc/bugs/unused_fails_due_to_commitBuffer_containing_an_invalid_argument/comment_6_8da2a73381309ecef4b2796d8f2bb0bb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmp1ThsNNAbSn46ju-gwFELfStlhl8usJo"
+ nickname="donkeyicydragon"
+ subject="Your changes to git annex worked"
+ date="2014-03-19T21:27:39Z"
+ content="""
+Thanks a lot.
+
+BTW, will you start a new funding round?
+"""]]
diff --git a/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote.mdwn b/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote.mdwn
index ee69014d2..98ee21d16 100644
--- a/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote.mdwn
+++ b/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote.mdwn
@@ -26,3 +26,5 @@ lrwxrwxrwx 1 jkt jkt 329 Mar 3 02:08 2011-08-13 Svatba Anička Fellnerová a v
The directory names are valid UTF-8. These are very common on my machine and there is a ton of directories with these funny names here -- all working without any real trouble.
As far as I know, the file which the links point to is absolutely correct and not corrupted. Looking at the files in the directory chronologically, it also appears that the symlinks point to a correct file.
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote/comment_2_f430538101f0ef6114b5e953248fa599._comment b/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote/comment_2_f430538101f0ef6114b5e953248fa599._comment
new file mode 100644
index 000000000..e78971a90
--- /dev/null
+++ b/doc/bugs/whereis_claims_file_is_not_here__44___but_it_is_available_both_here_and_in_another_remote/comment_2_f430538101f0ef6114b5e953248fa599._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="ping?"
+ date="2014-03-19T20:24:23Z"
+ content="""
+Have you tried running git-annex fsck?
+"""]]
diff --git a/doc/bugs/whereis_outputs_no_informaiton_for_unlocked_files/comment_1_47bd0fc8d1c65f8a868d9722e66c71db._comment b/doc/bugs/whereis_outputs_no_informaiton_for_unlocked_files/comment_1_47bd0fc8d1c65f8a868d9722e66c71db._comment
new file mode 100644
index 000000000..e92ec33f9
--- /dev/null
+++ b/doc/bugs/whereis_outputs_no_informaiton_for_unlocked_files/comment_1_47bd0fc8d1c65f8a868d9722e66c71db._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 1"
+ date="2014-03-19T20:52:08Z"
+ content="""
+The reason this doesn't work is that, in indirect mode, git-annex looks at the current state of the symlink in the work tree to know what key is associated with a file. And an unlocked file has no symlink.
+
+Direct mode avoids this problem, but at the expense of being less flexible and well, doing more work.
+"""]]
diff --git a/doc/copies.mdwn b/doc/copies.mdwn
index 205d2d5b1..3e0ebc6c6 100644
--- a/doc/copies.mdwn
+++ b/doc/copies.mdwn
@@ -30,3 +30,6 @@ refuse to do so.
With N=2, in order to drop the file content from Laptop, it would need access
to both USB and Server.
+
+For more complicated requirements about which repositories contain which
+content, see [[required_content]].
diff --git a/doc/design/assistant/blog/day_288__success_stories/comment_15_5749aef8b585b293385b20b75c40f9d8._comment b/doc/design/assistant/blog/day_288__success_stories/comment_15_5749aef8b585b293385b20b75c40f9d8._comment
index d8c99640b..cefc5045c 100644
--- a/doc/design/assistant/blog/day_288__success_stories/comment_15_5749aef8b585b293385b20b75c40f9d8._comment
+++ b/doc/design/assistant/blog/day_288__success_stories/comment_15_5749aef8b585b293385b20b75c40f9d8._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="http://jasonwoof.com/"
nickname="JasonWoof"
subject="It's been great!"
diff --git a/doc/design/assistant/blog/day_45__long_polling/comment_3_5526c9dd4fd87da56cb8456083169f55._comment b/doc/design/assistant/blog/day_45__long_polling/comment_3_5526c9dd4fd87da56cb8456083169f55._comment
index 4880bd98d..7881bcda5 100644
--- a/doc/design/assistant/blog/day_45__long_polling/comment_3_5526c9dd4fd87da56cb8456083169f55._comment
+++ b/doc/design/assistant/blog/day_45__long_polling/comment_3_5526c9dd4fd87da56cb8456083169f55._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawmz8d2M0lQDYWLSbDQSjYRHfrQkWKgPu60"
nickname="Alex"
subject="long polling in Widget form"
diff --git a/doc/design/assistant/polls/Android_default_directory.mdwn b/doc/design/assistant/polls/Android_default_directory.mdwn
index 0e5ade06a..869aedf4b 100644
--- a/doc/design/assistant/polls/Android_default_directory.mdwn
+++ b/doc/design/assistant/polls/Android_default_directory.mdwn
@@ -4,4 +4,4 @@ Same as the desktop webapp, users will be able to enter a directory they
want the first time they run it, but to save typing on android, anything
that gets enough votes will be included in a list of choices as well.
-[[!poll open=yes expandable=yes 63 "/sdcard/annex" 6 "Whole /sdcard" 5 "DCIM directory (photos and videos only)" 1 "Same as for regular git-annex. ~/annex/"]]
+[[!poll open=yes expandable=yes 66 "/sdcard/annex" 6 "Whole /sdcard" 6 "DCIM directory (photos and videos only)" 1 "Same as for regular git-annex. ~/annex/"]]
diff --git a/doc/design/assistant/polls/prioritizing_special_remotes.mdwn b/doc/design/assistant/polls/prioritizing_special_remotes.mdwn
index f7462af0d..c6dbb376c 100644
--- a/doc/design/assistant/polls/prioritizing_special_remotes.mdwn
+++ b/doc/design/assistant/polls/prioritizing_special_remotes.mdwn
@@ -6,7 +6,7 @@ locally paired systems, and remote servers with rsync.
Help me prioritize my work: What special remote would you most like
to use with the git-annex assistant?
-[[!poll open=yes 16 "Amazon S3 (done)" 12 "Amazon Glacier (done)" 9 "Box.com (done)" 71 "My phone (or MP3 player)" 25 "Tahoe-LAFS" 10 "OpenStack SWIFT" 31 "Google Drive"]]
+[[!poll open=yes 16 "Amazon S3 (done)" 12 "Amazon Glacier (done)" 9 "Box.com (done)" 71 "My phone (or MP3 player)" 25 "Tahoe-LAFS" 10 "OpenStack SWIFT" 33 "Google Drive"]]
This poll is ordered with the options I consider easiest to build
listed first. Mostly because git-annex already supports them and they
diff --git a/doc/design/assistant/telehash.mdwn b/doc/design/assistant/telehash.mdwn
index b9755736f..ea507d9aa 100644
--- a/doc/design/assistant/telehash.mdwn
+++ b/doc/design/assistant/telehash.mdwn
@@ -11,6 +11,9 @@ git-annex (assistant) repositories.
* Rapid development, situation may change in a month or 2.
* Is it secure? A security review should be done by competant people
(not Joey). See <https://github.com/telehash/telehash.org/issues/23>
+* **Haskell version**
+ <https://github.com/alanz/htelehash/tree/v2/src/TeleHash>
+ Development on v2 in haskell is just starting up!
## implementation basics
diff --git a/doc/design/caching_database.mdwn b/doc/design/caching_database.mdwn
new file mode 100644
index 000000000..9d688a9d4
--- /dev/null
+++ b/doc/design/caching_database.mdwn
@@ -0,0 +1,124 @@
+* [[metadata]] for views
+* [direct mode mappings scale badly with thousands of identical files](/bugs/__34__Adding_4923_files__34___is_really_slow)
+* [[bugs/incremental_fsck_should_not_use_sticky_bit]]
+* [[todo/wishlist:_pack_metadata_in_direct_mode]]
+* [[todo/cache_key_info]]
+
+What do all these have in common? They could all be improved by
+using some kind of database to locally store the information in an
+efficient way.
+
+The database should only function as a cache. It should be able to be
+generated and updated by looking at the git repository.
+
+* Metadata can be updated by looking at the git-annex branch,
+ either its current state, or the diff between the old and new versions
+* Direct mode mappings can be updated by looking at the current branch,
+ to see which files map to which key. Or the diff between the old
+ and new versions of the branch.
+* Incremental fsck information is not stored in git, but can be
+ "regenerated" by running fsck again.
+ (Perhaps doesn't quite fit, but let it slide..)
+
+Store in the database the Ref of the branch that was used to construct it.
+(Update in same transaction as cached data.)
+
+## implementation plan
+
+1. Implement for metadata, on a branch, with sqlite.
+2. Make sure that builds on all platforms.
+3. Add associated file mappings support. This is needed to fully
+ use the caching database to construct views.
+4. Store incremental fsck info in db.
+5. Replace .map files with 3. for direct mode.
+
+## case study: persistent with sqllite
+
+Here's a non-normalized database schema in persistent's syntax.
+
+<pre>
+CachedKey
+ key Key
+ associatedFiles [FilePath]
+ lastFscked Int Maybe
+ KeyIndex key
+
+CachedMetaData
+ key Key
+ metaDataField MetaDataField
+ metaDataValue MetaDataValue
+</pre>
+
+Using the above database schema and persistent with sqlite, I made
+a database containing 30k Cache records. This took 5 seconds to create
+and was 7 mb on disk. (Would be rather smaller, if a more packed Key
+show/read instance were used.)
+
+Running 1000 separate queries to get 1000 CachedKeys took 0.688s with warm
+cache. This was more than halved when all 1000 queries were done inside the
+same `runSqlite` call. (Which could be done using a separate thread and some
+MVars.)
+
+(Note that if the database is a cache, there is no need to perform migrations
+when querying it. My benchmarks skip `runMigration`. Instead, if the query
+fails, the database doesn't exist, or uses an incompatable schema, and the
+cache can be rebuilt then. This avoids the problem that persistent's migrations
+can sometimes fail.)
+
+Doubling the db to 60k scaled linearly in disk and cpu and did not affect
+query time.
+
+----
+
+Here's a normalized schema:
+
+<pre>
+CachedKey
+ key Key
+ KeyIndex key
+ deriving Show
+
+AssociatedFiles
+ keyId CachedKeyId Eq
+ associatedFile FilePath
+ KeyIdIndex keyId associatedFile
+ deriving Show
+
+CachedMetaField
+ field MetaField
+ FieldIndex field
+
+CachedMetaData
+ keyId CachedKeyId Eq
+ fieldId CachedMetaFieldId Eq
+ metaValue String
+
+LastFscked
+ keyId CachedKeyId Eq
+ localFscked Int Maybe
+</pre>
+
+With this, running 1000 joins to get the associated files of 1000
+Keys took 5.6s with warm cache. (When done in the same `runSqlite` call.) Ouch!
+
+Update: This performance was fixed by adding `KeyIdOutdex keyId associatedFile`,
+which adds a uniqueness constraint on the tuple of key and associatedFile.
+With this, 1000 queries takes 0.406s. Note that persistent is probably not
+actually doing a join at the SQL level, so this could be sped up using
+eg, esquelito.
+
+Update2: Using esquelito to do a join got this down to 0.250s.
+
+Code: <http://lpaste.net/101141> <http://lpaste.net/101142>
+
+Compare the above with 1000 calls to `associatedFiles`, which is approximately
+as fast as just opening and reading 1000 files, so will take well under
+0.05s with a **cold** cache.
+
+So, we're looking at nearly an order of magnitude slowdown using sqlite and
+persistent for associated files. OTOH, the normalized schema should
+perform better when adding an associated file to a key that already has many.
+
+For metadata, the story is much nicer. Querying for 30000 keys that all
+have a particular tag in their metadata takes 0.65s. So fast enough to be
+used in views.
diff --git a/doc/design/metadata/comment_4_c32ade1524487e5fdc6f83b2db39f04c._comment b/doc/design/metadata/comment_4_c32ade1524487e5fdc6f83b2db39f04c._comment
new file mode 100644
index 000000000..01f917ef5
--- /dev/null
+++ b/doc/design/metadata/comment_4_c32ade1524487e5fdc6f83b2db39f04c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="bremner"
+ ip="198.164.160.48"
+ subject="convenient way to query metadata?"
+ date="2014-03-15T20:58:28Z"
+ content="""
+I'd like to be able to do something like \"git annex metadata -q fieldname\" and have that output the value(s) of fieldname. I see I could parse the json output but that isn't too convenient in a shell script. Or have I missed something that already exists?
+"""]]
diff --git a/doc/design/metadata/comment_5_0ac3132cd7a84f0e170fbe3a6f235fe7._comment b/doc/design/metadata/comment_5_0ac3132cd7a84f0e170fbe3a6f235fe7._comment
new file mode 100644
index 000000000..ca98f7f41
--- /dev/null
+++ b/doc/design/metadata/comment_5_0ac3132cd7a84f0e170fbe3a6f235fe7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 5"
+ date="2014-03-15T21:30:52Z"
+ content="""
+@bremner, you must be up to something interesting.. Added metadata --get for you.
+"""]]
diff --git a/doc/design/roadmap.mdwn b/doc/design/roadmap.mdwn
index 7458468f0..3fa261e6f 100644
--- a/doc/design/roadmap.mdwn
+++ b/doc/design/roadmap.mdwn
@@ -10,8 +10,8 @@ Now in the
* Month 4 [[!traillink assistant/windows text="Windows webapp"]], Linux arm, [[!traillink todo/support_for_writing_external_special_remotes]]
* Month 5 user-driven features and polishing
* Month 6 get Windows out of beta, [[!traillink design/metadata text="metadata and views"]]
-* **Month 7 user-driven features and polishing**
-* Month 8 [[!traillink assistant/telehash]]
+* Month 7 user-driven features and polishing
+* **Month 8 [[!traillink assistant/telehash]]**
* Month 9 [[!traillink assistant/gpgkeys]] [[!traillink assistant/sshpassword]]
* Month 10 get [[assistant/Android]] out of beta
* Month 11 [[!traillink assistant/chunks]] [[!traillink assistant/deltas]]
diff --git a/doc/devblog/day_-4__forgetting/comment_8_3f7045a00905b4287d950b08d5a77a82._comment b/doc/devblog/day_-4__forgetting/comment_8_3f7045a00905b4287d950b08d5a77a82._comment
new file mode 100644
index 000000000..f0ba50990
--- /dev/null
+++ b/doc/devblog/day_-4__forgetting/comment_8_3f7045a00905b4287d950b08d5a77a82._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="stp"
+ ip="188.193.207.34"
+ subject="Any update on cleaning up commands?"
+ date="2014-03-21T16:32:43Z"
+ content="""
+Is there any update on cleaning up object/file references to objects/content not at all present and lost. I would love my git annex fsck --all to show current failures and not these old files all the time.
+Thanks
+"""]]
diff --git a/doc/devblog/day_132__database_musings.mdwn b/doc/devblog/day_132__database_musings.mdwn
new file mode 100644
index 000000000..76ce14c32
--- /dev/null
+++ b/doc/devblog/day_132__database_musings.mdwn
@@ -0,0 +1,17 @@
+Updated the Debian stable backport to the last release. Also it seems that
+the last release unexpectedly fixed XMPP SIGILL on some OSX machines.
+Apparently when I rebuilt all the libraries recently, it somehow fixed that
+[[old_unsolved_bug|bugs/Share_with_friends_crash_in_osx]].
+
+[RichiH](http://richardhartmann.de/) suggested "wrt ballooning memory on
+repair: can you read in broken
+stuff and simply stop reading once you reach a certain threshold, then
+start repairing, re-run fsck, etc?" .. I had considered that but was
+not sure it would work. I think I've gotten it to work.
+
+Now working on a design for using a [[design/caching_database]]
+for some parts of git-annex. My initial benchmarks using SQLite
+indicate it would slow down associated file lookups by nearly an order of
+magnitude compared with the current ".map files" implementation.
+(But would scale better in edge cases). OTOH, using a SQLite
+database to index metadata for use in views looks very promising.
diff --git a/doc/devblog/day_133__db_and_bugfixes.mdwn b/doc/devblog/day_133__db_and_bugfixes.mdwn
new file mode 100644
index 000000000..b844708dc
--- /dev/null
+++ b/doc/devblog/day_133__db_and_bugfixes.mdwn
@@ -0,0 +1,20 @@
+Did some more exploration and perf tuning and thinking on caching
+databases, and am pretty sure I know how I want to implement it. Will be
+several stages, starting with using it for generating views, and ending(?)
+with using it for direct mode file mappings.
+
+Not sure I'm ready to dive into that yet, so instead spent the rest of the
+day working on small bugfixes and improvemnts. Only two significant ones..
+
+Made the webapp use a constant time string comparison (from `securemem`)
+to check if its auth token is valid. This could help avoid a potential
+timing attack to guess the auth token, although that is theoretical.
+Just best practice to do this.
+
+Seems that openssh 6.5p1 had another hidden surprise (in addition to
+its now-fixed bug in handing hostnames in `.ssh/config`) -- it broke
+the method git-annex was using for stopping a cached ssh connection,
+which led to some timeouts for failing DNS lookups. If git-annex seems
+to stall for a few seconds at startup/shutdown, that may be why
+(--debug will say for sure). I seem to have found a workaround that
+avoids this problem.
diff --git a/doc/devblog/day_134-135__avoiding_the_turing_tarpit.mdwn b/doc/devblog/day_134-135__avoiding_the_turing_tarpit.mdwn
new file mode 100644
index 000000000..d18470ae0
--- /dev/null
+++ b/doc/devblog/day_134-135__avoiding_the_turing_tarpit.mdwn
@@ -0,0 +1,18 @@
+Added some power and convenience to [[preferred_content]] expressions.
+
+Before, "standard" was a special case. Now it's a first-class keyword,
+so you can do things like "standard or present" to use the standard
+preferred content expression, modified to also want any file that happens
+to be present.
+
+Also added a way to write your own reusable preferred content expressions,
+tied to groups. To make a repository use them, set its preferred
+content to "groupwanted". Of course, "groupwanted" is also a first-class
+keyword, so "not groupwanted" or something can also be done.
+
+While I was at it, I made `vicfg` show the built-in standard preferred
+content expressions, for reference. This little IDE should be pretty
+self-explanatory, I hope.
+
+So, preferred content is almost its own little programming language now.
+Except I was careful to not allow recursion. ;)
diff --git a/doc/devblog/day_136__frustrating_day.mdwn b/doc/devblog/day_136__frustrating_day.mdwn
new file mode 100644
index 000000000..9088093d4
--- /dev/null
+++ b/doc/devblog/day_136__frustrating_day.mdwn
@@ -0,0 +1,10 @@
+The website broke and I spent several hours fixing it, changing the
+configuration to not let it break like this again, cleaning up after it,
+etc.
+
+Did manage to make a few minor bugfixes and improvements, but nothing
+stunning.
+
+----
+
+I'll be attending LibrePlanet at MIT this weekend.
diff --git a/doc/devblog/day_137-138__bug_triage_and_too_much_windows.mdwn b/doc/devblog/day_137-138__bug_triage_and_too_much_windows.mdwn
new file mode 100644
index 000000000..28b197356
--- /dev/null
+++ b/doc/devblog/day_137-138__bug_triage_and_too_much_windows.mdwn
@@ -0,0 +1,15 @@
+Yesterday, worked on cleaning up the todo list. Fixed Windows slash problem
+with rsync remotes. Today, more Windows work; it turns out to have been
+quite buggy in its handling of non-ASCII characters in filenames. Encoding
+stuff is never easy for me, but I eventually managed to find a way to fix
+that, although I think there are other filename encoding problems lurking
+in git-annex on Windows still to be dealt with.
+
+Implemented an interesting metadata feature yesterday. It turns out that
+metadata can have metadata. Particularly, it can be useful to know when a
+field was last set. That was already beeing tracked, internally (to make
+union merging work), so I was able to quite cheaply expose it as
+"$field-lastchanged" metadata that can be used like any other metadata.
+
+I've been thinking about how to implement [[todo/required_content]]
+expressions, and think I have a reasonably good handle on it.
diff --git a/doc/devblog/day_139-140__traveling.mdwn b/doc/devblog/day_139-140__traveling.mdwn
new file mode 100644
index 000000000..3025e45b5
--- /dev/null
+++ b/doc/devblog/day_139-140__traveling.mdwn
@@ -0,0 +1,17 @@
+Yesterday coded up one nice improvement on the plane -- `git annex unannex`
+(and `uninit`) is now tons faster. Before it did a git commit after every
+file processed, now there's just 1 commit at the end. This required using
+some locking to prevent the `pre-commit` hook from running in a confusing
+state.
+
+Today. LibrePlanet and a surprising amount of development. I've
+added [[tips/file_manager_integration]], only for Nautilus so far.
+The main part of this was adding --notify-start and --notify-finish, which
+use dbus desktop notifications to provide feedback.
+
+(Made possible thanks to Max Rabkin for updating
+[fdo-notify](http://hackage.haskell.org/package/fdo-notify) to use the
+new dbus library, and ion for developing the initial Nautilus integration
+scripts.)
+
+Today's work and LibrePlanet visit was sponsored by Jürgen Lüters.
diff --git a/doc/devblog/day_141__f-droid_sprint.mdwn b/doc/devblog/day_141__f-droid_sprint.mdwn
new file mode 100644
index 000000000..2a9e30b55
--- /dev/null
+++ b/doc/devblog/day_141__f-droid_sprint.mdwn
@@ -0,0 +1,3 @@
+Attended at the f-droid sprint at LibrePlanet, and have been getting a
+handle on how their build server works with an eye toward adding git-annex
+to it. Not entirely successful getting vagrant to build an image yet.
diff --git a/doc/devblog/day_141__f-droid_sprint/comment_1_1cc76207020ac478747117c76d7b5f9c._comment b/doc/devblog/day_141__f-droid_sprint/comment_1_1cc76207020ac478747117c76d7b5f9c._comment
new file mode 100644
index 000000000..9971f33da
--- /dev/null
+++ b/doc/devblog/day_141__f-droid_sprint/comment_1_1cc76207020ac478747117c76d7b5f9c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmJuOOkYYguRbWhXzxihIPBavxITJIMyww"
+ nickname="Matt"
+ subject="Excellent News"
+ date="2014-03-26T14:14:35Z"
+ content="""
+It will be great to see git-annex on f-droid!
+"""]]
diff --git a/doc/devblog/day_142__digging_out.mdwn b/doc/devblog/day_142__digging_out.mdwn
new file mode 100644
index 000000000..fc2ceea36
--- /dev/null
+++ b/doc/devblog/day_142__digging_out.mdwn
@@ -0,0 +1,13 @@
+Catching up on conference backlog. 36 messages backlog remains.
+
+Fixed `git-annex-shell configlist` to automatically initialize a
+git remote when a git-annex branch had been pushed to it. This is necessary
+for gitolite to be easy to use, and I'm sure it used to work.
+
+Updated the Debian backport and made a Debian package of the
+fdo-notify haskell library used for notifications.
+
+Applied a patch from Alberto Berti to fix support for tahoe-lafs
+1.10.
+
+And various other bug fixes and small improvements.
diff --git a/doc/devblog/day_143__foolish_hiatus.mdwn b/doc/devblog/day_143__foolish_hiatus.mdwn
new file mode 100644
index 000000000..f6763dff3
--- /dev/null
+++ b/doc/devblog/day_143__foolish_hiatus.mdwn
@@ -0,0 +1,20 @@
+Last week's trip was productive, but I came home more tired than I
+realized. Found myself being snappy & stressed, so I have been on break.
+
+I did do a little git-annex dev in the past 5 days. On Saturday I
+implemented [[todo/preferred_content]] (although without the active checks
+I think it probably ought to have.) Yesterday I had a long conversation
+with the Tahoe developers about improving git-annex's tahoe integration.
+
+Today, I have been wrapping up [building propellor](http://joeyh.name/code/propellor/).
+To test its docker support, I used propellor to build and deploy a
+container that is a git-annex autobuilder. I'll be replacing the old
+autobuilder setup with this shortly, and expect to also publish docker
+images for git-annex autobuilders, so anyone who wants to can run their
+own autobuilder really easily.
+
+---
+
+I have April penciled in on the roadmap as the month to do telehash.
+I don't know if telehash-c is ready for me yet, but it has had a lot of
+activity lately, so this schedule may still work out!
diff --git a/doc/devblog/day_144__catching_up.mdwn b/doc/devblog/day_144__catching_up.mdwn
new file mode 100644
index 000000000..52e25f0d5
--- /dev/null
+++ b/doc/devblog/day_144__catching_up.mdwn
@@ -0,0 +1,12 @@
+Got caught up on all recent bugs and questions, although I still have a
+backlog of 27 older things that I really should find time for.
+
+Fixed a couple of bugs. One was that the assistant set up ssh
+`authorized_keys` that didn't work with the fish shell.
+
+Also got caught up on the current state of telehash-c. Have not quite
+gotten it to work, but it seems pretty close to being able to see it do
+something useful for the first time.
+
+Pushing out a release this evening with a good number of changes left over
+from March.
diff --git a/doc/devblog/day_144__catching_up/comment_1_311a7245dd12f1a7e432168d16041348._comment b/doc/devblog/day_144__catching_up/comment_1_311a7245dd12f1a7e432168d16041348._comment
new file mode 100644
index 000000000..f13ed82ae
--- /dev/null
+++ b/doc/devblog/day_144__catching_up/comment_1_311a7245dd12f1a7e432168d16041348._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="70.82.37.38"
+ subject="comment 1"
+ date="2014-04-02T21:28:15Z"
+ content="""
+awesome! can't wait to see telehash land! :)
+"""]]
diff --git a/doc/devblog/day_82__rpi_and_synology/comment_1_d154ddcf22027fd06acf9da73e12c006._comment b/doc/devblog/day_82__rpi_and_synology/comment_1_d154ddcf22027fd06acf9da73e12c006._comment
index 9b73a8e79..33bc12e63 100644
--- a/doc/devblog/day_82__rpi_and_synology/comment_1_d154ddcf22027fd06acf9da73e12c006._comment
+++ b/doc/devblog/day_82__rpi_and_synology/comment_1_d154ddcf22027fd06acf9da73e12c006._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="Attila"
ip="213.163.19.162"
subject="git-annex.org"
diff --git a/doc/favicon.ico b/doc/favicon.ico
index 5bb405931..e754f5a48 100644
--- a/doc/favicon.ico
+++ b/doc/favicon.ico
Binary files differ
diff --git a/doc/favicon.png b/doc/favicon.png
deleted file mode 100644
index 1efbebdd7..000000000
--- a/doc/favicon.png
+++ /dev/null
Binary files differ
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__.mdwn b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__.mdwn
new file mode 100644
index 000000000..84f92ae7e
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__.mdwn
@@ -0,0 +1,3 @@
+I have 2 clients (laptops) that would (usually) not be online at the same time. Is it possible to use git-annex for syncing these 2 clients through an encrypted server?
+
+I have tried to set this up with the assistant by using an USB-disk for copying the repository from one client to the other. The server is configured through the assistant as repository group 'transfer'. Now both clients see the encrypted ssh-server, each client copy stuff to the encrypted server, but no files are copied between the 2 clients. (In my case, running git-annex on the server is not an option. I have read through this forum, but it doesn't seem anyone has been able to get it to work.)
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_1_924521ad5972046bac44d2e04ec296c7._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_1_924521ad5972046bac44d2e04ec296c7._comment
new file mode 100644
index 000000000..90b47a3a9
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_1_924521ad5972046bac44d2e04ec296c7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnvVfFLW4CTKs7UjdiLIsOn_cxj1Jnh64I"
+ nickname="Charl"
+ subject="Change the encrypted server repository group to &quot;full backup&quot;"
+ date="2014-03-23T21:00:01Z"
+ content="""
+Have you tried changing the repository group of the encrypted server to \"full backup\" instead of \"transfer\"?
+
+I've just started experimenting with git-annex, and this setup (two possibly remote laptops, one encrypted server) seems to be working after very limited testing. I'm currently importing a larger collection of about 40000 files, will see if it still does (it seems whilst one client is transferring to the remote server, the other client laptop is not beeing synced; it did sync after my first batch of copying however.)
+"""]]
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_2_e2a7f34a3ccc1b6467e6da611c067d66._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_2_e2a7f34a3ccc1b6467e6da611c067d66._comment
new file mode 100644
index 000000000..b50ba4b46
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_2_e2a7f34a3ccc1b6467e6da611c067d66._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkvN0eFnwvgw2JyTSSHw0QouytcxtPLln8"
+ nickname="Stein Roald"
+ subject="No success"
+ date="2014-03-26T19:43:24Z"
+ content="""
+Thank you, Charl, for your suggestion. I've tried it, without success. (It doesn't seem like that change changed anything on the encrypted ssh-server.)
+"""]]
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_3_f9a369a6ac69f091e6128990274d3228._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_3_f9a369a6ac69f091e6128990274d3228._comment
new file mode 100644
index 000000000..1e4206144
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_3_f9a369a6ac69f091e6128990274d3228._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 3"
+ date="2014-03-26T21:10:39Z"
+ content="""
+What kind of encrypted remote are you using? An encrypted rsync special remote does not include the git repository, but only the content of the files, so cannot be used in this way.
+
+If you set up a [[gcrypt special remote|special_remotes/gcrypt]], it will be encrypted and includes the full git repository, as well as the content of the files, so can be used like this.
+"""]]
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_4_91b422f8d55b68077245c606c4f7f87c._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_4_91b422f8d55b68077245c606c4f7f87c._comment
new file mode 100644
index 000000000..4d8915b8d
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_4_91b422f8d55b68077245c606c4f7f87c._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkvN0eFnwvgw2JyTSSHw0QouytcxtPLln8"
+ nickname="Stein Roald"
+ subject="Need some clarification"
+ date="2014-03-28T22:49:14Z"
+ content="""
+OK, thank you Joey for your help, and I think you have made some really excellent software. I've spent a couple of days to configure gpg and understand how to use it (glad I did, it has been on my todo-list for a long time...)
+
+First to your question: When I started, I just used the git-annex assistant to \"set up a repository on a remote server using ssh\" as a \"transfer repository\". Now I'll use git-remote-gcrypt instead.
+
+Now I have 2 questions:
+
+---
+
+1) On this webpage: [[https://github.com/joeyh/git-remote-gcrypt]] these are the instructions for setting up a remote for two participants:
+
+ git remote add cryptremote gcrypt::rsync://example.com:repo
+ git config remote.cryptremote.gcrypt-participants \"KEY1 KEY2\"
+ git push cryptremote master
+
+**Question 1:** As I own both computers myself, will syncing between the 2 computers work if I only use 1 KEY (the same KEY on both computers)?
+
+---
+
+2) I am still struggling to understand git-annex assistant and the use of special remotes. Important reasons for using git-annex are backups and moving data to the cloud to free up disk space locally. If I've understood it correctly, git-annex assistant always encrypts data sent to special remotes. And it seems to me that this page [[http://git-annex.branchable.com/special_remotes/]] suggest that git-annex assistant makes it easy to transfer files between different computers that do not communicate directly. I must clearly have misunderstood something, as Joey's comment above seem to state that I can't use the assistant for setting up syncing between computers.
+
+**Question 2:** If I loose my computer, or it becomes corrupted, how can I get my files back if I don't set up special remotes as a gcrypt special remote? (And if I can't, what is the purpose of the special remotes made by the assistant?)
+"""]]
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_5_f6128fe75ff3453747f69f12e0fd0a5b._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_5_f6128fe75ff3453747f69f12e0fd0a5b._comment
new file mode 100644
index 000000000..8dcddbeef
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_5_f6128fe75ff3453747f69f12e0fd0a5b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Confused"
+ date="2014-03-31T03:18:41Z"
+ content="""
+>What kind of encrypted remote are you using? An encrypted rsync special remote does not include the git repository, but only the content of the files, so cannot be used in this way.
+
+Forgive me, Joey, I've been following your work on the assistant for almost as long as you've been working on it, and I use git a little bit, but I have yet to wrap my head around the complexities of git and how git-annex and the assistant...morph them. I've read all the design docs you've written, but I still don't understand this. From reading the OP it sounds like this is exactly what the encrypted rsync special remote is for: using a transfer repo to sync two devices that don't connect directly to each other. Why would he need to use a gcrypt repo instead?
+
+Thanks for your patience. I know you get asked these basic questions over and over again.
+"""]]
diff --git a/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_6_9b90b4031a5ed26c375903b33ed65a10._comment b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_6_9b90b4031a5ed26c375903b33ed65a10._comment
new file mode 100644
index 000000000..5fc4286b2
--- /dev/null
+++ b/doc/forum/2_clients_using_an_encrypted_server_for_syncing_-_possible__63__/comment_6_9b90b4031a5ed26c375903b33ed65a10._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 6"
+ date="2014-04-02T20:11:35Z"
+ content="""
+@Adam, an encrypted special remote does not contain the git repository (the gcrypt special remote is an exception to this rule). So you need to use another method to sync the git repository between machines.
+
+@Stein Roald once you have a clone of the git repository, you have the information that git-annex needs in able to get files from encrypted special remotes.
+
+Question 1: While gcrypt supports multi-key setups, when you use the git-annex assistant to set up a gcrypt remote it only sets it up to use one key. It's left to you to arrange for this key to be on every computer that needs it. Or use command-line stuff to add additional keys later.
+
+Question 2: You can certianly use the assistant to set up syncing between computers, but the only setup that currently provides 100% end-to-end enctyption of the git repository is using gcrypt. (Special remotes are 100% end-to-end encrypted, but as I've stated several times, do not contain the git repository data.)
+Since you seemed to want 100% end to end encryption I suggested using gcrypt. There are simpler setups, like using XMPP, that encrypt everything but not end-to-end, so the XMPP server could snoop on it.
+
+If you loose your computer, you can get your files back from any other device where you've set up a clone of that repository. A backup drive, another computer , etc.
+"""]]
diff --git a/doc/forum/Add_a___34__local__34___remote.txt b/doc/forum/Add_a___34__local__34___remote.mdwn
index c35a637a8..c35a637a8 100644
--- a/doc/forum/Add_a___34__local__34___remote.txt
+++ b/doc/forum/Add_a___34__local__34___remote.mdwn
diff --git a/doc/forum/Auto_sync_with_music_player/comment_3_99f65a0efaf5d5f9b8ff530acc122860._comment b/doc/forum/Auto_sync_with_music_player/comment_3_99f65a0efaf5d5f9b8ff530acc122860._comment
new file mode 100644
index 000000000..b0275abdc
--- /dev/null
+++ b/doc/forum/Auto_sync_with_music_player/comment_3_99f65a0efaf5d5f9b8ff530acc122860._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-18T19:59:07Z"
+ content="""
+Turns out there is an open todo about this with details: [[todo/Use_MediaScannerConnection_on_Android]]
+"""]]
diff --git a/doc/forum/Folders_for___34__actions__34___-_now_that_views_have_disrupted_the_file_structure__63__.mdwn b/doc/forum/Folders_for___34__actions__34___-_now_that_views_have_disrupted_the_file_structure__63__.mdwn
new file mode 100644
index 000000000..61a8c7905
--- /dev/null
+++ b/doc/forum/Folders_for___34__actions__34___-_now_that_views_have_disrupted_the_file_structure__63__.mdwn
@@ -0,0 +1,20 @@
+The _views_ functionality has made the file structure dynamic.
+
+With this in mind would it be possible/suitable to make drag and drop targets for `git-annex get` and `git-annex drop` commands?
+This would make available git annex most interesting feature to assistant users.
+
+I'm not entirely sure it's a good idea but it avoids file manager scripts and should be discoverable and easy to use.
+
+I see two possibilities:
+
+1. A folder in the annex root that contains a mirror of the tree but with only the unavailable files. Unavaliable files would then not be displayed in the live tree. Perhaps the folder can be called `remote`? Files can then be dragged from this tree to the live tree to trigger transfer of files. Any error/info gets displayed in the assistant
+2. Flat droptargets in the annex root for `drop` and `get` commands.
+
+
+Number one above makes discovering available files a bit cumbersome as you have to navigate down a parallell tree. It does make the available/remote distinction clearer which may be good for assistant users.
+
+The mechanism could be extended to include a folder or droptarget for each remote.
+
+The creation of droptargets/action folders could be triggered by a big visible button in the assistant interface **Manage Files**
+
+Is it messy?
diff --git a/doc/forum/GPG_passphrase_handling.txt b/doc/forum/GPG_passphrase_handling.mdwn
index b0f82cb89..b0f82cb89 100644
--- a/doc/forum/GPG_passphrase_handling.txt
+++ b/doc/forum/GPG_passphrase_handling.mdwn
diff --git a/doc/forum/Generating_a_Temp_View_of_Available_Files.mdwn b/doc/forum/Generating_a_Temp_View_of_Available_Files.mdwn
new file mode 100644
index 000000000..bdb8ece69
--- /dev/null
+++ b/doc/forum/Generating_a_Temp_View_of_Available_Files.mdwn
@@ -0,0 +1 @@
+Is it possible to generate a view of files currently available on the annex? My use case is that I have pretty large repo (couple of TBs) and I have partial checkouts on multiple machines instead of seeing 100s of broken symlinks I would like to just filter filter files that are present on the machine?
diff --git a/doc/forum/Git_annex_on_Windows/comment_6_79fb5ec1b47593ab3355543c5499284a._comment b/doc/forum/Git_annex_on_Windows/comment_6_79fb5ec1b47593ab3355543c5499284a._comment
new file mode 100644
index 000000000..c3f2ca2a8
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_6_79fb5ec1b47593ab3355543c5499284a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://alerque.com/"
+ nickname="Caleb"
+ subject="path issue"
+ date="2014-03-20T13:05:34Z"
+ content="""
+It seems the use of the cmd folder in the Windows git-annex installer no longer meshes with the git install from msysgit. Changing \"cmd\" to \"bin\" during the install process made it work for me.
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_7_75d4450b4608ad0b453bc69159e708de._comment b/doc/forum/Git_annex_on_Windows/comment_7_75d4450b4608ad0b453bc69159e708de._comment
new file mode 100644
index 000000000..2d0b3ea3c
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_7_75d4450b4608ad0b453bc69159e708de._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 7"
+ date="2014-03-20T16:04:36Z"
+ content="""
+Hmm, putting git-annex.exe in to bin and not cmd with mysysgit 1.8.5.2 will make \"git annex\" work, but \"git-annex\" will not.
+
+What version of msysgit has the problem with bin?
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_8_e4e5ad0cda34bb597fe1bb804acc15e9._comment b/doc/forum/Git_annex_on_Windows/comment_8_e4e5ad0cda34bb597fe1bb804acc15e9._comment
new file mode 100644
index 000000000..3a649c501
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_8_e4e5ad0cda34bb597fe1bb804acc15e9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 8"
+ date="2014-03-20T19:50:26Z"
+ content="""
+I upgraded to msysgit 1.9.0 and git annex works in cmd.
+
+Did you tell the msysgit installer to \"Run git from the windows command prompt\"? This is the default. If you chose \"Use git bash only\" then git-annex will only work from within git bash.
+"""]]
diff --git a/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_2_85415e1fceb737919cc1cd9f37242458._comment b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_2_85415e1fceb737919cc1cd9f37242458._comment
new file mode 100644
index 000000000..a251dade3
--- /dev/null
+++ b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_2_85415e1fceb737919cc1cd9f37242458._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 2"
+ date="2014-03-12T19:35:26Z"
+ content="""
+Probably this will fix it:
+
+`git annex dead 70582c7b-0b57-4087-a9d1-77b5f5f3c75e`
+"""]]
diff --git a/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_3_fb3a591dc60182f7922fc2b5c24f50f1._comment b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_3_fb3a591dc60182f7922fc2b5c24f50f1._comment
new file mode 100644
index 000000000..bebd8f290
--- /dev/null
+++ b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_3_fb3a591dc60182f7922fc2b5c24f50f1._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="comment 3"
+ date="2014-03-13T20:05:53Z"
+ content="""
+Unfortunately git annex tells me there is no such remote:
+
+ cody:games schmitta$ git annex dead 70582c7b-0b57-4087-a9d1-77b5f5f3c75e
+ dead 70582c7b-0b57-4087-a9d1-77b5f5f3c75e git-annex: there is no available git remote named \"70582c7b-0b57-4087-a9d1-77b5f5f3c75e\"
+"""]]
diff --git a/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_4_aed0be32e579c7a39c63aa7e3ec5f67b._comment b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_4_aed0be32e579c7a39c63aa7e3ec5f67b._comment
new file mode 100644
index 000000000..99ac0d5a6
--- /dev/null
+++ b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_4_aed0be32e579c7a39c63aa7e3ec5f67b._comment
@@ -0,0 +1,29 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 4"
+ date="2014-03-14T17:46:23Z"
+ content="""
+It seems that the git-annex branch's uuid.log must somehow not list this uuid, but it's used in the location tracking log files.
+
+The only way I can think of that this could happen is if you had set up a repository, run git-annex init, and then went in and changed the annex.uuid setting to this other uuid, and added files with that misconfiguration. Does that sound like what happened?
+
+The fix is just as evil as the cause -- you can edit .git/config to add a new, dummy git remote that has annex-uuid set to the problem uuid, and then `git-annex dead` can be used to kill the uuid via that remote. For example:
+
+[[!format sh \"\"\"
+joey@darkstar:~/tmp/x>git annex whereis eep
+whereis eep (1 copy)
+ 00000a6d-e770-4ab9-a640-7d6272e9ffff
+ok
+joey@darkstar:~/tmp/x>git annex dead 00000a6d-e770-4ab9-a640-7d6272e9ffff
+dead 00000a6d-e770-4ab9-a640-7d6272e9ffff git-annex: there is no available git remote named \"00000a6d-e770-4ab9-a640-7d6272e9ffff\"
+- exit 1
+joey@darkstar:~/tmp/x>git remote add dummy dummy
+joey@darkstar:~/tmp/x>git config remote.dummy.annex-uuid 00000a6d-e770-4ab9-a640-7d6272e9ffff
+joey@darkstar:~/tmp/x>git annex dead dummy
+dead dummy ok
+(Recording state in git...)
+joey@darkstar:~/tmp/x>git annex whereis eep
+whereis eep (0 copies) failed
+\"\"\"]]
+"""]]
diff --git a/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_5_0c9a6c8a92d6c6e04ae3a8349b799c60._comment b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_5_0c9a6c8a92d6c6e04ae3a8349b799c60._comment
new file mode 100644
index 000000000..9807fb7d9
--- /dev/null
+++ b/doc/forum/How_do_I_get_rid_of_a_wrong_remote_uuid__63__/comment_5_0c9a6c8a92d6c6e04ae3a8349b799c60._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="comment 5"
+ date="2014-03-14T18:11:52Z"
+ content="""
+Thanks, it worked!
+
+Regarding how I got into that state, here is what happened:
+- I configured a new repository (git init, git annex init) on machine B
+- I added that repository as a remote from machine A
+- I started pushing files from machine A to machine B, starting with the file that later showed this problem
+- I then noticed that, although the files were said to be successfully sent, I could not see them on machine B (no symbolic link was created), even after a \"git annex sync\" there
+- I decided to start over, deleting the annex, and creating it from a clone of an existing annex
+- This resulted in a duplicated UUID for the same path, which led to this problem
+
+Maybe some documentation on how to cleanly start over when things get in a bad state would be very useful.
+
+Thanks again,
+
+Alan
+"""]]
diff --git a/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository.mdwn b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository.mdwn
new file mode 100644
index 000000000..48ad2d1d8
--- /dev/null
+++ b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository.mdwn
@@ -0,0 +1,3 @@
+I have git-annex set up with three clients and a transfer repository and everything was working fine, but a couple of days ago I noticed that git-annex was starting to upload to the transfer repository files that where already present on the three clients, and it hasn't stopped since. It's uploading all my files and I don't really know why.
+
+Is there a way to know why does git-annex think it needs to upload this files?
diff --git a/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_1_17db96492e6bc0e243fc7cb62565c4c4._comment b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_1_17db96492e6bc0e243fc7cb62565c4c4._comment
new file mode 100644
index 000000000..6cf5541e8
--- /dev/null
+++ b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_1_17db96492e6bc0e243fc7cb62565c4c4._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T17:46:30Z"
+ content="""
+A few likely reasons:
+
+* If a 4th client repository had popped up.
+* If you have configured a high number of copies, it might only be able to be met by keeping files on the transfer repository.
+* Similarly, if a repository that used to have the files has been marked as dead or deleted, more copies might be needed to make up for that.
+* For completeness, if the transfer repository accidentially had its type changed to some other kind of repository, like a full backup.
+
+You can enable debugging (start with --debug or go into the webapp's preferences) and it might say a little more, but the debugging info is not very good.
+
+The best thing is probably to look at one single file, use `git annex whereis` on the file to see what repositories contain it, and then think about how that interacts with the [[preferred_content_expression_of_the_transfer_repository|preferred_content/standard_groups]].
+"""]]
diff --git a/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_2_e772ea0383ac690cbcbcf125258986cf._comment b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_2_e772ea0383ac690cbcbcf125258986cf._comment
new file mode 100644
index 000000000..27f158ea1
--- /dev/null
+++ b/doc/forum/How_to_know_why_is_git-annex_uploading_a_file_to_a_transfer_repository/comment_2_e772ea0383ac690cbcbcf125258986cf._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk9nck8WX8-ADF3Fdh5vFo4Qrw1I_bJcR8"
+ nickname="Jon Ander"
+ subject="comment 2"
+ date="2014-04-01T08:01:00Z"
+ content="""
+I thought I had already checked all does possibilities, the repositories where in the correct group and no new repositories had been added. *git annex info* didn't show anything weird and nor did *git annex whereis*. I finally found out *git annex vicfg* and I found two new repositories with no name in the repository groups. It looked something like this:
+
+ # (for )
+ group repository-hash = client
+ # (for )
+ group repository-hash = client
+
+
+No idea of how they got there, but setting both of them to unwanted solved the issue.
+"""]]
diff --git a/doc/forum/Import_options.txt b/doc/forum/Import_options.mdwn
index 543d1a4ec..543d1a4ec 100644
--- a/doc/forum/Import_options.txt
+++ b/doc/forum/Import_options.mdwn
diff --git a/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__.mdwn b/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__.mdwn
new file mode 100644
index 000000000..dfe8afe2c
--- /dev/null
+++ b/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__.mdwn
@@ -0,0 +1,4 @@
+Hi,
+
+Suppose I have an annexed file whose content is stored on an extenal hard drive.
+When the hard drive is mounted, is it possible to have immediately access to this file without transfering it, by modifying the symlink to point to the file content on the hard drive instead of having a broken link?
diff --git a/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__/comment_1_ce0464d5fca6ada9f1477831fd47ce09._comment b/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__/comment_1_ce0464d5fca6ada9f1477831fd47ce09._comment
new file mode 100644
index 000000000..ee6ec690e
--- /dev/null
+++ b/doc/forum/Link_to_local_remote_instead_of_broken_link_when_possible__63__/comment_1_ce0464d5fca6ada9f1477831fd47ce09._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T18:25:16Z"
+ content="""
+See [[todo/union_mounting]]
+"""]]
diff --git a/doc/forum/Purge_a_remote.txt b/doc/forum/Purge_a_remote.mdwn
index f1b04ead2..f1b04ead2 100644
--- a/doc/forum/Purge_a_remote.txt
+++ b/doc/forum/Purge_a_remote.mdwn
diff --git a/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment b/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment
index ddcab44dd..86827c529 100644
--- a/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment
+++ b/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
nickname="dxtrish"
subject="comment 2"
diff --git a/doc/forum/Sync_with_one_offline_peer.txt b/doc/forum/Sync_with_one_offline_peer.mdwn
index 6ee05c6e6..6ee05c6e6 100644
--- a/doc/forum/Sync_with_one_offline_peer.txt
+++ b/doc/forum/Sync_with_one_offline_peer.mdwn
diff --git a/doc/forum/Tracking_a_directory_with_some_hg_and_git_repositories/comment_4_c889050d3079edefc4633451bd5baff8._comment b/doc/forum/Tracking_a_directory_with_some_hg_and_git_repositories/comment_4_c889050d3079edefc4633451bd5baff8._comment
new file mode 100644
index 000000000..55f9f2534
--- /dev/null
+++ b/doc/forum/Tracking_a_directory_with_some_hg_and_git_repositories/comment_4_c889050d3079edefc4633451bd5baff8._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnvVfFLW4CTKs7UjdiLIsOn_cxj1Jnh64I"
+ nickname="Charl"
+ subject="use case: changing workstations mid-way through development session"
+ date="2014-03-23T21:22:15Z"
+ content="""
+An important use case for me with automatic synchronization, is being able to change computers mid-way through a development session. I used to do this with dropbox for years: I'd work in a git checkout, then take another laptop to go work elsewhere, and just continue in the \"same\" synchronized git repo. Having to remember to commit and push a long list of repos before changing workstations is error-prone. Also, I prefer to commit when a discrete atom of work has been completed, and to push when a topic branch is good and ready to be merged (for example), not every time that I feel like changing workstations. :) Dropbox never dropped a stitch in all this time. As long as all laptops are in a 1) connected and 2) synced up state, switching is possible.
+
+The limitation of not being able to sync the .git directories in git checkouts means that this use case can't currently be supported by git-annex (assistant). Is a work-around possible, or is this something that can't ever be supported due to the limitations of git itself?
+
+"""]]
diff --git a/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.txt b/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.mdwn
index 6b1c03d9a..6b1c03d9a 100644
--- a/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.txt
+++ b/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.mdwn
diff --git a/doc/forum/Using_git-annex_as_a_library/comment_3_ac52304a096ebc66967352efaffb060a._comment b/doc/forum/Using_git-annex_as_a_library/comment_3_ac52304a096ebc66967352efaffb060a._comment
new file mode 100644
index 000000000..cda6e0799
--- /dev/null
+++ b/doc/forum/Using_git-annex_as_a_library/comment_3_ac52304a096ebc66967352efaffb060a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Alexcei"
+ ip="92.255.239.77"
+ subject="comment 3"
+ date="2014-03-25T05:43:36Z"
+ content="""
+With version 5.20140127 first approach became impossible. Why did you decide to remove json supported by the majority of command?
+"""]]
diff --git a/doc/forum/Using_git-annex_as_a_library/comment_4_d502fea60bf3a82f8a50f72a90a80c25._comment b/doc/forum/Using_git-annex_as_a_library/comment_4_d502fea60bf3a82f8a50f72a90a80c25._comment
new file mode 100644
index 000000000..642fda2fe
--- /dev/null
+++ b/doc/forum/Using_git-annex_as_a_library/comment_4_d502fea60bf3a82f8a50f72a90a80c25._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 4"
+ date="2014-03-26T18:31:30Z"
+ content="""
+I didn't. I removed the --json options from commands that didn't necessarily output valid json when used with it. There are numerous commands that support --json (find, whereis, info, status, metadata, examinekey), and I'm open to adding it to other commands -- but it's probably not feasible to make commands like `get` output json, since their output includes progress info printed by rsync etc.
+"""]]
diff --git a/doc/forum/XBMC__44___NFS___38___git-annex_.txt b/doc/forum/XBMC__44___NFS___38___git-annex_.mdwn
index fc5cd702a..fc5cd702a 100644
--- a/doc/forum/XBMC__44___NFS___38___git-annex_.txt
+++ b/doc/forum/XBMC__44___NFS___38___git-annex_.mdwn
diff --git a/doc/forum/central_non-bare_and_git_push.txt b/doc/forum/central_non-bare_and_git_push.mdwn
index ecc81096e..ecc81096e 100644
--- a/doc/forum/central_non-bare_and_git_push.txt
+++ b/doc/forum/central_non-bare_and_git_push.mdwn
diff --git a/doc/forum/faking_location_information.mdwn b/doc/forum/faking_location_information.mdwn
new file mode 100644
index 000000000..7c84e12e3
--- /dev/null
+++ b/doc/forum/faking_location_information.mdwn
@@ -0,0 +1,19 @@
+Hi
+
+I am using git-annex even if people I exchange data with (currently) don‘t use it for there data. My idea behind this is that I would like to know from where I got a file, whom I gave a file and who does (probably) still have a copy of the file. To do this you need to trick git-annex location tracking feature a bit. I successfully managed to achieve this in a simple data exchange which only consisted of me coping over files to one of my git-annex repos. I did the following to make git-annex believe that the files are in two repos without the need to *copy* them around the repos.
+
+This is what I did in this simple case:
+
+1. mounted the drive from someone
+2. made a clone of my git-annex repo on the filesystem which should hold the copy of the data
+3. initialized the cloned repo with `git annex init "Drive from person X"`
+4. imported the files to the cloned repo with `git annex import --duplicate $path_to_files_from_person_x`
+5. `git annex sync` in the cloned repo
+6. `git annex sync` in main repo
+7. `git annex move . --to origin` in the cloned repo
+
+The impotent part (and the limit) here was that you can not sync these two repos after you moved files to the main repo. The problem is that there will be situations where I will have to sync them also after moving files around (for example if I want to store new files in multiple repos (and not just one main repo), or if I also want to copy files over to drives from someone).
+
+Note: I have also worked out a solution to allow someone to choose which files he/she would like to get as described [on superuser.com](http://superuser.com/a/717689).
+
+Are there better ways to fake location information then the thing I came up with (except making multiple repos for one person/drive)? Can multiple remotes be merged to one remote?
diff --git a/doc/forum/git_annex_get_--want-get_another__95__repo/comment_1_0be0b3981ddd0743ff26cf6d396e521d._comment b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_1_0be0b3981ddd0743ff26cf6d396e521d._comment
new file mode 100644
index 000000000..7a58e35d6
--- /dev/null
+++ b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_1_0be0b3981ddd0743ff26cf6d396e521d._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-12T17:15:23Z"
+ content="""
+Well, I suppose this is doable, but the way this scenario is generally handled is to make a transfer repository (which your desktop is serving as here) have a preferred content expression that makes it want files that the client repositories (phones) want, until the files have reached the clients:
+
+In your case you could have:
+
+ (not inallgroup=phones and ($phone_preferred_content)) or ($desktop_preferred_content)
+
+Where `$desktop_preferred_content` is whatever files the desktop actually wants on its own, and `$phone_preferred_content` is a copy of the preferred content setting for the phone.
+
+To make this work, you also need to put your phone in the phones group.
+"""]]
diff --git a/doc/forum/git_annex_get_--want-get_another__95__repo/comment_2_b1ead1085a87818625579bf1ef151b5d._comment b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_2_b1ead1085a87818625579bf1ef151b5d._comment
new file mode 100644
index 000000000..1f8ce270e
--- /dev/null
+++ b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_2_b1ead1085a87818625579bf1ef151b5d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 2"
+ date="2014-03-12T17:16:59Z"
+ content="""
+BTW expressing this in the preferred content as above also has the benefit that you can use the new `git annex sync --content` on the desktop and it will automatically get files, copy the right ones to the phone, and drop any then-unwanted files.
+"""]]
diff --git a/doc/forum/git_annex_get_--want-get_another__95__repo/comment_3_cf2018852c84b0bf1ac061def6f0ac5d._comment b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_3_cf2018852c84b0bf1ac061def6f0ac5d._comment
new file mode 100644
index 000000000..c6bd20e1f
--- /dev/null
+++ b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_3_cf2018852c84b0bf1ac061def6f0ac5d._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm3vKzS4eOWYpKMoYXqMIjNsIg_nYF-loU"
+ nickname="Konubinix"
+ subject="That does it but not totally"
+ date="2014-03-13T11:36:02Z"
+ content="""
+I agree with the fact that it answers my initial question.
+
+Nevertheless, I guess it is really annoying to have to change the preferred content in two locations each time I change want to modify what is on my phone.
+Indeed, I quite often change what should be really present on my phone, depending on several factors (my mood, the time I will have in transports and the phase of the moon).
+
+The reason why I use \"git annex wanted\" is that it is straightforward: I just launch : \"git annex wanted phone include=some/file\" and that's all.
+
+With the solution you propose, I would have to each time additionally launch \"git annex wanted here '(not inallgroup=phones and (include=some/file)) or ($desktop_preferred_content)'\"
+
+Where I probably have to previously launch \"git annex wanted here\" to remember what is the preferred content of my computer (and put it in $desktop_preferred_content).
+
+Another option would be to run \"git annex vicfg\" and edit both fields manually, but IMHO this appears also to be too complicated relatively to the use case.
+
+About your second comment, I really enjoy the idea if \"git annex sync --content\", but it is really long in big repositories. I guess it is because I cannot restrict the command to a directory like I do with get, drop, move and copy.
+
+Besides, the use case wants to get the files whenever they are and copy them only to the phone. With git annex sync --content, the files are also put in the other repositories.
+
+For the time being, I prefer falling back to explicit commands that are much faster when I know a directory to sync \"git annex get --auto directory && git annex copy --auto --to phone directory\".
+
+For example, I just tried \"git annex sync --content phone\" and I killed it after 5 minutes and nothing was copied yet. With the set of two commands above, the synchronization of directory (get --to phone directory + drop --from here directory) took about 3 minutes.
+"""]]
diff --git a/doc/forum/git_annex_get_--want-get_another__95__repo/comment_4_22562e8f1f2f91b9f9a5939ec9006cb5._comment b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_4_22562e8f1f2f91b9f9a5939ec9006cb5._comment
new file mode 100644
index 000000000..25624c2c0
--- /dev/null
+++ b/doc/forum/git_annex_get_--want-get_another__95__repo/comment_4_22562e8f1f2f91b9f9a5939ec9006cb5._comment
@@ -0,0 +1,38 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm3vKzS4eOWYpKMoYXqMIjNsIg_nYF-loU"
+ nickname="Konubinix"
+ subject="Precision of the use case"
+ date="2014-03-13T11:47:59Z"
+ content="""
+I realized that the directory restriction described earlier is not clear. Let me explain it.
+
+Say I have a big repository of files with the following structure.
+
+A/...
+B/...
+C/...
+D/D1/...
+D/D2/...
+D/D3/...
+
+Imagine that each of A, B, C and D contains a lot of files.
+
+Now imagine that I have often put in the preferred content of my phone files in one of D1, D2 or D3. (for instance, include=D/D1/*)
+
+I implicitly know that I can restrict the command to D, and I can rely on preferred content to know what file from D I have to put into my phone.
+
+Then, I can run
+ $ git annex get --auto D
+ $ git annex copy --auto --to phone D
+ $ git annex drop --auto D
+
+This in my use case takes 3 minutes.
+
+When I run
+ $ git annex sync --content phone
+
+git annex goes recursively through A, B and C and that takes a long time (much more than 3 minutes). This time is really wasted since I know I only want to sync files from D.
+
+I cannot test the behavior of \"git annex sync --content\", but if I restrict the sync to phone, will it take the files from the NAS to put them on the phone?
+If I don't precise phone in the command line, it will try to sync with other repositories not in sync that I don't want to be in sync for the time being.
+"""]]
diff --git a/doc/forum/git_annex_on_osx_only_creating_symlinks__63____63__/comment_2_978fc11c463a457382fddd668cd1d0dd._comment b/doc/forum/git_annex_on_osx_only_creating_symlinks__63____63__/comment_2_978fc11c463a457382fddd668cd1d0dd._comment
index e50e0b073..b3a848ffe 100644
--- a/doc/forum/git_annex_on_osx_only_creating_symlinks__63____63__/comment_2_978fc11c463a457382fddd668cd1d0dd._comment
+++ b/doc/forum/git_annex_on_osx_only_creating_symlinks__63____63__/comment_2_978fc11c463a457382fddd668cd1d0dd._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawkipQLNyt8RHREHpg2k5wdYeRSCCvSNSBg"
nickname="Tim"
subject="I had this same problem too"
diff --git a/doc/forum/handling_MP3_metadata_changes.txt b/doc/forum/handling_MP3_metadata_changes.mdwn
index 9b6caa27a..9b6caa27a 100644
--- a/doc/forum/handling_MP3_metadata_changes.txt
+++ b/doc/forum/handling_MP3_metadata_changes.mdwn
diff --git a/doc/forum/handling_MP3_metadata_changes/comment_1_aa4955fd64ea5aa836f1a591e185c4a2._comment b/doc/forum/handling_MP3_metadata_changes/comment_1_aa4955fd64ea5aa836f1a591e185c4a2._comment
new file mode 100644
index 000000000..483c1fb78
--- /dev/null
+++ b/doc/forum/handling_MP3_metadata_changes/comment_1_aa4955fd64ea5aa836f1a591e185c4a2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T19:29:53Z"
+ content="""
+Check out [[metadata]]
+"""]]
diff --git a/doc/forum/ignore_changes_made_by_a_remote.mdwn b/doc/forum/ignore_changes_made_by_a_remote.mdwn
new file mode 100644
index 000000000..3659774b4
--- /dev/null
+++ b/doc/forum/ignore_changes_made_by_a_remote.mdwn
@@ -0,0 +1,8 @@
+Hi,
+
+I have two repo one in direct (on windows) and one in indirect mode. From time to time the files in the direct repo are replaced by empty files however running git annex fsck always solves it.
+The problem is that today I did run git annex sync before running git annex fsck and git annex has then created two -variants for each of my files one empty and one with the content.
+I guess the easier for me is to just scrap that repo and make a new one however how do I prevent the changes to propagate now? I guess that if I now run git annex sync on my other repo all those small files are going to have linked created for them there as well.
+
+I hope this is clear,
+Thanks in advance.
diff --git a/doc/forum/ignore_changes_made_by_a_remote/comment_1_825676069d2e1554499b76fd8c306c30._comment b/doc/forum/ignore_changes_made_by_a_remote/comment_1_825676069d2e1554499b76fd8c306c30._comment
new file mode 100644
index 000000000..8abc059f6
--- /dev/null
+++ b/doc/forum/ignore_changes_made_by_a_remote/comment_1_825676069d2e1554499b76fd8c306c30._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T20:02:19Z"
+ content="""
+I don't see any need to scrap the repository. Since you have an indirect mode repsitory, you can use `git log` in there to find commits you don't like, and run `git revert` to revert them. So if a bad commit comes down from windows, you can just undo it. That's why we use git, yes?
+
+I'm much more curious about the circumstances that cause empty files to end up in the direct mode repository.
+"""]]
diff --git a/doc/forum/lost_in_walkthrough....txt b/doc/forum/lost_in_walkthrough....mdwn
index 89f4af026..89f4af026 100644
--- a/doc/forum/lost_in_walkthrough....txt
+++ b/doc/forum/lost_in_walkthrough....mdwn
diff --git a/doc/forum/manual_update_of_.git__47__annex__47__objects.txt b/doc/forum/manual_update_of_.git__47__annex__47__objects.mdwn
index 9de5779c1..9de5779c1 100644
--- a/doc/forum/manual_update_of_.git__47__annex__47__objects.txt
+++ b/doc/forum/manual_update_of_.git__47__annex__47__objects.mdwn
diff --git a/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_2_a7bbf304b26650a786e358bdc01e3069._comment b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_2_a7bbf304b26650a786e358bdc01e3069._comment
new file mode 100644
index 000000000..5468ed3d0
--- /dev/null
+++ b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_2_a7bbf304b26650a786e358bdc01e3069._comment
@@ -0,0 +1,33 @@
+[[!comment format=mdwn
+ username="rasmus"
+ ip="109.201.154.177"
+ subject="But how to clean this folder?"
+ date="2014-03-20T21:55:26Z"
+ content="""
+Joey,
+
+I have sometimes experienced that there is way too much content in the `.git/annex/objects` folder. For instance, my terminal emulator recently crashed during a sync which seemed to create a lot of folders.
+
+In the annex repo where this happened I now got way too many folders (annex sometimes complain about no. of inodes or something like that) and I don't know how to clean it correctly.
+
+Here's a \"screenshot\":
+
+ [doc.annex] $ ls -a
+ . .. documents .git .gitignore
+ [doc.annex] $ find . -type d | wc -l
+ 38568
+ [doc.annex] $ git annex fsck > /dev/null 2>&1
+ [doc.annex] $ find . -type d | wc -l
+ 38568
+ [doc.annex] $ git annex repair > /dev/null 2>&1
+ [doc.annex] $ find . -type d | wc -l
+ 38568
+ [doc.annex] $ find documents -type d | wc -l
+ 1513
+ [doc.annex] $ find .git/annex/objects -type d | wc -l
+ 36712
+
+This is a `direct`-mode repo. With `.git/objectcts` I can use `git gc`. How can I tell annex to tidy up? I have tried `fsck`, `repair` and `forget`.
+
+Any hints on how to deal with this? Other than manually clean up by deleting `.git/annex/objects` and rerunning `fsck`?
+"""]]
diff --git a/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_3_a855096b683c4c4f84e72c797e065d59._comment b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_3_a855096b683c4c4f84e72c797e065d59._comment
new file mode 100644
index 000000000..2271e04ff
--- /dev/null
+++ b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_3_a855096b683c4c4f84e72c797e065d59._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 3"
+ date="2014-03-26T19:09:07Z"
+ content="""
+1. This followup question seems to have nothing to do with the original question. (The aswer to the original question was `git annex fsck --fast`.)
+2. I find it hard to believe that a crashing terminal emulator will create a lot of folders.
+3. You show 36k subdirectories in .git/annex/objects. If I make a *tiny* 100 mb ext2 filesystem, it has 26k inodes. A 200 mb filesystem has 50k. So we're talking about a number of directories that is only large when using hardware from 1996.
+
+I'm not convinced yet that anything is wrong, or that there's anything you can do to improve matters. In any case, see [[todo/wishlist:_pack_metadata_in_direct_mode]].
+"""]]
diff --git a/doc/forum/multiple_repositories_single_backup.txt b/doc/forum/multiple_repositories_single_backup.mdwn
index 10f8c0e43..10f8c0e43 100644
--- a/doc/forum/multiple_repositories_single_backup.txt
+++ b/doc/forum/multiple_repositories_single_backup.mdwn
diff --git a/doc/forum/multiple_repositories_single_backup/comment_2_bbe19eec0969385a0d4682bf9e9de21a._comment b/doc/forum/multiple_repositories_single_backup/comment_2_bbe19eec0969385a0d4682bf9e9de21a._comment
index 8b81d56f4..bac577ce9 100644
--- a/doc/forum/multiple_repositories_single_backup/comment_2_bbe19eec0969385a0d4682bf9e9de21a._comment
+++ b/doc/forum/multiple_repositories_single_backup/comment_2_bbe19eec0969385a0d4682bf9e9de21a._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawkNE-H4vEcbcGndxq5daT8qUb7yIf7r1OE"
nickname="Łukasz"
subject="comment 2"
diff --git a/doc/forum/partial_synchronisation._android_phone.txt b/doc/forum/partial_synchronisation._android_phone.mdwn
index 7abfb24cd..7abfb24cd 100644
--- a/doc/forum/partial_synchronisation._android_phone.txt
+++ b/doc/forum/partial_synchronisation._android_phone.mdwn
diff --git a/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__.mdwn b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__.mdwn
new file mode 100644
index 000000000..2a22d6ee7
--- /dev/null
+++ b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__.mdwn
@@ -0,0 +1,13 @@
+When trying to setup an rsync.net repo I always get the following error:
+
+Permission denied, please try again.
+Permission denied, please try again.
+Received disconnect from 114.xxx.xxx.xxx: 2: Too many authentication failures for 2*****
+
+I can ssh into the account without any problems and couldn't find anything, which would have helped me any further.
+Any ideas? Is the problem sitting in front of the computer? Is it a bug?
+
+Thanks.
+David
+
+This is happening on Mavericks (10.9)
diff --git a/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_1_7754e2cfb72b034effe8642c1b3e593e._comment b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_1_7754e2cfb72b034effe8642c1b3e593e._comment
new file mode 100644
index 000000000..d29f6482c
--- /dev/null
+++ b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_1_7754e2cfb72b034effe8642c1b3e593e._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn_3tllXjSmtgm__aGr9Z4gVNFgJgGyJ30"
+ nickname="David Alan"
+ subject="comment 1"
+ date="2014-04-02T15:58:57Z"
+ content="""
+This problem also exists, when connecting to other ssh remote servers.
+The error msg would be:
+
+ Failed to ssh to the server. Transcript: Permission denied, please try again. Received disconnect from 80.xxx.xxx.xxx: 2: Too many authentication failures for ssh-xxxxxx-git-annex-assist
+"""]]
diff --git a/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_2_04e1da4352ef9f9be90253ea726e5f24._comment b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_2_04e1da4352ef9f9be90253ea726e5f24._comment
new file mode 100644
index 000000000..3181c4fe0
--- /dev/null
+++ b/doc/forum/rsync.net:_Too_many_authentication_failures_for___42____42____42____42____42__/comment_2_04e1da4352ef9f9be90253ea726e5f24._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 2"
+ date="2014-04-02T19:41:29Z"
+ content="""
+What version of git-annex?
+
+Do you have ssh-askpass installed?
+
+You might try running git webapp from a terminal, in case ssh is unable to prompt for the password in a window using ssh-askpass.
+"""]]
diff --git a/doc/forum/sync_between_indirect_and_direct_mode/comment_3_9acb237711669ec6046a8d07f9ed3b2c._comment b/doc/forum/sync_between_indirect_and_direct_mode/comment_3_9acb237711669ec6046a8d07f9ed3b2c._comment
new file mode 100644
index 000000000..f743487b2
--- /dev/null
+++ b/doc/forum/sync_between_indirect_and_direct_mode/comment_3_9acb237711669ec6046a8d07f9ed3b2c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-12T17:03:30Z"
+ content="""
+Direct mode does not require all content be present any more than indirect mode does, and missing content is represented the same in both modes, with broken symlinks.
+"""]]
diff --git a/doc/forum/telehash_syncing.mdwn b/doc/forum/telehash_syncing.mdwn
new file mode 100644
index 000000000..3a5266506
--- /dev/null
+++ b/doc/forum/telehash_syncing.mdwn
@@ -0,0 +1,10 @@
+Hi
+
+I have read some info about telehash. It looks verry promising. I was wondering though how syncing will work. For example. I have 2 computers. Normal PC and a laptop. Mostly only one is on at a time.
+
+* Sync messages will be sent over telehash protocoll ?
+* What if I push some changes (they will be synced to a shared repository) and laptop is not online. How will git-annex know what to sync from a shared repository ?
+* Do you plan to send files/commits directly to online clients ? If 2 friends are online at the same time.
+* What will happen with data on a shared repository if all clients have synced content ? Will it be deleted since it is not longer needed ?
+
+I was thinking of a model where you sync directly (if possible), and just drop shared content to repo for offline users. Whan everyone have pulled content it may be removed from shared repo.
diff --git a/doc/forum/unrelated_repositories_sync.mdwn b/doc/forum/unrelated_repositories_sync.mdwn
new file mode 100644
index 000000000..030fb380d
--- /dev/null
+++ b/doc/forum/unrelated_repositories_sync.mdwn
@@ -0,0 +1,15 @@
+I have no idea how to search for this here, so I'll just go the "lazy web" approach and just ask.
+
+Say I have two "conference" repos. One is the famous [conference procedings](https://github.com/RichiH/conference_proceedings) repo, and another one is a totally unrelated repo of local conferences that are not of world-wide significance. Let's call this second repo `presentations`.
+
+I would like to have my videos of both repos in a single repo.
+
+Can I add the `conference procedings` repo as a git remote to the `presentations` repo and have it do the right thing?
+
+In fact, I'm not even sure what the right thing would be here, I guess that's the first thing I would like to clear up. But I would like to do things like what the new [[metadata]] system does. For example, I would have only the "Debian" directory from `conference procedings` in my `presentations` repo.
+
+How would that work? Would I need to do some [subtree merging](http://git-scm.com/book/ch6-7.html) magic? or `git subtree`? or submodules? or should i just use myrepos and pretend I never brought up this idea?
+
+thanks! -- [[anarcat]]
+
+related: [[tips/migrating_two_seperate_disconnected_directories_to_git_annex/]] - but that creates a merged repo...
diff --git a/doc/forum/unrelated_repositories_sync/comment_1_c899b7b05a96d14e25c2efadff3b4e52._comment b/doc/forum/unrelated_repositories_sync/comment_1_c899b7b05a96d14e25c2efadff3b4e52._comment
new file mode 100644
index 000000000..7df8a0eb9
--- /dev/null
+++ b/doc/forum/unrelated_repositories_sync/comment_1_c899b7b05a96d14e25c2efadff3b4e52._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 1"
+ date="2014-04-02T19:51:06Z"
+ content="""
+It might help if you think about these two different repositories as branches. You have 2 branches with different files in them, and you want to produce a third branch with some mix of the two.
+
+I think git is perfectly capable of doing that. Where it gets hairy is dealing with merges when either of the 2 repositories change going forward. The same as if you've forked and modified source code, you will need to do *something* to resolve merges.
+"""]]
diff --git a/doc/forum/view_from_numeric_values.mdwn b/doc/forum/view_from_numeric_values.mdwn
new file mode 100644
index 000000000..e1fc48a0f
--- /dev/null
+++ b/doc/forum/view_from_numeric_values.mdwn
@@ -0,0 +1,9 @@
+Hi Joey,
+
+it would be nice when views could take numeric comparisons as filters.
+
+ git annex metadata -s length=273.0 john_cage_4_33.mp3
+
+ git annex view length<=300
+
+... here is the catch, < and > don't work well in shell, this needs some other Syntax. I think the underlying machinery (using numeric comparisons instead globs) should be quite trivial. Any Ideas about a Syntax?
diff --git a/doc/forum/view_from_numeric_values/comment_1_f3c440f3f0104002a0020ba96ddcf87b._comment b/doc/forum/view_from_numeric_values/comment_1_f3c440f3f0104002a0020ba96ddcf87b._comment
new file mode 100644
index 000000000..4df3034a2
--- /dev/null
+++ b/doc/forum/view_from_numeric_values/comment_1_f3c440f3f0104002a0020ba96ddcf87b._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="cehteh"
+ ip="217.8.62.137"
+ subject="consistent syntax"
+ date="2014-03-25T15:25:43Z"
+ content="""
+Further thinking led to the idea to use the test(1) like syntax to filter matches.
+
+ git annex view length=.* -lt 300 -gt 30 -o -eq 273 bpm=.* -eq 0
+
+"""]]
diff --git a/doc/forum/view_from_numeric_values/comment_2_2414e1a8cfd154c339d8fc0e4a630ae9._comment b/doc/forum/view_from_numeric_values/comment_2_2414e1a8cfd154c339d8fc0e4a630ae9._comment
new file mode 100644
index 000000000..ff4fcc551
--- /dev/null
+++ b/doc/forum/view_from_numeric_values/comment_2_2414e1a8cfd154c339d8fc0e4a630ae9._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 2"
+ date="2014-03-26T17:53:28Z"
+ content="""
+I'm a little bit worried about the potential to reinvent SQL, badly. ;)
+
+As shown in your example, once you have ranges, it's natural to also want disjunctions, and then probably parenthesized expressions, and suddenly things are very complicated.
+
+Also, it's important that views remain reversable, so that committing a moved file in a view can unambiguously calculate the new metadata for it. I think that quickly becomes hard when adding these complications.
+"""]]
diff --git a/doc/forum/view_from_numeric_values/comment_3_7879a11cc9767cdaac14f9993182dc25._comment b/doc/forum/view_from_numeric_values/comment_3_7879a11cc9767cdaac14f9993182dc25._comment
new file mode 100644
index 000000000..da6dded17
--- /dev/null
+++ b/doc/forum/view_from_numeric_values/comment_3_7879a11cc9767cdaac14f9993182dc25._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="cehteh"
+ ip="217.8.62.137"
+ subject="comment 3"
+ date="2014-03-26T18:55:41Z"
+ content="""
+I'm a little bit worried about the potential to reinvent SQL, badly. ;)
+
+As shown in your example, once you have ranges, it's natural to also want disjunctions, and then probably parenthesized expressions, and suddenly things are very complicated.
+
+Also, it's important that views remain reversable, so that committing a moved file in a view can unambiguously calculate the new metadata for it. I think that quickly becomes hard when adding these complications.
+
+"""]]
diff --git a/doc/forum/view_from_numeric_values/comment_4_517c7659654a6fc608eb3332053df8a4._comment b/doc/forum/view_from_numeric_values/comment_4_517c7659654a6fc608eb3332053df8a4._comment
new file mode 100644
index 000000000..90cb1c22a
--- /dev/null
+++ b/doc/forum/view_from_numeric_values/comment_4_517c7659654a6fc608eb3332053df8a4._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="cehteh"
+ ip="217.8.62.137"
+ subject="comment 4"
+ date="2014-03-26T20:03:51Z"
+ content="""
+I agree with you that things must stay simple. All what should be done is having the same effects like normal globs but adding arithmetic comparisons to it (could you think about a globbing extension over numeric values?). Then the generated views will have the same properties/semnatic as the normal glob'ed views without other side effects (if you want to go that far, this would even hold true for disjunct, parenthesized and otherwise complex expression).
+
+Example (how it should work, except my bug report 'set metadata on wrong files')
+
+ git annex metadata a.txt -s foo=bar -s num=1
+ git annex metadata b.txt -s foo=baz -s num=2
+ git annex metadata c.txt -s foo=barf -s num=3
+
+ git annex view foo=bar* num=* -ne 2
+
+should give
+ ./bar/1/a.txt ./barf/3/c.txt
+
+am I right now than one could
+
+ mkdir -p ./baz/2
+ mv /bar/1/a.txt ./baz/2
+
+to change the metadata of a.txt, despite the foo=baz and num=2 fields where initially filtered out when creating the view?
+If this assumption is true then having arithmetic filters, no matter how complex they are won't change the existing semantics over what globs do.
+
+"""]]
diff --git a/doc/forum/view_including_files_with_no_tags.mdwn b/doc/forum/view_including_files_with_no_tags.mdwn
new file mode 100644
index 000000000..7ed64fc7d
--- /dev/null
+++ b/doc/forum/view_including_files_with_no_tags.mdwn
@@ -0,0 +1,5 @@
+Hi
+
+Is it possible to create a view which also includes files with no tag?
+
+I use something like `git annex view 'rating=*'` to view files sorted by rating but this view does not include files which don‘t have a rating yet. What I was looking for is a way to show tagged files and untagged files in one view.
diff --git a/doc/forum/view_including_files_with_no_tags/comment_1_b0aafc023fbec33af268576c4c199af3._comment b/doc/forum/view_including_files_with_no_tags/comment_1_b0aafc023fbec33af268576c4c199af3._comment
new file mode 100644
index 000000000..ec58308b7
--- /dev/null
+++ b/doc/forum/view_including_files_with_no_tags/comment_1_b0aafc023fbec33af268576c4c199af3._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="Xyem"
+ ip="87.194.19.134"
+ subject="comment 1"
+ date="2014-03-25T08:54:23Z"
+ content="""
+This is a TODO:
+
+http://git-annex.branchable.com/design/metadata/
+
+ unmatched files in filtered branches
+
+ TODO Files not matching the view should be able to be included in the filtered branch, in a special location, an \"other\" directory.
+
+In the meantime, I do this before switching to the view:
+
+ git annex metadata -s fieldIwant?=untagged
+
+This shows the files without any \"fieldIwant\" in the directory \"untagged\". Afterwards, I could (but don't need to in my workflow, it automatically gets removed), do this to remove it:
+
+ git annex metadata -s fieldIwant-=untagged
+
+What the \"?=\" does is add that metadata only if the \"fieldIwant\" hasn't been set at all.
+"""]]
diff --git a/doc/forum/view_including_files_with_no_tags/comment_2_5ae9d5308371bdb1f94342c9f9b01aff._comment b/doc/forum/view_including_files_with_no_tags/comment_2_5ae9d5308371bdb1f94342c9f9b01aff._comment
new file mode 100644
index 000000000..3f16a163f
--- /dev/null
+++ b/doc/forum/view_including_files_with_no_tags/comment_2_5ae9d5308371bdb1f94342c9f9b01aff._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://ypid.wordpress.com/"
+ ip="213.153.84.215"
+ subject="Perfect"
+ date="2014-03-25T20:11:26Z"
+ content="""
+This works great. Nice workaround, thanks very much.
+"""]]
diff --git a/doc/git-annex-shell.mdwn b/doc/git-annex-shell.mdwn
index c866154ac..c015a7bda 100644
--- a/doc/git-annex-shell.mdwn
+++ b/doc/git-annex-shell.mdwn
@@ -26,7 +26,12 @@ first "/~/" or "/~user/" is expanded to the specified home directory.
* configlist directory
This outputs a subset of the git configuration, in the same form as
- `git config --list`
+ `git config --list`. This is used to get the annex.uuid of the remote
+ repository.
+
+ When run in a repository that does not yet have an annex.uuid, one
+ will be created, as long as a git-annex branch has already been pushed to
+ the repository.
* inannex directory [key ...]
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 30494e95c..987a9ffef 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -62,10 +62,14 @@ subdirectories).
* `add [path ...]`
- Adds files in the path to the annex. Files that are already checked into
- git, or that git has been configured to ignore will be silently skipped.
- (Use `--force` to add ignored files.) Dotfiles are skipped unless explicitly
- listed.
+ Adds files in the path to the annex. If no path is specified, adds
+ files from the current directory and below.
+
+ Files that are already checked into git, or that git has been configured
+ to ignore will be silently skipped. (Use `--force` to add ignored files.)
+
+ Dotfiles are skipped unless explicitly listed, or the --include-dotfiles
+ option is used.
* `get [path ...]`
@@ -302,7 +306,8 @@ subdirectories).
* `webapp`
Opens a web app, that allows easy setup of a git-annex repository,
- and control of the git-annex assistant.
+ and control of the git-annex assistant. If the assistant is not
+ already running, it will be started.
By default, the webapp can only be accessed from localhost, and running
it opens a browser window.
@@ -476,8 +481,8 @@ subdirectories).
* `vicfg`
Opens EDITOR on a temp file containing most of the above configuration
- settings, and when it exits, stores any changes made back to the git-annex
- branch.
+ settings, as well as a few others, and when it exits, stores any changes
+ made back to the git-annex branch.
* `direct`
@@ -704,12 +709,21 @@ subdirectories).
# METADATA COMMANDS
-* `metadata [path ...] [-s field=value -s field+=value -s field-=value ...]`
+* `metadata [path ...] [-s field=value -s field+=value -s field-=value ...] [-g field]`
+
+ The content of a file can have any number of metadata fields
+ attached to it to describe it. Each metadata field can in turn
+ have any number of values.
+
+ This command can be used to set metadata, or show the currently set
+ metadata.
+
+ To show current metadata, run without any -s parameters. The --json
+ option will enable json output.
- Each file can have any number of metadata fields attached to it,
- which each in turn have any number of values. This sets metadata
- for the specified file or files, or if run without any values, shows
- the current metadata.
+ To only get the value(s) of a single field, use -g field.
+ The values will be output one per line, with no other output, so
+ this is suitable for use in a script.
To set a field's value, removing any old value(s), use -s field=value.
@@ -1044,6 +1058,19 @@ subdirectories).
Overrides the User-Agent to use when downloading files from the web.
+* `--notify-finish`
+
+ Caused a desktop notification to be displayed after each successful
+ file download and upload.
+
+ (Only supported on some platforms, eg Linux with dbus. A no-op when
+ not supported.)
+
+* `--notify-start`
+
+ Caused a desktop notification to be displayed when a file upload
+ or download has started, or when a file is dropped.
+
* `-c name=value`
Overrides git configuration settings. May be specified multiple times.
@@ -1688,7 +1715,7 @@ used by git-annex.
`~/.config/git-annex/autostart` is a list of git repositories
to start the git-annex assistant in.
-`.git/hooks/pre-commit-annex` in your git repsitory will be run whenever
+`.git/hooks/pre-commit-annex` in your git repository will be run whenever
a commit is made, either by git commit, git-annex sync, or the git-annex
assistant.
diff --git a/doc/install.mdwn b/doc/install.mdwn
index ecbf11a15..d9715b7da 100644
--- a/doc/install.mdwn
+++ b/doc/install.mdwn
@@ -14,6 +14,7 @@ detailed instructions | quick install
&nbsp;&nbsp;[[Gentoo]] | `emerge git-annex`
&nbsp;&nbsp;[[ScientificLinux5]] |
&nbsp;&nbsp;[[openSUSE]] |
+&nbsp;&nbsp;[[Docker]] |
[[Windows]] | [download installer](http://downloads.kitenet.net/git-annex/windows/current/) **alpha**
"""]]
diff --git a/doc/install/ArchLinux/comment_6_1d597d6a95f9c2df7dae6e98813e4865._comment b/doc/install/ArchLinux/comment_6_1d597d6a95f9c2df7dae6e98813e4865._comment
new file mode 100644
index 000000000..9f158347b
--- /dev/null
+++ b/doc/install/ArchLinux/comment_6_1d597d6a95f9c2df7dae6e98813e4865._comment
@@ -0,0 +1,36 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmqWbWVRH2k9spSMqKfIXBP1G3ekkj9Igg"
+ nickname="Rado"
+ subject="problem installing using cabal: language-javascript missing"
+ date="2014-03-28T22:38:04Z"
+ content="""
+Configuring gnuidn-0.2.1...
+cabal: The program c2hs is required but it could not be found.
+Failed to install gnuidn-0.2.1
+Configuring language-javascript-0.5.9...
+cabal: The program happy version >=1.18.5 is required but it could not be
+found.
+Failed to install language-javascript-0.5.9
+cabal: Error: some packages failed to install:
+git-annex-5.20140320 depends on language-javascript-0.5.9 which failed to
+install.
+gnuidn-0.2.1 failed during the configure step. The exception was:
+ExitFailure 1
+hjsmin-0.1.4.6 depends on language-javascript-0.5.9 which failed to install.
+language-javascript-0.5.9 failed during the configure step. The exception was:
+ExitFailure 1
+network-protocol-xmpp-0.4.6 depends on gnuidn-0.2.1 which failed to install.
+yesod-static-1.2.2.4 depends on language-javascript-0.5.9 which failed to
+install.
+[r-c@rc-laptop ~]$ cabal install language-javascript
+Resolving dependencies...
+Configuring language-javascript-0.5.9...
+cabal: The program happy version >=1.18.5 is required but it could not be
+found.
+Failed to install language-javascript-0.5.9
+cabal: Error: some packages failed to install:
+language-javascript-0.5.9 failed during the configure step. The exception was:
+ExitFailure 1
+
+Can you help how to solve?
+"""]]
diff --git a/doc/install/ArchLinux/comment_7_2d708977e2fad6b68803494576382df5._comment b/doc/install/ArchLinux/comment_7_2d708977e2fad6b68803494576382df5._comment
new file mode 100644
index 000000000..3d7826bc1
--- /dev/null
+++ b/doc/install/ArchLinux/comment_7_2d708977e2fad6b68803494576382df5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://alerque.com/"
+ nickname="Caleb"
+ subject="dep problems"
+ date="2014-03-28T22:50:37Z"
+ content="""
+@rado The Haskel dependencies can be a nightmare to sort out for the un-initiated. You can side-step the whole issue by uninstalling the pre-built version that that has all the dependencies built in out of the box.
+
+Just grab the git-annex-bin package from the AUR and be done with it. (The -bin and -standalone packages recently merged so there is just -bin now).
+"""]]
diff --git a/doc/install/ArchLinux/comment_8_5b5f5e0b64e5bfb1ea12e8b251c6fb5f._comment b/doc/install/ArchLinux/comment_8_5b5f5e0b64e5bfb1ea12e8b251c6fb5f._comment
new file mode 100644
index 000000000..3e6d6b3a8
--- /dev/null
+++ b/doc/install/ArchLinux/comment_8_5b5f5e0b64e5bfb1ea12e8b251c6fb5f._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmqWbWVRH2k9spSMqKfIXBP1G3ekkj9Igg"
+ nickname="Rado"
+ subject="I solved it installing dependencies....but dont know hot to start it..."
+ date="2014-03-29T07:45:19Z"
+ content="""
+cabal install gsasl
+cabal install happy
+cabal install language-javascript
+cabal install alex
+cabal install c2hs
+
+after installing writing in terminal: git-annex, git-annex webapp does nothing...
+can you help how to start git-annex?
+"""]]
diff --git a/doc/install/Docker.mdwn b/doc/install/Docker.mdwn
new file mode 100644
index 000000000..3e0171dde
--- /dev/null
+++ b/doc/install/Docker.mdwn
@@ -0,0 +1,27 @@
+There is not yet a pre-built Docker image for git-annex. However, it's
+easy to add it to an image.
+
+For example:
+
+ docker run -i -t joeyh/debian-unstable apt-get install git-annex
+
+# autobuilders
+
+The git-annex Linux autobuilds are built using a Docker container.
+If you'd like to set up your own autobuilder in a Docker container,
+the image that is used is not currently published, but you can build
+a new image using [Propellor](http://joeyh.name/code/propellor). Just
+install Propellor and add this to its `config.hs`:
+
+[[!format haskell """
+host hostname@"your.machine.net" = Just $ props
+ & Docker.configured
+ & Docker.docked container hostname "amd64-git-annex-builder"
+
+container _ "amd64-git-annex-builder" = in Just $ Docker.containerFrom
+ (image $ System (Debian Unstable) "amd64")
+ [ Docker.inside $ props & GitAnnexBuilder.builder "amd64" "15 * * * *" False ]
+"""]]
+
+This will autobuild every hour at :15, and the autobuilt image will be
+left inside the container in /home/builder/gitbuilder/out/
diff --git a/doc/install/cabal/comment_33_8d4dfc33cada6091c30d3a43ce404b8b._comment b/doc/install/cabal/comment_33_8d4dfc33cada6091c30d3a43ce404b8b._comment
new file mode 100644
index 000000000..8fab5a45f
--- /dev/null
+++ b/doc/install/cabal/comment_33_8d4dfc33cada6091c30d3a43ce404b8b._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn3p4i4lk_zMilvjnJ9sS6g2nerpgz0Fjc"
+ nickname="Matthias"
+ subject="Build failure"
+ date="2014-03-20T09:10:44Z"
+ content="""
+I followed the instructions and the invocation of
+
+ cabal install git-annex --bindir=$HOME/bin -f\"-assistant -webapp -webdav -pairing -xmpp -dns\"
+
+resulted in the following error:
+
+ Test.hs:107:41: Not in scope: `errMessage'
+ Failed to install git-annex-5.20140306
+ cabal: Error: some packages failed to install:
+ git-annex-5.20140306 failed during the building phase. The exception was:
+ ExitFailure 1
+
+I used the Haskell Platform for Mac OS X (10.8)
+
+"""]]
diff --git a/doc/install/cabal/comment_34_38451e751add6daf479b559c4b6a7c61._comment b/doc/install/cabal/comment_34_38451e751add6daf479b559c4b6a7c61._comment
new file mode 100644
index 000000000..619e79012
--- /dev/null
+++ b/doc/install/cabal/comment_34_38451e751add6daf479b559c4b6a7c61._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://openid.stackexchange.com/user/a05bb829-932b-49f2-85a9-00dcda8b5e20"
+ nickname="Christian Pietsch"
+ subject="Re: Build failure"
+ date="2014-03-20T13:56:16Z"
+ content="""
+I get exactly the same error message as Matthias when attempting the minimal Cabal install on openSUSE 12.2 (x86_64) Linux.
+"""]]
diff --git a/doc/install/cabal/comment_35_4d44e4531e6686bd340f26836ad40026._comment b/doc/install/cabal/comment_35_4d44e4531e6686bd340f26836ad40026._comment
new file mode 100644
index 000000000..899e4fc01
--- /dev/null
+++ b/doc/install/cabal/comment_35_4d44e4531e6686bd340f26836ad40026._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 35"
+ date="2014-03-20T16:06:22Z"
+ content="""
+The `errMessage` build failure is due to a new version of optparse-applicative. I've added support for it in git master.
+"""]]
diff --git a/doc/install/cabal/comment_5_8789fc27466714faa5a3a7a6b8ec6e5d._comment b/doc/install/cabal/comment_5_8789fc27466714faa5a3a7a6b8ec6e5d._comment
index 52606082e..59bdbdd13 100644
--- a/doc/install/cabal/comment_5_8789fc27466714faa5a3a7a6b8ec6e5d._comment
+++ b/doc/install/cabal/comment_5_8789fc27466714faa5a3a7a6b8ec6e5d._comment
@@ -1,4 +1,4 @@
-[[!comment format=txt
+[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawnaH44G3QbxBAYyDwy0PbvL0ls60XoaR3Y"
nickname="Nigel"
subject="Re: Comment 3"
diff --git a/doc/install/fromscratch.mdwn b/doc/install/fromscratch.mdwn
index 3843c31fa..46ee5a055 100644
--- a/doc/install/fromscratch.mdwn
+++ b/doc/install/fromscratch.mdwn
@@ -3,65 +3,16 @@ quite a lot.
* Haskell stuff
* [The Haskell Platform](http://haskell.org/platform/) (GHC 7.4 or newer)
- * [mtl](http://hackage.haskell.org.package/mtl) (2.1.1 or newer)
- * [MissingH](http://github.com/jgoerzen/missingh/wiki)
- * [data-default](http://hackage.haskell.org/package/data-default)
- * [utf8-string](http://hackage.haskell.org/package/utf8-string)
- * [SHA](http://hackage.haskell.org/package/SHA)
- * [cryptohash](http://hackage.haskell.org/package/cryptohash) (optional but recommended)
- * [dataenc](http://hackage.haskell.org/package/dataenc)
- * [monad-control](http://hackage.haskell.org/package/monad-control)
- * [QuickCheck 2](http://hackage.haskell.org/package/QuickCheck)
- * [json](http://hackage.haskell.org/package/json)
- * [aeson](http://hackage.haskell.org/package/aeson)
- * [IfElse](http://hackage.haskell.org/package/IfElse)
- * [dlist](http://hackage.haskell.org/package/dlist)
- * [bloomfilter](http://hackage.haskell.org/package/bloomfilter)
- * [edit-distance](http://hackage.haskell.org/package/edit-distance)
- * [hS3](http://hackage.haskell.org/package/hS3) (optional)
- * [DAV](http://hackage.haskell.org/package/DAV) (optional)
- * [SafeSemaphore](http://hackage.haskell.org/package/SafeSemaphore)
- * [UUID](http://hackage.haskell.org/package/uuid)
- * [regex-tdfa](http://hackage.haskell.org/package/regex-tdfa)
- * [extensible-exceptions](http://hackage.haskell.org/package/extensible-exceptions)
- * [feed](http://hackage.haskell.org/package/feed)
- * [async](http://hackage.haskell.org/package/async)
- * [case-insensitive](http://hackage.haskell.org/package/case-insensitive)
- * [stm](http://hackage.haskell.org/package/stm)
- (version 2.3 or newer)
-* Optional haskell stuff, used by the [[assistant]] and its webapp
- * [hinotify](http://hackage.haskell.org/package/hinotify)
- (Linux only)
- * [dbus](http://hackage.haskell.org/package/dbus)
- * [yesod](http://hackage.haskell.org/package/yesod)
- * [yesod-static](http://hackage.haskell.org/package/yesod-static)
- * [yesod-default](http://hackage.haskell.org/package/yesod-default)
- * [data-default](http://hackage.haskell.org/package/data-default)
- * [http-types](http://hackage.haskell.org/package/http-types)
- * [wai](http://hackage.haskell.org/package/wai)
- * [wai-logger](http://hackage.haskell.org/package/wai-logger)
- * [warp](http://hackage.haskell.org/package/warp)
- * [warp-tls](http://hackage.haskell.org/package/warp-tls)
- * [blaze-builder](http://hackage.haskell.org/package/blaze-builder)
- * [crypto-api](http://hackage.haskell.org/package/crypto-api)
- * [hamlet](http://hackage.haskell.org/package/hamlet)
- * [clientsession](http://hackage.haskell.org/package/clientsession)
- * [network-multicast](http://hackage.haskell.org/package/network-multicast)
- * [network-info](http://hackage.haskell.org/package/network-info)
- * [network-protocol-xmpp](http://hackage.haskell.org/package/network-protocol-xmpp)
- * [dns](http://hackage.haskell.org/package/dns)
- * [xml-types](http://hackage.haskell.org/package/xml-types)
- * [HTTP](http://hackage.haskell.org/package/HTTP)
- * [unix-compat](http://hackage.haskell.org/package/unix-compat)
- * [MonadCatchIO-transformers](http://hackage.haskell.org/package/MonadCatchIO-transformers)
+ * A ton of haskell libraries. Rather than try to list them all here,
+ see git-annex.cabal. Probably the easiest way to install them:
+ `cabal update; cabal install git-annex --only-dependencies`
* Shell commands
- * [git](http://git-scm.com/) (1.7.2 or newer; 1.8.5 recommended)
+ * [git](http://git-scm.com/) (1.7.2 or newer; 1.8.5 or newer recommended)
* [xargs](http://savannah.gnu.org/projects/findutils/)
* [rsync](http://rsync.samba.org/)
* [curl](http://http://curl.haxx.se/) (optional, but recommended)
* [wget](http://www.gnu.org/software/wget/) (optional)
- * [sha1sum](ftp://ftp.gnu.org/gnu/coreutils/) (optional, but recommended;
- a sha1 command will also do)
+ * [sha*sum](ftp://ftp.gnu.org/gnu/coreutils/) (optional)
* [gpg](http://gnupg.org/) (optional; needed for encryption)
* [lsof](ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/)
(optional; recommended for watch mode)
diff --git a/doc/internals.mdwn b/doc/internals.mdwn
index 4e003d9bc..bf0fa668c 100644
--- a/doc/internals.mdwn
+++ b/doc/internals.mdwn
@@ -150,6 +150,22 @@ Files matching the expression are preferred to be retained in the
repository, while files not matching it are preferred to be stored
somewhere else.
+## `required-content.log`
+
+Used to indicate which repositories are required to contain which file
+contents.
+
+File format is identical to preferred-content.log.
+
+## `group-preferred-content.log`
+
+Contains standard preferred content settings for groups. (Overriding or
+supplimenting the ones built into git-annex.)
+
+The file format is one line per group, staring with a timestamp, then a
+space, then the group name followed by a space and then the preferred
+content expression.
+
## `aaa/bbb/*.log`
These log files record [[location_tracking]] information
diff --git a/doc/logo_16x16.png b/doc/logo_16x16.png
new file mode 100644
index 000000000..c98663d57
--- /dev/null
+++ b/doc/logo_16x16.png
Binary files differ
diff --git a/doc/logo_32x32.png b/doc/logo_32x32.png
new file mode 100644
index 000000000..9075cc2b6
--- /dev/null
+++ b/doc/logo_32x32.png
Binary files differ
diff --git a/doc/metadata.mdwn b/doc/metadata.mdwn
index df873c4c1..684820cb9 100644
--- a/doc/metadata.mdwn
+++ b/doc/metadata.mdwn
@@ -1,7 +1,7 @@
-git-annex allows you to store arbitrary metadata about files stored in the
-git-annex repository. The metadata is stored in the `git-annex` branch, and
-so is automatically kept in sync with the rest of git-annex's state, such
-as [[location_tracking]] information.
+git-annex allows you to store arbitrary metadata about the content of files
+stored in the git-annex repository. The metadata is stored in the
+`git-annex` branch, and so is automatically kept in sync with the rest of
+git-annex's state, such as [[location_tracking]] information.
Some of the things you can do with metadata include:
@@ -23,12 +23,17 @@ The field names are limited to alphanumerics (and `[_-.]`), and are case
insensitive. The metadata values can contain absolutely anything you
like -- but you're recommended to keep it simple and reasonably short.
-Here are some recommended metadata fields to use:
+Here are some metadata fields that git-annex has special support for:
* `tag` - With each tag being a different value.
* `year`, `month` - When this particular version of the file came into
being.
-
+* `$field-lastchanged` - This is automatically maintained for each
+ field that's set, and gives the date and time of the most recent
+ change to the field. It cannot be modified directly.
+* `lastchanged` - This is automatically maintained, giving the data and time
+ of the last change to any of the metadata of a file.
+
To make git-annex automatically set the year and month when adding files,
run `git config annex.genmetadata true`. Also, see
[[tips/automatically_adding_metadata]].
diff --git a/doc/metadata/comment_1_d367fdaf0425b59d694bf16059d47192._comment b/doc/metadata/comment_1_d367fdaf0425b59d694bf16059d47192._comment
new file mode 100644
index 000000000..8fb93442c
--- /dev/null
+++ b/doc/metadata/comment_1_d367fdaf0425b59d694bf16059d47192._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="bremner"
+ ip="198.164.160.48"
+ subject="access metadata by key?"
+ date="2014-03-17T01:26:44Z"
+ content="""
+I'm hacking around with using metadata from an external special remote. Those work with keys, not files, so one option would be to add a GETMETADATA to the protocol. It also seems like it would not be too hard to add
+an option to \"git annex metadata\" to take a key rather than a file.
+"""]]
diff --git a/doc/metadata/comment_2_e15d2b5a405db4ccdb91d6aad4a22983._comment b/doc/metadata/comment_2_e15d2b5a405db4ccdb91d6aad4a22983._comment
new file mode 100644
index 000000000..1fd5a9fe1
--- /dev/null
+++ b/doc/metadata/comment_2_e15d2b5a405db4ccdb91d6aad4a22983._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 2"
+ date="2014-03-17T19:32:39Z"
+ content="""
+I've made `git annex metadata --key` work.
+
+I'll wait and see what you come up with your special remote and add something to the protocol later if it makes sense.
+"""]]
diff --git a/doc/news/version_5.20140210.mdwn b/doc/news/version_5.20140210.mdwn
deleted file mode 100644
index 3049e9d47..000000000
--- a/doc/news/version_5.20140210.mdwn
+++ /dev/null
@@ -1,42 +0,0 @@
-git-annex 5.20140210 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * --in can now refer to files that were located in a repository at
- some past date. For example, --in="here@{yesterday}"
- * Fixed direct mode annexed content locking code, which is used to
- guard against recursive file drops.
- * This is the first beta-level release of the Windows port with important
- fixes (see below).
- (The webapp and assistant are still alpha-level on Windows.)
- * sync --content: Honor annex-ignore configuration.
- * sync: Don't try to sync with xmpp remotes, which are only currently
- supported when using the assistant.
- * sync --content: Re-pull from remotes after downloading content,
- since that can take a while and other changes may be pushed in the
- meantime.
- * sync --content: Reuse smart copy code from copy command, including
- handling and repairing out of date location tracking info.
- Closes: #[737480](http://bugs.debian.org/737480)
- * sync --content: Drop files from remotes that don't want them after
- getting them.
- * sync: Fix bug in automatic merge conflict resolution code when used
- on a filesystem not supporting symlinks, which resulted in it losing
- track of the symlink bit of annexed files.
- * Added ways to configure rsync options to be used only when uploading
- or downloading from a remote. Useful to eg limit upload bandwidth.
- * Fix initremote with encryption=pubkey to work with S3, glacier, webdav,
- and external special remotes.
- * Avoid building with DAV 0.6 which is badly broken (see #737902).
- * Fix dropping of unused keys with spaces in their name.
- * Fix build on platforms not supporting the webapp.
- * Document in man page that sshcaching uses ssh ControlMaster.
- Closes: #[737476](http://bugs.debian.org/737476)
- * Windows: It's now safe to run multiple git-annex processes concurrently
- on Windows; the lock files have been sorted out.
- * Windows: Avoid using unix-compat's rename, which refuses to rename
- directories.
- * Windows: Fix deletion of repositories by test suite and webapp.
- * Windows: Test suite 100% passes again.
- * Windows: Fix bug in symlink calculation code.
- * Windows: Fix handling of absolute unix-style git repository paths.
- * Android: Avoid crashing when unable to set file mode for ssh config file
- due to Android filesystem horribleness."""]] \ No newline at end of file
diff --git a/doc/news/version_5.20140320.mdwn b/doc/news/version_5.20140320.mdwn
new file mode 100644
index 000000000..ee2e95d48
--- /dev/null
+++ b/doc/news/version_5.20140320.mdwn
@@ -0,0 +1,37 @@
+git-annex 5.20140320 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * Fix zombie leak and general inneficiency when copying files to a
+ local git repo.
+ * Fix ssh connection caching stop method to work with openssh 6.5p1,
+ which broke the old method.
+ * webapp: Added a "Sync now" item to each repository's menu.
+ * webapp: Use securemem for constant time auth token comparisons.
+ * copy --fast --to remote: Avoid printing anything for files that
+ are already believed to be present on the remote.
+ * Commands that allow specifying which repository to act on using
+ the repository's description will now fail when multiple repositories
+ match, rather than picking a repository at random.
+ (So will --in=)
+ * Better workaround for problem umasks when eg, setting up ssh keys.
+ * "standard" can now be used as a first-class keyword in preferred content
+ expressions. For example "standard or (include=otherdir/*)"
+ * groupwanted can be used in preferred content expressions.
+ * vicfg: Allows editing preferred content expressions for groups.
+ * Improve behavior when unable to parse a preferred content expression
+ (thanks, ion).
+ * metadata: Add --get
+ * metadata: Support --key option (and some other ones like --all)
+ * For each metadata field, there's now an automatically maintained
+ "$field-lastchanged" that gives the date of the last change to that
+ field. Also the "lastchanged" field for the date of the last change
+ to any of a file's metadata.
+ * unused: In direct mode, files that are deleted from the work tree
+ and so have no content present are no longer incorrectly detected as
+ unused.
+ * Avoid encoding errors when using the unused log file.
+ * map: Fix crash when one of the remotes of a repo is a local directory
+ that does not exist, or is not a git repo.
+ * repair: Improve memory usage when git fsck finds a great many broken
+ objects.
+ * Windows: Fix some filename encoding bugs.
+ * rsync special remote: Fix slashes when used on Windows."""]] \ No newline at end of file
diff --git a/doc/preferred_content.mdwn b/doc/preferred_content.mdwn
index 6d1acfb0f..4f6a3409f 100644
--- a/doc/preferred_content.mdwn
+++ b/doc/preferred_content.mdwn
@@ -1,8 +1,8 @@
git-annex tries to ensure that the configured number of [[copies]] of your
data always exist, and leaves it up to you to use commands like `git annex
get` and `git annex drop` to move the content to the repositories you want
-to contain it. But sometimes, it can be good to have more fine-grained
-control over which repositories prefer to have which content. Configuring
+to contain it. But often, it can be good to have more fine-grained
+control over which content is wanted by which repositories. Configuring
this allows the git-annex assistant as well as
`git annex get --auto`, `git annex drop --auto`, `git annex sync --content`,
etc to do smarter things.
@@ -11,12 +11,32 @@ Preferred content settings can be edited using `git
annex vicfg`, or viewed and set at the command line with `git annex wanted`.
Each repository can have its own settings, and other repositories will
try to honor those settings when interacting with it.
-So there's no local `.git/config` for preferred content settings.
+(So there's no local `.git/config` for preferred content settings.)
+
+[[!template id=note text="""
+### [[quickstart|standard_groups]]
+
+Rather than writing your own preferred content expression, you can use
+several standard ones included in git-annex that are tuned to cover different
+common use cases.
+
+You do this by putting a repository in a group,
+and simply setting its preferred content to "standard" to match whatever
+is standard for that group. See [[standard_groups]] for a list.
+"""]]
The idea is that you write an expression that files are matched against.
-If a file matches, it's preferred to have its content stored in the
-repository. If it doesn't, it's preferred to drop its content from
-the repository (if there are enough copies elsewhere).
+If a file matches, the repository wants to store its content.
+If it doesn't, the repository wants to drop its content
+(if there are enough copies elsewhere to allow removing it).
+
+To check at the command line which files are matched by preferred content
+settings, you can use the --want-get and --want-drop options.
+
+For example, `git annex find --want-get --not --in .` will find all the
+files that `git annex get --auto` will want to get, and `git annex find
+--want-drop --in .` will find all the files that `git annex drop --auto`
+will want to drop.
The expressions are very similar to the matching options documented
on the [[git-annex]] man page. At the command line, you can use those
@@ -54,7 +74,7 @@ and use "copies=transfer:1"
To decide if content should be dropped, git-annex evaluates the preferred
content expression under the assumption that the content has *already* been
-dropped. If the content would not be preferred then, the drop can be done.
+dropped. If the content would not be wanted then, the drop can be done.
So, for example, `copies=2` in a preferred content expression lets
content be dropped only when there are currently 3 copies of it, including
the repo it's being dropped from. This is different than running `git annex
@@ -63,7 +83,7 @@ drop --copies=2`, which will drop files that currently have 2 copies.
### difference: "present"
There's a special "present" keyword you can use in a preferred content
-expression. This means that content is preferred if it's present,
+expression. This means that content is wanted if it's present,
and not otherwise. This leaves it up to you to use git-annex manually
to move content around. You can use this to avoid preferred content
settings from affecting a subdirectory. For example:
@@ -71,7 +91,7 @@ settings from affecting a subdirectory. For example:
auto/* or (include=ad-hoc/* and present)
Note that `not present` is a very bad thing to put in a preferred content
-expression. It'll make it prefer to get content that's not present, and
+expression. It'll make it want to get content that's not present, and
drop content that is present! Don't go there..
### difference: "inpreferreddir"
@@ -86,130 +106,64 @@ The name of the directory can be configured using
(If no directory name is configured, it uses "public" by default.)
-## testing preferred content settings
-
-To check at the command line which files are matched by preferred content
-settings, you can use the --want-get and --want-drop options.
-
-For example, "git annex find --want-get --not --in ." will find all the
-files that "git annex get --auto" will want to get, and "git annex find
---want-drop --in ." will find all the files that "git annex drop --auto"
-will want to drop.
-
-## standard expressions
-
-git-annex comes with some standard preferred content expressions, that can
-be used with repositories that are in some pre-defined groups. To make a
-repository use one of these, just set its preferred content expression
-to "standard", and put it in one of these groups.
-
-(Note that most of these standard expressions also make the repository
-prefer any content that is only currently available on untrusted and
-dead repositories. So if an untrusted repository gets connected,
-any repository that can will back it up.)
-
-### client
-
-All content is preferred, unless it's for a file in a "archive" directory,
-which has reached an archive repository, or is unused.
-
-`(((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or roughlylackingcopies=1`
-
-### transfer
-
-Use for repositories that are used to transfer data between other
-repositories, but do not need to retain data themselves. For
-example, a repository on a server, or in the cloud, or a small
-USB drive used in a sneakernet.
-
-The preferred content expression for these causes them to get and retain
-data until all clients have a copy.
-
-`(not (inallgroup=client and copies=client:2) and ($client)`
-
-(Where $client is a copy of the preferred content expression used for
-clients.)
-
-The "copies=client:2" part of the above handles the case where
-there is only one client repository. It makes a transfer repository
-speculatively prefer content in this case, even though it as of yet
-has nowhere to transfer it to. Presumably, another client repository
-will be added later.
-
-### backup
-
-All content is preferred.
-
-`include=* or unused`
-
-### incremental backup
-
-Only prefers content that's not already backed up to another backup
-or incremental backup repository.
-
-`((include=* or unused) and (not copies=backup:1) and (not copies=incrementalbackup:1)) or approxlackingcopies=1`
-
-### small archive
-
-Only prefers content that's located in an "archive" directory, and
-only if it's not already been archived somewhere else.
-
-`((include=*/archive/* or include=archive/*) and not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1`
-
-### full archive
-
-All content is preferred, unless it's already been archived somewhere else.
-
-`(not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1`
-
-Note that if you want to archive multiple copies (not a bad idea!),
-you should instead configure all your archive repositories with a
-version of the above preferred content expression with a larger
-number of copies.
-
-### source
-
-Use for repositories where files are often added, but that do not need to
-retain files for local use. For example, a repository on a camera, where
-it's desirable to remove photos as soon as they're transferred elsewhere.
-
-The preferred content expression for these causes them to only retain
-data until a copy has been sent to some other repository.
-
-`not (copies=1)`
-
-### manual
-
-This gives you nearly full manual control over what content is stored in the
-repository. This allows using the [[assistant]] without it trying to keep a
-local copy of every file. Instead, you can manually run `git annex get`,
-`git annex drop`, etc to manage content. Only content that is present
-is preferred.
-
-The exception to this manual control is that content that a client
-repository would not want is not preferred. So, files in archive
-directories are not preferred once their content has
-reached an archive repository.
-
-`present and ($client)`
-
-(Where $client is a copy of the preferred content expression used for
-clients.)
-
-### public
-
-This is used for publishing information to a repository that can be
-publically accessed. Only files in a directory with a particular name
-will be published. (The directory can be located anywhere in the
-repository.)
-
-The name of the directory can be configured using
-`git annex enableremote $remote preferreddir=$dirname`
-
-### unwanted
-
-Use for repositories that you don't want to exist. This will result
-in any content on them being moved away to other repositories. (Works
-best when the unwanted repository is also marked as untrusted or dead.)
-
-`exclude=*`
+### difference: "standard"
+
+git-annex comes with some built-in preferred content expressions, that
+can be used with repositories that are in some [[standard_groups]].
+
+When a repository is in exactly one such group, you can use the "standard"
+keyword in its preferred content expression, to match whatever content
+the group's expression matches.
+(If a repository is put into multiple standard
+groups, "standard" will match anything.. so don't do that!)
+
+Most often, the whole preferred content expression is simply "standard".
+But, you can do more complicated things, for example:
+"`standard or include=otherdir/*`"
+
+### difference: "groupwanted"
+
+The "groupwanted" keyword can be used to refer to a preferred content
+expression that is associated with a group. This is like the "standard"
+keyword, but you can set up groupwanted preferred content expressions
+using `git annex vicfg`.
+
+Note that when writing a groupwanted preferred content expression,
+you can use all of the keywords listed above, including "standard".
+(But not "groupwanted".)
+
+For example, to make a variant of the standard client preferred content
+expression that does not want files in the "out" directory, you
+could set `groupwanted client = standard and exclude=out/*`.
+Then repositories that are in the client group and have their preferred
+content expression set to "groupwanted" will use that, while
+other client repositories that have their preferred content expression
+set to "standard" will use the standard expression.
+
+Or, you could make a new group, with your own custom preferred content
+expression tuned for your needs, and every repository you put in this
+group and make its preferred content be "groupwanted" will use it.
+
+## upgrades
+
+It's important that all clones of a repository can understand one-another's
+preferred content expressions, especially when using the git-annex
+assistant. So using newly added keywords can cause a problem if
+an older version of git-annex is in use elsewhere.
+
+Before git-annex version 5.20140320, when git-annex saw a keyword it
+did not understand, it defaulted to assuming *all* files were
+preferred content. From version 5.20140320, git-annex has a nicer fallback
+behavior: When it is unable to parse a preferred content expression,
+it assumes all files that are currently present are preferred content.
+
+Here are recent changes to preferred content expressions, and the version
+they were added in.
+
+* "standard" 5.20140314
+ (only when used in a more complicated expression; "standard" by
+ itself has been supported for a long time)
+* "groupwanted=" 5.20140314
+* "metadata=" 5.20140221
+* "lackingcopies=", "approxlackingcopies=", "unused=" 5.20140127
+* "inpreferreddir=" 4.20130501
diff --git a/doc/preferred_content/standard_groups.mdwn b/doc/preferred_content/standard_groups.mdwn
new file mode 100644
index 000000000..dd73b669f
--- /dev/null
+++ b/doc/preferred_content/standard_groups.mdwn
@@ -0,0 +1,117 @@
+git-annex comes with some built-in [[preferred_content]] settings, that can
+be used with repositories that are in special groups. To make a
+repository use one of these, just set its preferred content expression
+to "standard", and put it in one of these groups.
+
+(Note that most of these standard expressions also make the repository
+want to get any content that is only currently available on untrusted and
+dead repositories. So if an untrusted repository gets connected,
+any repository that can will back it up.)
+
+### client
+
+All content is wanted, unless it's for a file in a "archive" directory,
+which has reached an archive repository, or is unused.
+
+`(((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and not unused) or roughlylackingcopies=1`
+
+### transfer
+
+Use for repositories that are used to transfer data between other
+repositories, but do not need to retain data themselves. For
+example, a repository on a server, or in the cloud, or a small
+USB drive used in a sneakernet.
+
+The preferred content expression for these causes them to get and retain
+data until all clients have a copy.
+
+`not (inallgroup=client and copies=client:2) and ($client)`
+
+(Where $client is a copy of the preferred content expression used for
+clients.)
+
+The "copies=client:2" part of the above handles the case where
+there is only one client repository. It makes a transfer repository
+speculatively prefer content in this case, even though it as of yet
+has nowhere to transfer it to. Presumably, another client repository
+will be added later.
+
+### backup
+
+All content is wanted. Even content of old/deleted files.
+
+`include=* or unused`
+
+### incremental backup
+
+Only wants content that's not already backed up to another backup
+or incremental backup repository.
+
+`((include=* or unused) and (not copies=backup:1) and (not copies=incrementalbackup:1)) or approxlackingcopies=1`
+
+### small archive
+
+Only wants content that's located in an "archive" directory, and
+only if it's not already been archived somewhere else.
+
+`((include=*/archive/* or include=archive/*) and not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1`
+
+### full archive
+
+All content is wanted, unless it's already been archived somewhere else.
+
+`(not (copies=archive:1 or copies=smallarchive:1)) or approxlackingcopies=1`
+
+Note that if you want to archive multiple copies (not a bad idea!),
+you can set `groupwanted archive` to a version of
+the above preferred content expression with a larger number of copies
+than 1. Then make the archive repositories have a preferred
+content expression of "groupwanted" in order to use your modified
+version.
+
+### source
+
+Use for repositories where files are often added, but that do not need to
+retain files for local use. For example, a repository on a camera, where
+it's desirable to remove photos as soon as they're transferred elsewhere.
+
+The preferred content expression for these causes them to only retain
+data until a copy has been sent to some other repository.
+
+`not (copies=1)`
+
+### manual
+
+This gives you nearly full manual control over what content is stored in the
+repository. This allows using the [[assistant]] without it trying to keep a
+local copy of every file. Instead, you can manually run `git annex get`,
+`git annex drop`, etc to manage content. Only content that is already
+present is wanted.
+
+The exception to this manual control is that content that a client
+repository would not want is not wanted. So, files in archive
+directories are not wanted once their content has
+reached an archive repository.
+
+`present and ($client)`
+
+(Where $client is a copy of the preferred content expression used for
+clients.)
+
+### public
+
+This is used for publishing information to a repository that can be
+publically accessed. Only files in a directory with a particular name
+will be published. (The directory can be located anywhere in the
+repository.)
+
+The name of the directory can be configured using
+`git annex enableremote $remote preferreddir=$dirname`
+
+### unwanted
+
+Use for repositories that you don't want to exist. This will result
+in any content on them being moved away to other repositories. (Works
+best when the unwanted repository is also marked as untrusted or dead.)
+
+`exclude=*`
diff --git a/doc/preferred_content/standard_groups/comment_1_026e47e425d06c4b2580238b3187a379._comment b/doc/preferred_content/standard_groups/comment_1_026e47e425d06c4b2580238b3187a379._comment
new file mode 100644
index 000000000..9a06d3791
--- /dev/null
+++ b/doc/preferred_content/standard_groups/comment_1_026e47e425d06c4b2580238b3187a379._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://mildred.fr/"
+ ip="2a01:e35:2f7b:8350:290:f5ff:feea:5546"
+ subject="difference between source and unwanted"
+ date="2014-04-02T22:25:26Z"
+ content="""
+What's the difference between `source` and `unwanted` ?
+
+- `source` (`not copies=1`) will keep files that have less than 1 copies, meaning zero copies, meaning no files.
+- `unwanted` will exclude all files.
+
+Both gets to the same results, all files are moved elsewhere. Right?
+"""]]
diff --git a/doc/preferred_content/standard_groups/comment_2_460bae34ba7c05357318a202b2932d25._comment b/doc/preferred_content/standard_groups/comment_2_460bae34ba7c05357318a202b2932d25._comment
new file mode 100644
index 000000000..c877a9222
--- /dev/null
+++ b/doc/preferred_content/standard_groups/comment_2_460bae34ba7c05357318a202b2932d25._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.244"
+ subject="comment 2"
+ date="2014-04-02T22:44:14Z"
+ content="""
+@Mildred, I think both preferred content expressions will do the same thing. There is, however a difference between the groups: The webapp notices when all files have gone from an unwanted repository, and will help the user finish deleting the repository.
+"""]]
diff --git a/doc/related_software.mdwn b/doc/related_software.mdwn
index 66abad8df..0cd7d7fc8 100644
--- a/doc/related_software.mdwn
+++ b/doc/related_software.mdwn
@@ -11,3 +11,5 @@ designed to interoperate with it.
utility, with a `-A` switch that enables git-annex support.
* Emacs Org mode can auto-commit attached files to git-annex.
* [git annex darktable integration](https://github.com/xxv/darktable-git-annex)
+* Emacs's [Magit mode](http://www.emacswiki.org/emacs/Magit) has
+ [magit integration](http://melpa.milkbox.net/?utm_source=dlvr.it&utm_medium=twitter#/magit-annex)
diff --git a/doc/required_content.mdwn b/doc/required_content.mdwn
new file mode 100644
index 000000000..91c5614a8
--- /dev/null
+++ b/doc/required_content.mdwn
@@ -0,0 +1,17 @@
+Required content settings can be configured to do more complicated
+things than just setting the required number of [[copies]] of your data.
+For example, you could require that data be archived in at least two
+archival repositories, and also require that one copy be stored offsite.
+
+The format of required content expressions is the same as
+[[preferred_content]] expressions.
+
+Required content settings can be edited using `git annex vicfg`.
+Each repository can have its own settings, and other repositories will
+try to honor those settings when interacting with it.
+
+While [[preferred_content]] expresses a preference, it can be overridden
+by simply using `git annex drop`. On the other hand, required content
+settings are enforced; `git annex drop` will refuse to drop a file if
+doing so would violate its required content settings.
+(Although even this can be overridden using `--force`).
diff --git a/doc/special_remotes/tahoe.mdwn b/doc/special_remotes/tahoe.mdwn
index afe8c11da..df1ca620f 100644
--- a/doc/special_remotes/tahoe.mdwn
+++ b/doc/special_remotes/tahoe.mdwn
@@ -22,8 +22,12 @@ daemon as needed.
These parameters can be passed to `git annex initremote` to configure
the tahoe remote.
+* `shared-convergence-secret` - Optional. Can be useful to set to
+ allow tahoe to deduplicate information. By default, a new
+ shared-convergence-secret is created for each tahoe remote.
+
* `embedcreds` - Optional. Set to "yes" embed the tahoe credentials
- (specifically the introducer furl and shared-convergence-secret)
+ (specifically the introducer-furl and shared-convergence-secret)
inside the git repository, which allows other clones to also use them
in order to access the tahoe grid.
diff --git a/doc/tips/Synology_NAS_and_git_annex/comment_1_ef7e19f1fd2005eb7cc74509ffb92766._comment b/doc/tips/Synology_NAS_and_git_annex/comment_1_ef7e19f1fd2005eb7cc74509ffb92766._comment
new file mode 100644
index 000000000..e7a1db937
--- /dev/null
+++ b/doc/tips/Synology_NAS_and_git_annex/comment_1_ef7e19f1fd2005eb7cc74509ffb92766._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnrP-0DGtHDJbWSXeiyk0swNkK1aejoN3c"
+ nickname="sebastien"
+ subject="new dev site for syno dsm 5.0"
+ date="2014-03-25T10:20:46Z"
+ content="""
+There is a new website with documentation to create App for new synology dsm 5.0 here : http://www.synology.com/en-us/support/developer
+A good way to distribute git annex to lot of people ? :)
+"""]]
diff --git a/doc/tips/automatically_adding_metadata.mdwn b/doc/tips/automatically_adding_metadata.mdwn
index c3f50bb39..e6d02defa 100644
--- a/doc/tips/automatically_adding_metadata.mdwn
+++ b/doc/tips/automatically_adding_metadata.mdwn
@@ -17,7 +17,7 @@ like photos, mp3s, etc.
Now any fields you list in metadata.extract to will be extracted and
stored when files are committed.
-To get a list of all possible fields, run: `extract -L | sed ' ' _`
+To get a list of all possible fields, run: `extract -L | sed 's/ /_/g'`
By default, if a git-annex already has a metadata field for a file,
its value will not be overwritten with metadata taken from files.
diff --git a/doc/tips/automatically_adding_metadata/comment_2_bd64a53914107bc000c887b4d4bdf6af._comment b/doc/tips/automatically_adding_metadata/comment_2_bd64a53914107bc000c887b4d4bdf6af._comment
new file mode 100644
index 000000000..13b3865e1
--- /dev/null
+++ b/doc/tips/automatically_adding_metadata/comment_2_bd64a53914107bc000c887b4d4bdf6af._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="2001:1928:1:9::1"
+ subject="comment 2"
+ date="2014-04-01T04:18:10Z"
+ content="""
+is there a way for this to be done globally, without having to install and configure the hook for each repository? it seems like a fairly useful feature that could be factored in git-annex itself (as opposed to be shipped as a shell script)...
+
+also, is there a way to retroactively parse the tags from existing files (as opposed to only new files added to the repo).
+
+thanks
+"""]]
diff --git a/doc/tips/file_manager_integration.mdwn b/doc/tips/file_manager_integration.mdwn
new file mode 100644
index 000000000..1a1a557fc
--- /dev/null
+++ b/doc/tips/file_manager_integration.mdwn
@@ -0,0 +1,100 @@
+Integrating git-annex and your file manager provides an easy way to select
+annexed files to get or drop.
+
+[[!toc]]
+
+## GNOME (nautilus)
+
+Recent git-annex comes with built-in nautilus integration. Just pick the
+action from the menu.
+
+[[!img assistant/nautilusmenu.png]]
+
+[[!img assistant/downloadnotification.png]]
+
+This is set up by making simple scripts in
+`~/.local/share/nautilus/scripts`, with names like "git-annex get"
+
+## KDE (Dolphin/Konqueror)
+
+Create a file `~/.kde4/share/kde4/services/ServiceMenus/git-annex.desktop` with the following contents:
+
+ [Desktop Entry]
+ Type=Service
+ ServiceTypes=all/allfiles
+ MimeType=all/all;
+ Actions=GitAnnexGet;GitAnnexDrop;
+ X-KDE-Priority=TopLevel
+ X-KDE-Submenu=Git-Annex
+ X-KDE-Icon=git-annex
+ X-KDE-ServiceTypes=KonqPopupMenu/Plugin
+
+ [Desktop Action GitAnnexGet]
+ Name=Get
+ Icon=git-annex
+ Exec=git-annex get --notify-start --notify-finish -- %U
+
+ [Desktop Action GitAnnexDrop]
+ Name=Drop
+ Icon=git-annex
+ Exec=git-annex drop --notify-start --notify-finish -- %U
+
+## XFCE (Thunar)
+
+XFCE uses the Thunar file manager, which can also be easily configured to allow for custom actions. Just go to the "Configure custom actions..." item in the "Edit" menu, and create a custom action for get and drop with the following commands:
+
+ git-annex drop --notify-start --notify-finish -- %F
+
+for drop, and for get:
+
+ git-annex drop --notify-start --notify-finish -- %F
+
+This gives me the resulting config on disk, in `.config/Thunar/uca.xml`:
+
+ <action>
+ <icon>git-annex</icon>
+ <name>git-annex get</name>
+ <unique-id>1396278104182858-3</unique-id>
+ <command>git-annex get --notify-start --notify-finish -- %F</command>
+ <description>get the files from a remote git annex repository</description>
+ <patterns>*</patterns>
+ <directories/>
+ <audio-files/>
+ <image-files/>
+ <other-files/>
+ <text-files/>
+ <video-files/>
+ </action>
+ <action>
+ <icon>git-annex</icon>
+ <name>git-annex drop</name>
+ <unique-id>1396278093174843-2</unique-id>
+ <command>git-annex drop --notify-start --notify-finish -- %F</command>
+ <description>drop the files from the local repository</description>
+ <patterns>*</patterns>
+ <directories/>
+ <audio-files/>
+ <image-files/>
+ <other-files/>
+ <text-files/>
+ <video-files/>
+ </action>
+
+The complete instructions on how to setup actions is [in the XFCE documentation](http://docs.xfce.org/xfce/thunar/custom-actions).
+
+## your file manager here
+
+Edit this page and add instructions!
+
+## general
+
+If your file manager can run a command on a file, it should be easy to
+integrate git-annex with it. A simple script will suffice:
+
+ #!/bun/sh
+ git-annex get --notify-start --notify-finish -- "$@"
+
+The --notify-start and --notify-stop options make git-annex display a
+desktop notification. This is useful to give the user an indication that
+their action took effect. Desktop notifications are currently only
+implenented for Linux.
diff --git a/doc/tips/googledriveannex/comment_1_ce7f2b04e83cc02d9dabb712f266e5cc._comment b/doc/tips/googledriveannex/comment_1_ce7f2b04e83cc02d9dabb712f266e5cc._comment
new file mode 100644
index 000000000..aac4a8e08
--- /dev/null
+++ b/doc/tips/googledriveannex/comment_1_ce7f2b04e83cc02d9dabb712f266e5cc._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmlnEK_po7A0xMC9Xdp0FdcBgYllsCORXM"
+ nickname="Johnny"
+ subject="Shared google drive on multiple hosts"
+ date="2014-03-14T16:40:11Z"
+ content="""
+I have now configured my Googledrive on Laptop1 according to the guide above, how do I add the same remote on Laptop2? It would be nice if this was described in the guide, include where the encryption keys are stored.
+
+"""]]
diff --git a/doc/tips/metadata_driven_views/comment_1_1d6793701fd8a1a66bae04662cf853ce._comment b/doc/tips/metadata_driven_views/comment_1_1d6793701fd8a1a66bae04662cf853ce._comment
new file mode 100644
index 000000000..808a332af
--- /dev/null
+++ b/doc/tips/metadata_driven_views/comment_1_1d6793701fd8a1a66bae04662cf853ce._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlFZFMFm-AapYAgV_V5X9HRJxWvhdiX9fY"
+ nickname="Reiner"
+ subject="comment 1"
+ date="2014-03-24T21:11:31Z"
+ content="""
+I have played around with views and found out that I can create new tags by creating directories in the view and that I can created files in those new directories that are not contained in the original working tree. The behavoiur of git annex in this behaviour is a bit strange.
+
+Assume for example you have a file \"foo\" with tag \"t1\" and switch to the tag view. Then create a directory \"t2\" and a file \"bar\" in it. Add the file, sync, and switch back to the master branch. If you enter the tag view again, the directory \"t2\" will be vanished, i.e. your newly created file is gone, too. This is not surprising, as the file has never been added to the original working tree. However, another \"git annex sync\" will restore the file.
+
+I am unsure what behaviour I would expect, maybe it shouldn't be possible to files to a view in the first place, or newly created files might be collected in a separate branch. On the other hand, it seems reasonable to add a new file with a new tag at the same time. Anyway, I found it confusing that I can seemingly lose a file like this. It took me a bit of time to figure out that another sync recovers the file.
+"""]]
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_19_33c19097b6f2b48dfe09ec4c8d952d06._comment b/doc/tips/using_gitolite_with_git-annex/comment_19_33c19097b6f2b48dfe09ec4c8d952d06._comment
new file mode 100644
index 000000000..636794aba
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_19_33c19097b6f2b48dfe09ec4c8d952d06._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnftLWVOF0DUdXr2HSW4IKzuqtW8V7X3YU"
+ nickname="Adrian"
+ subject="How can the git annex init command be called on the server?"
+ date="2014-03-25T06:58:56Z"
+ content="""
+The latest commit in the gitolite repository \"git-annex support, finally in master!\" looks really promissing. I'm currently using ubuntu trusty with updated gitolite3 package and the configuration provided by Khaije. One line needs to be changed: 'git-annex-shell' => 'ua', instead of 'git-annex-shell' =>1,
+
+However, one little detail is still open for me. I need to call the server side \"git annex init\" on the server (sudo su gitolite3; cd ~/repositories/testing.git && git annex init). I cannot find a way to initialize the server from client side. E.g. git annex init && git push --all is not enough. The man page describes git annex initremote for other server types but not for gitolite remotes. Wouldn't we need something similar for gitolite as well? Or is there a better solution which I do not recognize?
+
+"""]]
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_20_c82af00db3dd74ee9bfe12668e76e57b._comment b/doc/tips/using_gitolite_with_git-annex/comment_20_c82af00db3dd74ee9bfe12668e76e57b._comment
new file mode 100644
index 000000000..45ff960f4
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_20_c82af00db3dd74ee9bfe12668e76e57b._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 20"
+ date="2014-03-26T18:24:30Z"
+ content="""
+@Adrian, that's good news. It would be helpful if someone could update the top of this page to document how to use git-annex with the new version of gitolite.
+This is a wiki..
+
+You're not supposed to need to use initremote when dealing with normal git remotes. It seems that something got lost that automatically initialize the remote repository in this situation. I've fixed it so that it will be set up when `git-annex-shell configlist` is run.
+
+(@wayne, this fixes the problem you reported too..)
+"""]]
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index 79552298b..62224c3be 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -1,4 +1,4 @@
-This is git-annex's todo list. Link items to [[todo/done]] when done.
+This is git-annex's todo list. Link items to [[todo/done]] when done. A more complete [[design/roadmap/]] is also available.
[[!inline pages="./todo/* and !./todo/done and !link(done)
and !*/Discussion" actions=yes postform=yes show=0 archive=yes]]
diff --git a/doc/todo/Bittorrent-like_features.mdwn b/doc/todo/Bittorrent-like_features.mdwn
index 41988a422..1dfe2c627 100644
--- a/doc/todo/Bittorrent-like_features.mdwn
+++ b/doc/todo/Bittorrent-like_features.mdwn
@@ -29,6 +29,8 @@ Another thing, this would be completely trackerless. You just use remote groups
This was originally posted [[as a forum post|forum/Wishlist:_Bittorrent-like_transfers]] by [[users/GLITTAH]].
+Update: note how [[design/assistant/telehash/]] may be able to answer this specific use case.
+
Using an external client (addurl torrent support)
=================================================
diff --git a/doc/todo/Bittorrent-like_features/comment_5_194dd0e8404ea72af9fb6ff34b994998._comment b/doc/todo/Bittorrent-like_features/comment_5_194dd0e8404ea72af9fb6ff34b994998._comment
new file mode 100644
index 000000000..620c82e97
--- /dev/null
+++ b/doc/todo/Bittorrent-like_features/comment_5_194dd0e8404ea72af9fb6ff34b994998._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="2001:1928:1:9::1"
+ subject="comment 5"
+ date="2014-04-01T04:43:16Z"
+ content="""
+re #3, sure, magnet link support would be awesome as well but i'd prefer to start with something i could digest more easily.
+
+looking at the source, it seems to me that the [quvi implementation](http://source.git-annex.branchable.com/?p=source.git;a=commitdiff;h=46b6d75) could serve as an example as to how this would work. more particularly, there's this concept of a [downloader](http://source.git-annex.branchable.com/?p=source.git;a=commitdiff;h=46b6d75#patch5) that can be used to tap into `addurl` directly. there's a check to see if the downloader is supported, for example.
+
+so we would need:
+
+1. see if the URL / magnet link can be turned into a .torrent somehow
+2. figure out what the filename(s!) will be
+3. start the torrent and wait for its completion, ideally with some progress bar
+
+i asked around to see if transmission-remote could do this, because it would be nice if we could use an existing daemon (instead of having to rebootstrap the whole DHT at every download). so far, I can't see how it could be done cleanly - maybe we would need to use the simpler \"bittorrent\" commandline client, or maybe tap into libtorrent...
+
+in any case, one of the key problems here is that addurl assumes that the URL maps to a single file, not a directory full of file, which is the way bittorrent works. I am not sure how to fix that assumption.
+"""]]
diff --git a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn
index 01bec0e21..e224215fc 100644
--- a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn
+++ b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp.mdwn
@@ -1 +1,3 @@
One Problem I am having is that I could never get the xmpp pairing to work so whenever I switch machines I have to manually run sync once on the command line to get the changes. Is it possible to have a sync now button of some sort that will trigger a sync on the repos?
+
+> moved from forum; [[done]] --[[Joey]]
diff --git a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment
index a5f631d50..a5f631d50 100644
--- a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment
+++ b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_1_0d5c90eb0e8fe61b82a19c5fea343613._comment
diff --git a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment
index 41e05bf6e..41e05bf6e 100644
--- a/doc/forum/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment
+++ b/doc/todo/Feature_Request:_Sync_Now_Button_in_Webapp/comment_2_196552002d70390e8b52b4af61dca903._comment
diff --git a/doc/todo/New_special_remote_suggeston_-_clean_directory.mdwn b/doc/todo/New_special_remote_suggeston_-_clean_directory.mdwn
index 9fd3c5a20..98dd58d5e 100644
--- a/doc/todo/New_special_remote_suggeston_-_clean_directory.mdwn
+++ b/doc/todo/New_special_remote_suggeston_-_clean_directory.mdwn
@@ -13,3 +13,11 @@ This special remote could be thought of as the 'least common denominator of spec
First and foremost, this can't be (really really shouldn't be) a trusted remote; my wife could accidentally delete all files on the NAS while I am away. So my local git-annex shouldn't assume the NAS counts towards numcopies (unless I'm a real masochist).
Secondly, what to do when files change/are added/removed on the special remote? Probably the same thing that the assistant does with everything. The only thing special is that new/modified files will need to be copied locally from this special remote before being added to the annex (to get hash and such).
+
+> This is not feaisble given git-annex's design. If I wanted to
+> make something completely unlike git-annex, I suppose it could be done,
+> but it's off topic here. [[wontfix|done]].
+>
+> If you want to use git-annex on a Synology NAS, the arm standalone build
+> will work, and then you can use the command-line, or the assistant
+> to maintain a git repository that contains your files as desired. --[[Joey]]
diff --git a/doc/todo/Views_Demo.mdwn b/doc/todo/Views_Demo.mdwn
index 2587642e3..54704afa6 100644
--- a/doc/todo/Views_Demo.mdwn
+++ b/doc/todo/Views_Demo.mdwn
@@ -11,3 +11,5 @@ So, are you considering a metadata syntax that can support complex metadata? One
FWIW,
Bob
+
+> [[closing|done]]; requested feature was already present --[[Joey]]
diff --git a/doc/todo/Wishlist:_additional_environment_variables_for_hooks/comment_1_d82cbbb478a81a651fbe6cb8b71c1192._comment b/doc/todo/Wishlist:_additional_environment_variables_for_hooks/comment_1_d82cbbb478a81a651fbe6cb8b71c1192._comment
new file mode 100644
index 000000000..4d0409d58
--- /dev/null
+++ b/doc/todo/Wishlist:_additional_environment_variables_for_hooks/comment_1_d82cbbb478a81a651fbe6cb8b71c1192._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T19:36:08Z"
+ content="""
+Is this still relevant?
+"""]]
diff --git a/doc/todo/add_a_--branch_to_applicable_git-annex_commands.mdwn b/doc/todo/add_a_--branch_to_applicable_git-annex_commands.mdwn
new file mode 100644
index 000000000..b2678bee8
--- /dev/null
+++ b/doc/todo/add_a_--branch_to_applicable_git-annex_commands.mdwn
@@ -0,0 +1,2 @@
+My original use case was for using git-annex find from scripts, where I didn't want to depend on the branch
+checked out at the time, but rather write something like "git annex find --branch=master $searchterms"
diff --git a/doc/todo/add_a_--branch_to_applicable_git-annex_commands/comment_1_3e0a1d1c41f317514dfc496f2274ad1c._comment b/doc/todo/add_a_--branch_to_applicable_git-annex_commands/comment_1_3e0a1d1c41f317514dfc496f2274ad1c._comment
new file mode 100644
index 000000000..6d5320d41
--- /dev/null
+++ b/doc/todo/add_a_--branch_to_applicable_git-annex_commands/comment_1_3e0a1d1c41f317514dfc496f2274ad1c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-17T19:48:57Z"
+ content="""
+The difficulty with adding a --branch is that if it causes git-annex to operate on a list of (file, key) from the branch, then commands that actually modify the working tree would modify it, instead of the branch. So the options seem to be only generating a list of keys, and so only letting commands that operate on keys work (which rules out the `git annex find` example), or carefully arranging for commands that actually affect the work tree to not be usable with this option.
+
+I'm not sure how many commands are affected. The ones I can immediately think of are sync, lock, unlock. (Commands like get obviously affect the work tree in direct mode, but it's fine to have getting a file from a branch also update files in the work tree, if they pointed at the same key.)
+"""]]
diff --git a/doc/todo/add_an_icon_for_the_.desktop_file.mdwn b/doc/todo/add_an_icon_for_the_.desktop_file.mdwn
index 3be158a0a..56428ff4b 100644
--- a/doc/todo/add_an_icon_for_the_.desktop_file.mdwn
+++ b/doc/todo/add_an_icon_for_the_.desktop_file.mdwn
@@ -1 +1,3 @@
Maybe add the icon /usr/share/doc/git-annex/html/logo.svg to the .desktp file.
+
+> [[done]] long ago.. --[[Joey]]
diff --git a/doc/todo/assistant_parallel_file_transfers.txt b/doc/todo/assistant_parallel_file_transfers.mdwn
index aafddf038..aafddf038 100644
--- a/doc/todo/assistant_parallel_file_transfers.txt
+++ b/doc/todo/assistant_parallel_file_transfers.mdwn
diff --git a/doc/todo/clear_file_names_in_special_remotes.mdwn b/doc/todo/clear_file_names_in_special_remotes.mdwn
new file mode 100644
index 000000000..1b6a9f935
--- /dev/null
+++ b/doc/todo/clear_file_names_in_special_remotes.mdwn
@@ -0,0 +1,13 @@
+To properly use amazon AWS S3 for CDN, we need to publish videos to S3. Ideally, we would like to do this via git-annex as the back-end of video.debian.net is being migrated to git-annex by me, atm.
+
+Obviously, we will need clear text names and proper directory structure, not SHA512E file names. This would need to be supported by the S3 special remote.
+
+I talked to TobiasTheViking in the past and he hinted at a reasonably clean way to do this, but that a clean solution would need support from git-annex. I will link him to this page and ask him to supply whatever info is needed.
+
+
+Thanks,
+Richard
+
+> This is not feaisble given git-annex's design. If I wanted to
+> make something completely unlike git-annex, I suppose it could be done,
+> but it's off topic here. [[wontfix|done]] --[[Joey]]
diff --git a/doc/todo/clear_file_names_in_special_remotes/comment_1_630f17c9a7ce9a77d5d5867a6e0c799b._comment b/doc/todo/clear_file_names_in_special_remotes/comment_1_630f17c9a7ce9a77d5d5867a6e0c799b._comment
new file mode 100644
index 000000000..7ca8e1916
--- /dev/null
+++ b/doc/todo/clear_file_names_in_special_remotes/comment_1_630f17c9a7ce9a77d5d5867a6e0c799b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 1"
+ date="2014-03-26T17:26:37Z"
+ content="""
+I don't see how this can possibly be done. A single git-annex object can have any number of file names, which can change at any time.
+"""]]
diff --git a/doc/todo/clear_file_names_in_special_remotes/comment_2_823c279683ac3f39c921be3fcbf6bfe2._comment b/doc/todo/clear_file_names_in_special_remotes/comment_2_823c279683ac3f39c921be3fcbf6bfe2._comment
new file mode 100644
index 000000000..b7f5a409e
--- /dev/null
+++ b/doc/todo/clear_file_names_in_special_remotes/comment_2_823c279683ac3f39c921be3fcbf6bfe2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 2"
+ date="2014-03-26T22:32:18Z"
+ content="""
+In that case, we would need to export the same file name several times, just like direct mode does.
+
+Could files be tracked via metadata? And yes, fsck would be... interesting...
+"""]]
diff --git a/doc/todo/clear_file_names_in_special_remotes/comment_3_4704e465025b543e47c18d565abd2747._comment b/doc/todo/clear_file_names_in_special_remotes/comment_3_4704e465025b543e47c18d565abd2747._comment
new file mode 100644
index 000000000..a925cb2de
--- /dev/null
+++ b/doc/todo/clear_file_names_in_special_remotes/comment_3_4704e465025b543e47c18d565abd2747._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.41"
+ subject="comment 3"
+ date="2014-03-27T17:44:46Z"
+ content="""
+Sounds like \"I want a pony to me\".
+"""]]
diff --git a/doc/todo/openwrt_package.txt b/doc/todo/openwrt_package.mdwn
index 70a4ae03f..70a4ae03f 100644
--- a/doc/todo/openwrt_package.txt
+++ b/doc/todo/openwrt_package.mdwn
diff --git a/doc/todo/required_content.mdwn b/doc/todo/required_content.mdwn
index 851e652ae..6afeee5c9 100644
--- a/doc/todo/required_content.mdwn
+++ b/doc/todo/required_content.mdwn
@@ -5,3 +5,19 @@ like preferred content, which is enforced. So, required content.
For example, I might want a repository that is required to contain
`*.jpeg`. This would make get --auto get it (it's implicitly part of the
preferred content), and would make drop refuse to drop it.
+
+> I've implemented the basic required content. Currently only configurable
+> via `vicfg`, because I don't think a lot of people are going to want to
+> use it.
+>
+> Note that I did not yet add the active verification discussed below.
+> So if required content is set to `not inallgroup=backup`, or
+> `not copies=10`, trying to drop a file will not go off and prove
+> that there are 10 copies or that the file is in every repository in
+> the backup group. It will assume that the location log is accurate
+> and go by that.
+>
+> I think this is enough to cover Richard's case, at least.
+> In his example, A B and C are in group anchor and have required
+> content set to `include=*`, and D E F have it set to
+> `not inallgroup=anchor`. --[[Joey]]
diff --git a/doc/todo/required_content/comment_2_132ec6378db63af6281569cf5748b9d3._comment b/doc/todo/required_content/comment_2_132ec6378db63af6281569cf5748b9d3._comment
new file mode 100644
index 000000000..dece48c01
--- /dev/null
+++ b/doc/todo/required_content/comment_2_132ec6378db63af6281569cf5748b9d3._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="partial implementation plan"
+ date="2014-03-19T16:37:05Z"
+ content="""
+* When there is a required content expression, OR it with the preferred content expression. This will make the assistant, --auto etc want to get required content.
+* When checking if something can be dropped, check the required content expression. Only Command.Drop does this so nicely centralized in one place.
+* When checking required content expression for drop, must do active verification of terminals that relate to other copies, for the same reason the numcopies check when dropping does active validation. This includes `copies=`, `lackingcopies=`, `approxlackingcopies=`, `inallgroup=`.
+
+The last is where the complication comes in. Seems to need a cache of places the key was just now verified to be present, which can be used to avoid unnecessary redundant active verification (for example \"not (copies=2 and inallgroup=bar)\" would otherwise redundantly check some remotes). The numcopies checking code should use the same cache too.
+
+* Finally, if the required content cannot be satisfied, it would be nice to know which terminal failed in order to show the user a useful error message. The current Matcher does not provide a way to do that though. Or could just say, \"unable to satisfy required content: $expression\"
+"""]]
diff --git a/doc/todo/tahoe_lfs_for_reals.mdwn b/doc/todo/tahoe_lfs_for_reals.mdwn
index e5b4a841d..2caeef11d 100644
--- a/doc/todo/tahoe_lfs_for_reals.mdwn
+++ b/doc/todo/tahoe_lfs_for_reals.mdwn
@@ -12,10 +12,12 @@ but a tahoe-lafs special remote would be more flexible.
To support a special remote, a mapping is needed from git-annex keys to
Tahoe keys, stored in the git-annex branch.
-> This is now done, however, there are 2 known
+> This is now done, however, there are 3 known
> problems:
>
> * tahoe start run unncessarily <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2149>
> * web.port can conflict <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2147>
->
+> * Nothing renews leases, which is a problem on grids that expire.
+> <https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2212>
+
> --[[Joey]]
diff --git a/doc/todo/union_mounting/comment_3_cf0a0d4fbd929f24f7056115b2acb7de._comment b/doc/todo/union_mounting/comment_3_cf0a0d4fbd929f24f7056115b2acb7de._comment
new file mode 100644
index 000000000..ae925adf0
--- /dev/null
+++ b/doc/todo/union_mounting/comment_3_cf0a0d4fbd929f24f7056115b2acb7de._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://ypid.wordpress.com/"
+ nickname="ypid"
+ subject="Please add this ;)"
+ date="2014-03-13T19:10:17Z"
+ content="""
++1 This would be so great. For me the only thing which is missing in this awesome project.
+"""]]
diff --git a/doc/todo/using_file_metadata_for_preferred___40__wanted__41___content.mdwn b/doc/todo/using_file_metadata_for_preferred___40__wanted__41___content.mdwn
new file mode 100644
index 000000000..d9226d21f
--- /dev/null
+++ b/doc/todo/using_file_metadata_for_preferred___40__wanted__41___content.mdwn
@@ -0,0 +1,12 @@
+Having the option of choosing for every file if we want it in our repository or not would be a great feature. It is currently possible using the wanted expression, but it is not very flexible, or it becomes unmaintainable.
+
+I tried with two repositories a and b, with the following wanted expressions :
+
+* for a: `not metadata=unwanted=<uuid-of-a>`
+* for b: `not metadata=unwanted=<uuid-of-b>`
+
+I think those expressions should be included in standard wanted expressions.
+
+Also, to improbe the feature, it should be possible to set (or remove) metadata in directories, and those should automatically affect their content.
+
+And we could imagine a `git annex unwant` command that would add the unwanted metadata to a file, copy it to other repositories, and attempt to drop it.
diff --git a/doc/todo/windows_support.mdwn b/doc/todo/windows_support.mdwn
index 17accd62e..0afcbb4fe 100644
--- a/doc/todo/windows_support.mdwn
+++ b/doc/todo/windows_support.mdwn
@@ -29,6 +29,42 @@ now! --[[Joey]]
* Deleting a git repository from inside the webapp fails "RemoveDirectory
permision denied ... file is being used by another process"
+## potential encoding problems
+
+[[bugs/Unicode_file_names_ignored_on_Windows]] is fixed, but some potential
+problems remain, since the FileSystemEncoding that git-annex relies on
+seems unreliable/broken on Windows.
+
+* When git-annex displays a filename that it's acting on, there
+ can be mojibake on Windows. For example, "háčky.txt" displays
+ the accented characters as instead the pairs of bytes making
+ up the utf-8. Tried doing various things to the stdout handle
+ to avoid this, but only ended up with encoding crashes, or worse
+ mojibake than this.
+
+* `md5FilePath` still uses the filesystem encoding, and so may produce the
+ wrong value on Windows. This would impact keys that contain problem characters
+ (probably coming from the filename extension), and might cause
+ interoperability problems when git-annex generates the hash directories of a
+ remote, for example a rsync remote.
+
+* `encodeW8` is used in Git.UnionMerge, and while I fixed the other calls to
+ encodeW8, which all involved ByteStrings reading from git and so can just
+ treat it as utf-8 on Windows (via `decodeBS`), in the union merge case,
+ the ByteString has no defined encoding. It may have been written on Unix
+ and contain keys with invalid unicode in them. On windows, the union
+ merge code should probably check if it's valid utf-8, and if not,
+ abort the merge.
+
+* If interoperating with a git-annex repository from a unix system, it's
+ possible for a key to contain some invalid utf-8, which means its filename
+ cannot even be represented on Windows, so who knows what will happen in that
+ case -- probably it will fail in some way when adding the object file
+ to the Windows repo.
+
+* If data from the git repo does not have a unicode encoding, it will be
+ mangled in various places on Windows, which can lead to undefined behavior.
+
## minor problems
* rsync special remotes with a rsyncurl of a local directory are known
@@ -91,3 +127,5 @@ Options:
of lots of yesod dependency chain to export modules referenced by TH
splices, like had to be done on Android. Horrible pain. Ugly as hell.
2. Make a helper program with the XMPP support in it, that does not use TH.
+3. Swich to a different XMPP client library, like
+ <http://hackage.haskell.org/package/pontarius-xmpp>
diff --git a/doc/todo/wishlist:_An_option_like_--git-dir.mdwn b/doc/todo/wishlist:_An_option_like_--git-dir.mdwn
index cb9d374b3..0582d9892 100644
--- a/doc/todo/wishlist:_An_option_like_--git-dir.mdwn
+++ b/doc/todo/wishlist:_An_option_like_--git-dir.mdwn
@@ -1,3 +1,5 @@
I'm currently integrating git-annex support into a filesystem synchronization tool that I use, and I have a use case where I'd like to run "git annex sync' on a local directory, and then automatically ssh over to remote hosts and run "git annex sync" in the related annex on that remote host. However, while I can easily "cd" on the local, there is no really easy way to "cd" on the remote without a hack.
If I could say: git annex --annex-dir=PATH sync, where PATH is the annex directory, it would solve all my problems, and would also provide a nice correlation to the --git-dir option used by most Git commands. The basic idea is that I shouldn't have to be IN the directory to run git-annex commands, I should be able to tell git-annex which directory to apply its commands to.
+
+> AFAIK this is fully supported for some time, so [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_a_spec.remote_for_network_directories_that_would_mount_them_whenever_needed___40__e.g.__44___with_WebDAV__41__.mdwn b/doc/todo/wishlist:_a_spec.remote_for_network_directories_that_would_mount_them_whenever_needed___40__e.g.__44___with_WebDAV__41__.mdwn
index f2c4254ad..df589be93 100644
--- a/doc/todo/wishlist:_a_spec.remote_for_network_directories_that_would_mount_them_whenever_needed___40__e.g.__44___with_WebDAV__41__.mdwn
+++ b/doc/todo/wishlist:_a_spec.remote_for_network_directories_that_would_mount_them_whenever_needed___40__e.g.__44___with_WebDAV__41__.mdwn
@@ -23,3 +23,7 @@ whenever I wanted to update the revisions of the textbooks (or to download them
So, this differs from [[tips/using box.com as a special remote]] in that the tip for WebDAV suggest to handle the mounting manually, and git-annex knows nothing about the WebDAV URL where the content comes from.
So here's my wish: a [[special remote|special remotes]] to track the WebDAV URLs in the repo, and mount the remote directory automatically under the hood, whenever one wants to get a file from there. (Then I assume it should also unmount it immediately in order to clean up after itself, despite possible inefficiencies).
+
+> I think the hooks are enough.. If not, you can use a hook special remote
+> or the external special remote protocol to make your own custom special
+> remote. So, [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_assistant_autostart_port_and_secret_configuration.mdwn b/doc/todo/wishlist:_assistant_autostart_port_and_secret_configuration.mdwn
index f0d27d0b1..a1aec1d49 100644
--- a/doc/todo/wishlist:_assistant_autostart_port_and_secret_configuration.mdwn
+++ b/doc/todo/wishlist:_assistant_autostart_port_and_secret_configuration.mdwn
@@ -1 +1,4 @@
When starting the assistant when logging in to the system (`--autostart`) it choses a new port an secret everytime. Having the assistant open in a pinned firefox tab which automatically restores when firefox starts we need to get the url from `.git/annex/url` and copy/paste it into the pinned tab. It would be very nice to have a configuration option which assigns a fixed port and secret so everytime the assistant is autostarted it uses the same settings and firefox is happy to open it automatically on start.
+
+> Closing, I've removed the option to choose webapp ports entirely.
+> [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_define_remotes_that_must_have_all_files.mdwn b/doc/todo/wishlist:_define_remotes_that_must_have_all_files.mdwn
index 156cfb009..a3beaadae 100644
--- a/doc/todo/wishlist:_define_remotes_that_must_have_all_files.mdwn
+++ b/doc/todo/wishlist:_define_remotes_that_must_have_all_files.mdwn
@@ -16,3 +16,7 @@ Based on existing output, this is what a warning message could look like:
Warning
What do you think?
+
+> I think that [[required_content]] will make it easy to configure
+> such remotes, so this is another reason to build that. Closing
+> this bug as a dup of that one; [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_git-annex_replicate.mdwn b/doc/todo/wishlist:_git-annex_replicate.mdwn
index 0d926b337..9ac6ade75 100644
--- a/doc/todo/wishlist:_git-annex_replicate.mdwn
+++ b/doc/todo/wishlist:_git-annex_replicate.mdwn
@@ -10,3 +10,13 @@ There might be the need to have a 'replication_priority' option for each remote
* maxspace - A self imposed quota per remote machine. git-annex replicate should try to replicate files first to machines with more free space. maxspace would change the free space calculation to be `min(actual_free_space, maxspace - space_used_by_git_annex)
* bandwidth - when replication files, copies should be done between machines with the highest available bandwidth. ( I think this option could be useful for git-annex get in general)
+
+> `git annex sync --content` handles this now. [[done]]
+>
+> You do need to run it, or the assistant, on each node that needs
+> to copy files to spread them through the network.
+>
+> A `git annex rebalance`
+> is essentially the same as sshing to the remote and running `git annex
+> sync --content` there. Assuming the remote repository itself has enough
+> remotes set up that git-annex is able to copy files around. --[[Joey]]
diff --git a/doc/todo/wishlist:_git_annex_diff/comment_1_16ccf2e1036d9e1a913db81988731b5a._comment b/doc/todo/wishlist:_git_annex_diff/comment_1_16ccf2e1036d9e1a913db81988731b5a._comment
new file mode 100644
index 000000000..86772e2fd
--- /dev/null
+++ b/doc/todo/wishlist:_git_annex_diff/comment_1_16ccf2e1036d9e1a913db81988731b5a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T20:00:16Z"
+ content="""
+`git diff` is quite flexible; it can use external diff drivers to perform the diff. Someone could write a diff driver that knows about git-annex symlinks, and shows some kind of diff of the file contents (since the files are probably binary, this gets into how to display a diff of different file types..)
+"""]]
diff --git a/doc/todo/wishlist:_make_partial_files_available_during_transfer/comment_2_8b1cfae6f2b61929a9c6f48ae63c921d._comment b/doc/todo/wishlist:_make_partial_files_available_during_transfer/comment_2_8b1cfae6f2b61929a9c6f48ae63c921d._comment
new file mode 100644
index 000000000..c4c222431
--- /dev/null
+++ b/doc/todo/wishlist:_make_partial_files_available_during_transfer/comment_2_8b1cfae6f2b61929a9c6f48ae63c921d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 2"
+ date="2014-03-18T20:08:13Z"
+ content="""
+There's now an easy way to do this:
+
+ git annex find --include=* --format='.git/annex/tmp/${hashdirmixed}${key}/${key}\n'
+
+Pass it the file or files you're interested in to get their partially transferred contents.
+"""]]
diff --git a/doc/todo/wishlist:_metadata_metadata_view.mdwn b/doc/todo/wishlist:_metadata_metadata_view.mdwn
new file mode 100644
index 000000000..a4b243cdd
--- /dev/null
+++ b/doc/todo/wishlist:_metadata_metadata_view.mdwn
@@ -0,0 +1,23 @@
+Currently looking at the metadata and views.
+
+One of the things I would like to do is have a view that shows files by metadata metadata.. for example, "when the file last had tags changed".
+
+Something along the lines of
+
+ $ git annex view metadata-tag-mtime=YYYYMMDD
+ view (searching...)
+
+ Switched to branch 'views/metadata/tag/mtime/YYYYMMDD'
+ ok
+
+ $ ls
+ 20130816
+ 20130921
+ 20131015
+
+This would allow me to review files that haven't had any tag changes applied for a while and thus, may need the tags updating.
+
+I've done this in every tagging system I've used by (ab)using mtime, but that requires an additional step (of touching the file).
+
+> [[done]]; "$field-lastchanged" is automatically made available for each
+> field! --[[Joey]]
diff --git a/doc/todo/wishlist:_metadata_metadata_view/comment_1_79dbf48cf2e0d649f32bd077f0c9bc5a._comment b/doc/todo/wishlist:_metadata_metadata_view/comment_1_79dbf48cf2e0d649f32bd077f0c9bc5a._comment
new file mode 100644
index 000000000..126a9148c
--- /dev/null
+++ b/doc/todo/wishlist:_metadata_metadata_view/comment_1_79dbf48cf2e0d649f32bd077f0c9bc5a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T17:09:55Z"
+ content="""
+I think this would be pretty easy to do actually. No need to trawl through git history to find when a field changed; the metadata log file format includes the timestamp when a line was changed, so it would only need to find the newest timestamp for the field in the current version of the file.
+"""]]
diff --git a/doc/todo/wishlist:_metadata_metadata_view/comment_2_5763d0e403c476ac692c1cd50630f824._comment b/doc/todo/wishlist:_metadata_metadata_view/comment_2_5763d0e403c476ac692c1cd50630f824._comment
new file mode 100644
index 000000000..8b3fc3108
--- /dev/null
+++ b/doc/todo/wishlist:_metadata_metadata_view/comment_2_5763d0e403c476ac692c1cd50630f824._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Xyem"
+ ip="87.194.19.134"
+ subject="comment 2"
+ date="2014-03-19T11:18:19Z"
+ content="""
+Can $field be a glob? i.e. *
+
+I'm looking for the files to be organised to the last change date to *any* metadata, not a specific field.
+
+For example, I may have added some vacation photos and set some metadata (location=Malta), a couple of months later, gone through and added metadata to some of them (person=Susan, event=Wedding Reception). 3 months later, I want to see a directory containing those that were initially added and metadata'd(?) with \"location=Malta\" and not touched since, and another showing those that had gotten additional metadata so I know which ones I should be looking at.
+"""]]
diff --git a/doc/todo/wishlist:_metadata_metadata_view/comment_3_797e6578c60d8e2ed1f61a8d6403575f._comment b/doc/todo/wishlist:_metadata_metadata_view/comment_3_797e6578c60d8e2ed1f61a8d6403575f._comment
new file mode 100644
index 000000000..aff5afbcf
--- /dev/null
+++ b/doc/todo/wishlist:_metadata_metadata_view/comment_3_797e6578c60d8e2ed1f61a8d6403575f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.102"
+ subject="comment 3"
+ date="2014-03-19T23:14:24Z"
+ content="""
+I added a toplevel \"lastchanged\" that applies to all the fields. (Also when the last change was unsetting a field, the toplevel lastchanged will show the time of that which is otherwise not visible by collecting the lastchanged-* fields).
+"""]]
diff --git a/doc/todo/wishlist:_metadata_metadata_view/comment_4_d271fe711b3fe5ffeb52f1caf44622b3._comment b/doc/todo/wishlist:_metadata_metadata_view/comment_4_d271fe711b3fe5ffeb52f1caf44622b3._comment
new file mode 100644
index 000000000..4bc147c4e
--- /dev/null
+++ b/doc/todo/wishlist:_metadata_metadata_view/comment_4_d271fe711b3fe5ffeb52f1caf44622b3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Xyem"
+ ip="87.194.19.134"
+ subject="comment 4"
+ date="2014-03-20T08:14:20Z"
+ content="""
+Awesome! :)
+
+Thank you for adding this, I hope others find it as useful as I will.
+"""]]
diff --git a/doc/todo/wishlist:_spec.remotes_for_other_peer_network_data_stores___40__gnunet__44___freenet__41__/comment_3_b4ff519ece76c6c3fb29b981320e2e1c._comment b/doc/todo/wishlist:_spec.remotes_for_other_peer_network_data_stores___40__gnunet__44___freenet__41__/comment_3_b4ff519ece76c6c3fb29b981320e2e1c._comment
new file mode 100644
index 000000000..dac333174
--- /dev/null
+++ b/doc/todo/wishlist:_spec.remotes_for_other_peer_network_data_stores___40__gnunet__44___freenet__41__/comment_3_b4ff519ece76c6c3fb29b981320e2e1c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 3"
+ date="2014-03-18T19:49:09Z"
+ content="""
+The new [[special_remotes/external]] special remote's protocol has GETSTATE and SETSTATE commands that can be used to store per-remote values in the git-annex branch.
+
+So, please go make these special remotes using it!
+"""]]
diff --git a/doc/todo/wishlist:_special_remote_Ubuntu_One/comment_1_ab0c761030bc55e8fb75d1b344bb98b9._comment b/doc/todo/wishlist:_special_remote_Ubuntu_One/comment_1_ab0c761030bc55e8fb75d1b344bb98b9._comment
new file mode 100644
index 000000000..4fb9bc95e
--- /dev/null
+++ b/doc/todo/wishlist:_special_remote_Ubuntu_One/comment_1_ab0c761030bc55e8fb75d1b344bb98b9._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T20:02:14Z"
+ content="""
+I suggest that if someone wants to build this, they use the new external special remote protocol to do it.
+"""]]
diff --git a/doc/todo/wishlist:alias_system/comment_1_5afad4b92f9a449d4a82a94ad31feec2._comment b/doc/todo/wishlist:alias_system/comment_1_5afad4b92f9a449d4a82a94ad31feec2._comment
new file mode 100644
index 000000000..ea8f2bd30
--- /dev/null
+++ b/doc/todo/wishlist:alias_system/comment_1_5afad4b92f9a449d4a82a94ad31feec2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.154"
+ subject="comment 1"
+ date="2014-03-18T19:38:19Z"
+ content="""
+Why not just use git's alias system? It can't make `git annex $foo` aliases, but `git $foo` is shorter anyway..
+"""]]
diff --git a/git-annex.cabal b/git-annex.cabal
index a98e3e34a..9a46077b1 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
Name: git-annex
-Version: 5.20140306
+Version: 5.20140402
Cabal-Version: >= 1.8
License: GPL-3
Maintainer: Joey Hess <joey@kitenet.net>
@@ -7,6 +7,7 @@ Author: Joey Hess
Stability: Stable
Copyright: 2010-2014 Joey Hess
License-File: COPYRIGHT
+Extra-Source-Files: CHANGELOG
Homepage: http://git-annex.branchable.com/
Build-type: Custom
Category: Utility
@@ -43,8 +44,8 @@ Flag Assistant
Flag Webapp
Description: Enable git-annex webapp
-Flag Webapp-https
- Description: Enable git-annex webapp https
+Flag Webapp-secure
+ Description: Secure webapp
Flag Pairing
Description: Enable pairing
@@ -84,6 +85,9 @@ Flag Tahoe
Flag CryptoHash
Description: Enable use of cryptohash for checksumming
+Flag DesktopNotify
+ Description: Enable desktop environment notifications
+
Flag EKG
Description: Enable use of EKG to monitor git-annex as it runs (at http://localhost:4242/)
Default: False
@@ -166,10 +170,16 @@ Executable git-annex
CPP-Options: -DWITH_KQUEUE
C-Sources: Utility/libkqueue.c
- if os(linux) && flag(Dbus)
- Build-Depends: dbus (>= 0.10.3)
- CPP-Options: -DWITH_DBUS
+ if (os(linux))
+ if flag(Dbus)
+ Build-Depends: dbus (>= 0.10.3)
+ CPP-Options: -DWITH_DBUS
+ if flag(DesktopNotify)
+ if flag(Dbus)
+ Build-Depends: dbus (>= 0.10.3), fdo-notify (>= 0.3)
+ CPP-Options: -DWITH_DESKTOP_NOTIFY -DWITH_DBUS_NOTIFICATIONS
+
if flag(Android)
Build-Depends: data-endian
CPP-Options: -D__ANDROID__ -DANDROID_SPLICES -D__NO_TH__
@@ -183,9 +193,9 @@ Executable git-annex
blaze-builder, crypto-api, hamlet, clientsession,
template-haskell, data-default, aeson, network-conduit
CPP-Options: -DWITH_WEBAPP
- if flag(Webapp) && flag (Webapp-https)
- Build-Depends: warp-tls (>= 1.4)
- CPP-Options: -DWITH_WEBAPP_HTTPS
+ if flag(Webapp) && flag (Webapp-secure)
+ Build-Depends: warp-tls (>= 1.4), securemem, byteable
+ CPP-Options: -DWITH_WEBAPP_SECURE
if flag(Pairing)
Build-Depends: network-multicast, network-info