aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2013-11-14 17:04:58 -0400
committerGravatar Joey Hess <joey@kitenet.net>2013-11-14 17:04:58 -0400
commit521ef9dfebd6a9418a5dce7d1686dbf353ddd0a0 (patch)
treeafe6bb5d52e21a049f04020ae448afb81adc02a7
parentf4b4f327b69189d24663a7db6407c1f7a6e48fdd (diff)
parent5c6f6e4d0abb9b4856908a500611044b3b7a48e6 (diff)
Merge branch 'master' into tasty-tests
Conflicts: Test.hs
-rw-r--r--.gitignore11
-rw-r--r--Annex.hs29
-rw-r--r--Annex/Branch.hs316
-rw-r--r--Annex/Branch/Transitions.hs53
-rw-r--r--Annex/CatFile.hs75
-rw-r--r--Annex/CheckIgnore.hs2
-rw-r--r--Annex/Content.hs35
-rw-r--r--Annex/Content/Direct.hs4
-rw-r--r--Annex/Direct.hs95
-rw-r--r--Annex/Environment.hs2
-rw-r--r--Annex/Exception.hs7
-rw-r--r--Annex/FileMatcher.hs1
-rw-r--r--Annex/Hook.hs42
-rw-r--r--Annex/Journal.hs54
-rw-r--r--Annex/Link.hs6
-rw-r--r--Annex/Quvi.hs20
-rw-r--r--Annex/Ssh.hs51
-rw-r--r--Annex/TaggedPush.hs8
-rw-r--r--Annex/UUID.hs22
-rw-r--r--Annex/Url.hs27
-rw-r--r--Annex/Version.hs18
-rw-r--r--Annex/Wanted.hs2
-rw-r--r--Assistant.hs25
-rw-r--r--Assistant/Alert.hs91
-rw-r--r--Assistant/DaemonStatus.hs7
-rw-r--r--Assistant/DeleteRemote.hs15
-rw-r--r--Assistant/MakeRemote.hs62
-rw-r--r--Assistant/Monad.hs3
-rw-r--r--Assistant/NamedThread.hs27
-rw-r--r--Assistant/NetMessager.hs4
-rw-r--r--Assistant/Pairing.hs2
-rw-r--r--Assistant/Pairing/MakeRemote.hs10
-rw-r--r--Assistant/RepoProblem.hs34
-rw-r--r--Assistant/Ssh.hs83
-rw-r--r--Assistant/Sync.hs60
-rw-r--r--Assistant/Threads/Committer.hs31
-rw-r--r--Assistant/Threads/ConfigMonitor.hs23
-rw-r--r--Assistant/Threads/Cronner.hs225
-rw-r--r--Assistant/Threads/Glacier.hs2
-rw-r--r--Assistant/Threads/Merger.hs4
-rw-r--r--Assistant/Threads/MountWatcher.hs45
-rw-r--r--Assistant/Threads/NetWatcher.hs6
-rw-r--r--Assistant/Threads/PairListener.hs38
-rw-r--r--Assistant/Threads/ProblemFixer.hs70
-rw-r--r--Assistant/Threads/Pusher.hs5
-rw-r--r--Assistant/Threads/SanityChecker.hs43
-rw-r--r--Assistant/Threads/TransferScanner.hs19
-rw-r--r--Assistant/Threads/TransferWatcher.hs38
-rw-r--r--Assistant/Threads/Transferrer.hs117
-rw-r--r--Assistant/Threads/Watcher.hs37
-rw-r--r--Assistant/Threads/WebApp.hs7
-rw-r--r--Assistant/Threads/XMPPClient.hs26
-rw-r--r--Assistant/TransferSlots.hs208
-rw-r--r--Assistant/TransferrerPool.hs13
-rw-r--r--Assistant/Types/Alert.hs1
-rw-r--r--Assistant/Types/DaemonStatus.hs19
-rw-r--r--Assistant/Types/NamedThread.hs8
-rw-r--r--Assistant/Types/RepoProblem.hs28
-rw-r--r--Assistant/XMPP.hs2
-rw-r--r--Backend.hs4
-rw-r--r--Backend/Hash.hs168
-rw-r--r--Backend/SHA.hs146
-rw-r--r--Backend/URL.hs17
-rw-r--r--Backend/Utilities.hs25
-rw-r--r--Backend/WORM.hs14
-rw-r--r--Build/BundledPrograms.hs9
-rw-r--r--Build/Configure.hs62
-rw-r--r--Build/EvilSplicer.hs59
-rw-r--r--Build/OSXMkLibs.hs2
-rw-r--r--Build/Version.hs69
-rwxr-xr-xBuild/mdwn2man3
-rw-r--r--BuildFlags.hs15
-rw-r--r--Command.hs2
-rw-r--r--Command/Add.hs88
-rw-r--r--Command/AddUnused.hs2
-rw-r--r--Command/AddUrl.hs101
-rw-r--r--Command/Assistant.hs41
-rw-r--r--Command/ConfigList.hs7
-rw-r--r--Command/Copy.hs5
-rw-r--r--Command/Direct.hs14
-rw-r--r--Command/Drop.hs2
-rw-r--r--Command/EnableRemote.hs6
-rw-r--r--Command/Fix.hs6
-rw-r--r--Command/Forget.hs52
-rw-r--r--Command/Fsck.hs16
-rw-r--r--Command/GCryptSetup.hs39
-rw-r--r--Command/Get.hs8
-rw-r--r--Command/Import.hs94
-rw-r--r--Command/ImportFeed.hs22
-rw-r--r--Command/Indirect.hs29
-rw-r--r--Command/Info.hs384
-rw-r--r--Command/InitRemote.hs17
-rw-r--r--Command/List.hs88
-rw-r--r--Command/Log.hs4
-rw-r--r--Command/Map.hs8
-rw-r--r--Command/Merge.hs6
-rw-r--r--Command/Mirror.hs58
-rw-r--r--Command/Move.hs13
-rw-r--r--Command/PreCommit.hs22
-rw-r--r--Command/ReKey.hs2
-rw-r--r--Command/RecvKey.hs19
-rw-r--r--Command/Reinject.hs2
-rw-r--r--Command/Repair.hs71
-rw-r--r--Command/Schedule.hs50
-rw-r--r--Command/SendKey.hs6
-rw-r--r--Command/Status.hs390
-rw-r--r--Command/Sync.hs272
-rw-r--r--Command/TransferInfo.hs2
-rw-r--r--Command/TransferKey.hs12
-rw-r--r--Command/TransferKeys.hs2
-rw-r--r--Command/Unannex.hs32
-rw-r--r--Command/Uninit.hs11
-rw-r--r--Command/Unused.hs71
-rw-r--r--Command/Upgrade.hs8
-rw-r--r--Command/Version.hs23
-rw-r--r--Command/Vicfg.hs35
-rw-r--r--Command/Wanted.hs (renamed from Command/Content.hs)6
-rw-r--r--Command/Watch.hs9
-rw-r--r--Command/WebApp.hs8
-rw-r--r--Common.hs1
-rw-r--r--Config.hs18
-rw-r--r--Config/Cost.hs2
-rw-r--r--Config/Files.hs2
-rw-r--r--Creds.hs12
-rw-r--r--Crypto.hs126
-rw-r--r--Git/Branch.hs38
-rw-r--r--Git/CatFile.hs81
-rw-r--r--Git/CheckAttr.hs39
-rw-r--r--Git/Command.hs30
-rw-r--r--Git/Config.hs40
-rw-r--r--Git/Construct.hs73
-rw-r--r--Git/DiffTree.hs31
-rw-r--r--Git/FileMode.hs23
-rw-r--r--Git/FilePath.hs6
-rw-r--r--Git/Fsck.hs87
-rw-r--r--Git/GCrypt.hs103
-rw-r--r--Git/HashObject.hs7
-rw-r--r--Git/Hook.hs54
-rw-r--r--Git/LsFiles.hs31
-rw-r--r--Git/LsTree.hs19
-rw-r--r--Git/Objects.hs29
-rw-r--r--Git/Queue.hs20
-rw-r--r--Git/Ref.hs29
-rw-r--r--Git/RefLog.hs22
-rw-r--r--Git/Remote.hs84
-rw-r--r--Git/Repair.hs534
-rw-r--r--Git/Types.hs14
-rw-r--r--Git/UpdateIndex.hs6
-rw-r--r--Git/Url.hs23
-rw-r--r--GitAnnex.hs27
-rw-r--r--GitAnnex/Options.hs36
-rw-r--r--GitAnnexShell.hs46
-rw-r--r--Init.hs98
-rw-r--r--Limit.hs8
-rw-r--r--Limit/Wanted.hs21
-rw-r--r--Locations.hs94
-rw-r--r--Logs.hs114
-rw-r--r--Logs/FsckResults.hs43
-rw-r--r--Logs/Group.hs5
-rw-r--r--Logs/Location.hs25
-rw-r--r--Logs/PreferredContent.hs7
-rw-r--r--Logs/Presence.hs83
-rw-r--r--Logs/Presence/Pure.hs84
-rw-r--r--Logs/Remote.hs5
-rw-r--r--Logs/Schedule.hs72
-rw-r--r--Logs/Transfer.hs6
-rw-r--r--Logs/Transitions.hs86
-rw-r--r--Logs/Trust.hs33
-rw-r--r--Logs/Trust/Pure.hs36
-rw-r--r--Logs/UUID.hs7
-rw-r--r--Logs/UUIDBased.hs5
-rw-r--r--Logs/Web.hs60
-rw-r--r--Makefile36
-rw-r--r--Remote.hs71
-rw-r--r--Remote/Bup.hs30
-rw-r--r--Remote/Directory.hs35
-rw-r--r--Remote/GCrypt.hs402
-rw-r--r--Remote/Git.hs244
-rw-r--r--Remote/Glacier.hs28
-rw-r--r--Remote/Helper/Chunked.hs33
-rw-r--r--Remote/Helper/Encryptable.hs75
-rw-r--r--Remote/Helper/Git.hs30
-rw-r--r--Remote/Helper/Hooks.hs8
-rw-r--r--Remote/Helper/Messages.hs17
-rw-r--r--Remote/Helper/Ssh.hs97
-rw-r--r--Remote/Hook.hs22
-rw-r--r--Remote/List.hs18
-rw-r--r--Remote/Rsync.hs89
-rw-r--r--Remote/S3.hs39
-rw-r--r--Remote/Web.hs61
-rw-r--r--Remote/WebDAV.hs33
-rw-r--r--Seek.hs19
-rw-r--r--Types/Crypto.hs10
-rw-r--r--Types/GitConfig.hs8
-rw-r--r--Types/Key.hs12
-rw-r--r--Types/Limit.hs20
-rw-r--r--Types/Remote.hs14
-rw-r--r--Types/ScheduledActivity.hs69
-rw-r--r--Types/StandardGroups.hs2
-rw-r--r--Types/TrustLevel.hs2
-rw-r--r--Upgrade.hs17
-rw-r--r--Upgrade/V1.hs2
-rw-r--r--Upgrade/V2.hs6
-rw-r--r--Upgrade/V4.hs23
-rw-r--r--Utility/Base64.hs2
-rw-r--r--Utility/Batch.hs51
-rw-r--r--Utility/Daemon.hs5
-rw-r--r--Utility/Data.hs17
-rw-r--r--Utility/DirWatcher.hs32
-rw-r--r--Utility/Directory.hs19
-rw-r--r--Utility/Exception.hs3
-rw-r--r--Utility/ExternalSHA.hs3
-rw-r--r--Utility/Format.hs11
-rw-r--r--Utility/Gpg.hs147
-rw-r--r--Utility/Gpg/Types.hs30
-rw-r--r--Utility/Hash.hs69
-rw-r--r--Utility/HumanTime.hs88
-rw-r--r--Utility/INotify.hs15
-rw-r--r--Utility/InodeCache.hs3
-rw-r--r--Utility/Lsof.hs4
-rw-r--r--Utility/Misc.hs2
-rw-r--r--Utility/Monad.hs2
-rw-r--r--Utility/Path.hs16
-rw-r--r--Utility/Process.hs58
-rw-r--r--Utility/QuickCheck.hs3
-rw-r--r--Utility/Quvi.hs81
-rw-r--r--Utility/SRV.hs8
-rw-r--r--Utility/Scheduled.hs350
-rw-r--r--Utility/Url.hs63
-rw-r--r--Utility/WebApp.hs6
-rw-r--r--Utility/Win32Notify.hs65
-rw-r--r--debian/NEWS8
-rw-r--r--debian/changelog274
-rw-r--r--debian/control9
-rw-r--r--debian/copyright4
-rw-r--r--debian/tests/basics4
-rw-r--r--debian/tests/control4
-rw-r--r--doc/Android/comment_5_ba11b81c671d9bcd6f496fbd6f562b0f._comment16
-rw-r--r--doc/assistant.mdwn11
-rw-r--r--doc/assistant/brokenrepositoryalert.pngbin0 -> 5806 bytes
-rw-r--r--doc/assistant/encryptdrive.pngbin0 -> 42725 bytes
-rw-r--r--doc/assistant/fsckconfig.pngbin0 -> 59050 bytes
-rw-r--r--doc/assistant/genkey.pngbin0 -> 27854 bytes
-rw-r--r--doc/assistant/local_pairing_walkthrough.mdwn30
-rw-r--r--doc/assistant/release_notes.mdwn31
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_4_978fab3cd165b4ca245e32fc48cf0970._comment8
-rw-r--r--doc/assistant/remote_sharing_walkthrough/comment_4_d7e879f7b098964040df2e27a18eda72._comment18
-rw-r--r--doc/assistant/repairrepository.pngbin0 -> 31791 bytes
-rw-r--r--doc/assistant/repoinfo.pngbin0 -> 7603 bytes
-rw-r--r--doc/assistant/rsync.net.encryption.pngbin0 -> 40504 bytes
-rw-r--r--doc/backends.mdwn4
-rw-r--r--doc/backends/comment_4_46591a3ba888fb686b1b319b80ca2c22._comment9
-rw-r--r--doc/backends/comment_5_2210c7ff2d5812fb3b778ac172291656._comment8
-rw-r--r--doc/backends/comment_6_82f239b58680a2681bd8074c7ef9584d._comment8
-rw-r--r--doc/bare_repositories.mdwn4
-rw-r--r--doc/bugs/400_mode_leakage.mdwn25
-rw-r--r--doc/bugs/Adding_unencrypted_repo_on_drive_in_webapp_gives_internal_server_error__.mdwn69
-rw-r--r--doc/bugs/Android_v4.3_-_Framework_18_-___34__Git_annex_webapp_CANNOT_LINK_EXECUTABLE:_git-annex_invalid_R__95__ARM__95__COPY_relocation_against_DT__95__SYMBOLIC_shared_library_libc.so___40__built_with_-Bsymbolic__63____41__.mdwn22
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux.mdwn75
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_10_ec4a7388ea7106a953f599b664b37f1d._comment8
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_1_6a60c23850a5e2a7bba355e1317abc69._comment13
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_2_90b6ed232b2917b9fe041532284e1212._comment10
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_3_5a89d79395d96c43d7d8a6fd9dc275f1._comment248
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_4_cdd26c71875428dbe3c100944a443d3f._comment9
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_5_76242f5d6c815acd5bd58213bd8bb0fe._comment10
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_6_10852171c0207ca61ea6df1082107353._comment8
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_7_73e8a5696709f8154e63693ba5e569c3._comment10
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_8_392fc344e5833b0eb665fcd38f956b7a._comment8
-rw-r--r--doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_9_9f0fc19a7fcaf7a5827e59e1495cf8c9._comment8
-rw-r--r--doc/bugs/Build_error_on_Linux.mdwn29
-rw-r--r--doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_2_38696178e658d1d32deec37dbea66a3d._comment8
-rw-r--r--doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_3_f34d996827f5e7662bec409cbcce961b._comment12
-rw-r--r--doc/bugs/Can__39__t_start_on_Cyanogenmod_10.2_nightly.mdwn158
-rw-r--r--doc/bugs/Conflicting_archive_descriptions.mdwn16
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn33
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_1_80ca50f5305eda71fe32f2b0bc922c34._comment21
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_2_e6bc6d1c0eb8c469e9e00b37bbcc9b86._comment9
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_0d0f6b6b46d0153433fead2bbd1bbe64._comment12
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_6058a22b733cb02126286af950074ed4._comment10
-rw-r--r--doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_6_593a49669e2fadfb91773f8c84fbb031._comment8
-rw-r--r--doc/bugs/Could_not_read_from_remote_repository.mdwn24
-rw-r--r--doc/bugs/Could_not_read_from_remote_repository/comment_1_da842a9d146bcd5c7773b58364c25597._comment8
-rw-r--r--doc/bugs/Could_not_read_from_remote_repository/comment_2_82746a0cf989d884cd0fd796db092b3c._comment36
-rw-r--r--doc/bugs/Creating_second_repository_leads_to_wrong_ip___40__using_git-annex_webapp_--listen__41__.mdwn35
-rw-r--r--doc/bugs/Discrepancy_between_git_annex_add_and_git_annex_watch.mdwn33
-rw-r--r--doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder.mdwn3747
-rw-r--r--doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_1_ae4a13ff121d27f78904eee9bf5e716b._comment20
-rw-r--r--doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_2_32e360cd7b100ddb9a526e7833fc55e1._comment15
-rw-r--r--doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_3_650dc9ede4e16ef668d96840f63dad47._comment12
-rw-r--r--doc/bugs/Endless_SSH_password_prompts.mdwn15
-rw-r--r--doc/bugs/Endless_SSH_password_prompts/comment_1_b3a32d7a53c30478f409a47f856282ab._comment10
-rw-r--r--doc/bugs/Endless_SSH_password_prompts/comment_2_0a1fc4b4580d8be4c37064e0a16de99b._comment8
-rw-r--r--doc/bugs/Endless_SSH_password_prompts/comment_3_46210f7745b8c7c237fc8b08309390fe._comment11
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__.mdwn28
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_1_9be1b577fa4d5fe9754845073fdf5d32._comment10
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_2_0da0d68b646f2b38be6ecf7c0fe13743._comment8
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_3_09c56f5574931f2ebe903069f0731160._comment16
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_4_0c127396e682ca6ced43aec7deeb0335._comment12
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_5_6bc3eadefde4750eec67a55de6651b2d._comment13
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_6_263ab9c1483438b1717c8061ac81a2fa._comment9
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_7_eccc10990dff37584f8e60cd481a7140._comment26
-rw-r--r--doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_8_f897d20cbe5e0f3f58ce1a0bacad3d71._comment8
-rw-r--r--doc/bugs/Failed_to_make_repository___40__calling_nonexistant_shell__41__.mdwn2
-rw-r--r--doc/bugs/Feature_request:___34__quvi__34___flag.mdwn14
-rw-r--r--doc/bugs/Feature_request:___34__quvi__34___flag/comment_1_908c38024fd252328566034608c2dec3._comment12
-rw-r--r--doc/bugs/Feature_request:___34__quvi__34___flag/comment_2_4b6822fe91aa865f2ac1297a3daa3fca._comment8
-rw-r--r--doc/bugs/Feature_request:___34__quvi__34___flag/comment_3_c72ef77e76b1c99b5e0c78d0742080e7._comment8
-rw-r--r--doc/bugs/Feature_request:___34__quvi__34___flag/comment_4_6092695d6afb1608447afe6f86e6fb83._comment8
-rw-r--r--doc/bugs/Finding_an_Unused_file.mdwn152
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__.mdwn44
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_1_6441dd04adc158df22589c81746108a9._comment10
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_2_d1c5d7642284a375f9c455dbf76efa5c._comment12
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_3_4b863da1c8ba73ad54da20f7d2ec6e5c._comment14
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_4_8e0f489305ce30ad578b9f8526e86416._comment10
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_5_c699034c8e02b2354516414d0ab73aab._comment53
-rw-r--r--doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_6_786cb7e643811dfd2496ceeff8f34f44._comment10
-rw-r--r--doc/bugs/GPG_can__39__t_handle_some_files.mdwn23
-rw-r--r--doc/bugs/GPG_can__39__t_handle_some_files/comment_1_4388c971e991dbc0326e69c49994df1e._comment8
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android.mdwn280
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_1_2fc435d1c741f9fc422401f682e7c8b7._comment17
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_2_b73fb99a75aef912f8286626c5bde66d._comment14
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_3_b7115f2c658439ff59a029f500697fc1._comment57
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_4_67de7a56ddb06fc0e31cc011d281c633._comment8
-rw-r--r--doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_5_58fdb2a00f1737746cdbc804f831a0e7._comment8
-rw-r--r--doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path.mdwn63
-rw-r--r--doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_1_b3197993dbdfaf2db5e4651ac54a896e._comment12
-rw-r--r--doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_2_1fbbd02e61ef524597dafd69460b00b4._comment10
-rw-r--r--doc/bugs/Hangs_on_creating_repository_when_using_--listen/comment_2_dc128eeddeaaf3f84e71aca0fb7d341f._comment8
-rw-r--r--doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__.mdwn295
-rw-r--r--doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_1_0ddcbe0ccecdec1012964dfa436a3eee._comment19
-rw-r--r--doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_2_5765b849bcf045ead9f007bd50b2cfbd._comment20
-rw-r--r--doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status.mdwn8
-rw-r--r--doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status/comment_3_a07105226ef3488b97731db004651976._comment10
-rw-r--r--doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp.mdwn21
-rw-r--r--doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp/comment_1_17814787e333d15da3ab4e57c7d31d4b._comment12
-rw-r--r--doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn42
-rw-r--r--doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__/comment_1_15c354c4841d364e78882d2b46a0a764._comment66
-rw-r--r--doc/bugs/Incorrect_merge___40__a_special_case__41__.mdwn45
-rw-r--r--doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_1_c80418d76b501c688e3a9fb4831520fd._comment41
-rw-r--r--doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_2_8b2a188696f46819f6e3f0e9660362d2._comment45
-rw-r--r--doc/bugs/Internal_Server_Error:_Unknown_UUID/comment_9_ced3516c3e7161e4d7e599232f62a511._comment8
-rw-r--r--doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss.mdwn7
-rw-r--r--doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_10_52364dc5b1b43b51748453d1896e35c6._comment8
-rw-r--r--doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_11_99b4db1841f8630a9c5efd08910e87a3._comment104
-rw-r--r--doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_9_e53148a9efa061a825f668a9492182f7._comment10
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop.mdwn39
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_1_b8c485bafd98be8c21595597af361255._comment8
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_2_bc63489334f44a423645021415ffe196._comment10
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_3_6345b174d04b6613c2c55a6ec9e50c21._comment16
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_4_f39ec6c3d5a016b3c5260162c0b42177._comment12
-rw-r--r--doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_5_ca0c5ef6e6a6d2c4b64430ac68370b6a._comment8
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo.mdwn20
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_1_0b4dcedc58e5071733e1239490aed2ea._comment10
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_2_1cb1ef0292a3357874b461a77c13373e._comment8
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_3_e5ec1e3ab304d738e3b0847287a47af4._comment10
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo.mdwn25
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_1_d95accb43bd18cc9acbbf1d4069f86b3._comment8
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_2_452a3c524974832f0742efb00df4d576._comment13
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_3_f8f6d1e0065e5ba56cd405b1c021ca09._comment10
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_4_b524649cee751532d20a4894d71c5cf3._comment8
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_5_8312ba868ef616ec00563446c9c3464f._comment12
-rw-r--r--doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_6_1af75c691d27c97397f1901f7c2483b0._comment8
-rw-r--r--doc/bugs/OSX_app_issues/comment_13_cb12d419459e5cac766022ee0697fedc._comment18
-rw-r--r--doc/bugs/OSX_app_issues/comment_14_c966fa549bc73c52034ac9abc49de52a._comment8
-rw-r--r--doc/bugs/OSX_app_issues/comment_15_10f1df95266f1a8c9ef933183190f6e2._comment8
-rw-r--r--doc/bugs/OSX_app_issues/comment_16_064e151da121f9c2ef13c19ecb4e7458._comment16
-rw-r--r--doc/bugs/OSX_app_issues/comment_17_0e6ac5e0a54ce78bdc56c62e6fb92846._comment8
-rw-r--r--doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex.mdwn54
-rw-r--r--doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex/comment_2_f7149b684a97070cff051b780c73be48._comment15
-rw-r--r--doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple.mdwn4
-rw-r--r--doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_3_eaed9b5532e30e401f50193a72b98310._comment13
-rw-r--r--doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_4_1fab407f3823ce8cec87f5df55e49f8c._comment8
-rw-r--r--doc/bugs/On_Windows__44___can__39__t_use_a_USB_disk_annex_created_on_Linux.mdwn2
-rw-r--r--doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured.mdwn2
-rw-r--r--doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured/comment_1_95655915ff6ba9fb5d873358ff047496._comment10
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn230
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_1_3a3891c9d7ee808f6a71780cb628f23d._comment12
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_2_2bc6efb1d9e872cc5d4fbfbaaf5cc10e._comment27
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_3_fff1e778a6334258c173a96e6bf7ef6a._comment10
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_4_2a86da97a89e28f0a0f5e160d4932ae6._comment19
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_5_41b8e8e58025cc8c8f12efb9a51acd29._comment50
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_6_38afcd8e7fb278ca0ee2e9e0c9f6883e._comment10
-rw-r--r--doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_7_06de36dcde4c52ab74c8134f3242ac02._comment9
-rw-r--r--doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds.mdwn6
-rw-r--r--doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_6_9e3300b223dd54a3f07c650f5cf70ae0._comment8
-rw-r--r--doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_7_b91f4a87b6d29ae6b4262922fd65a79d._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files.mdwn21
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_10_d4f6bfe8e04560fc661a47b09ed8a5f4._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_1_e1a99bd3eb8b3186653b52a52b1836de._comment10
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_2_dec3e5ffe5cfdc439f418ee00d7d9810._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_3_d106a87101db52f957da84d90dafcdbb._comment12
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_4_f28ed0635612693e437e64d872af5c37._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_5_f0237075653768c84deb702442645f28._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_6_b509006e1590480a104627369bc910f2._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_7_fe261c074211ccb94bbcb32cfd8ee654._comment14
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_8_bc8e4dc7e0d6577ba5fcc98f56627b1f._comment8
-rw-r--r--doc/bugs/Problem_when_dropping_unused_files/comment_9_e9a22aa2ebcde5f6595b49dba9375761._comment14
-rw-r--r--doc/bugs/Resource_exhausted.mdwn2
-rw-r--r--doc/bugs/Resource_exhausted/comment_10_bccf9528ffe963154c92ce49762e7ea6._comment10
-rw-r--r--doc/bugs/Resource_exhausted/comment_5_f55d933bce77fd2185ebd0cc46fe57ec._comment64
-rw-r--r--doc/bugs/Resource_exhausted/comment_6_26c98fca45b029a527f9684873db4be5._comment18
-rw-r--r--doc/bugs/Resource_exhausted/comment_7_8bab413b472f900e04977db2bc3951b6._comment8
-rw-r--r--doc/bugs/Resource_exhausted/comment_8_e9bec0b80179b1229b6af0979a21c727._comment9
-rw-r--r--doc/bugs/Resource_exhausted/comment_9_419e24e0b91f569294ece28c42daa246._comment15
-rw-r--r--doc/bugs/S3_buckets_with_capital_letters_breaks_authentication.mdwn32
-rw-r--r--doc/bugs/S3_memory_leaks/comment_1_a7268213b090bce6b1f1858a8e23d90e._comment14
-rw-r--r--doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.txt46
-rw-r--r--doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_1_00b52dba3bc30516e06c44cbfd3a05a2._comment17
-rw-r--r--doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_2_8f5fa659c2ab91b1757bac31cd3b15eb._comment10
-rw-r--r--doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_3_ccf9623d60c58d036d8bf24757e50de3._comment10
-rw-r--r--doc/bugs/Stale_lock_files_on_Android.mdwn7
-rw-r--r--doc/bugs/Too_much_system_load_on_startup.mdwn24
-rw-r--r--doc/bugs/Too_much_system_load_on_startup/comment_1_4470cddc0965062588acff1bc77285e9._comment8
-rw-r--r--doc/bugs/Transfers_continue_after_daemon_stopped.mdwn5
-rw-r--r--doc/bugs/Transfers_continue_after_daemon_stopped/comment_1_39eb527d64367e6762281246f1d49b1f._comment12
-rw-r--r--doc/bugs/Unable_to_import_feed.mdwn27
-rw-r--r--doc/bugs/Unable_to_import_feed/comment_1_16230fbbb996e165b84787ed4d5f72ea._comment45
-rw-r--r--doc/bugs/Unable_to_use_remotes_with_space_in_the_path.mdwn35
-rw-r--r--doc/bugs/Unfortunate_interaction_with_Calibre/comment_5_fc4d5301797589e92cc9a24697b2155d._comment15
-rw-r--r--doc/bugs/Unknown_command___39__list__39__.mdwn15
-rw-r--r--doc/bugs/Unknown_command___39__list__39__/comment_1_c625d03d1ed2019141ac9202f933466d._comment8
-rw-r--r--doc/bugs/Unknown_command___39__list__39__/comment_2_800e1b6417768bdadda311ebfb5df637._comment8
-rw-r--r--doc/bugs/Unknown_command___39__list__39__/comment_3_35dfc75ce9efffff139f8929dc311e29._comment10
-rw-r--r--doc/bugs/Unnecessary_remote_transfers.mdwn24
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_10_b778fbb1386f0f51bf057ffacd590ebb._comment12
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_11_55430eac842d0a192dc7f41d7730e4d5._comment10
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_1_00c18e07678dc513a02d974fe059df73._comment12
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_2_2e9992dbfceabd6df535a2770626de16._comment35
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_3_a98f3091a6a658919f0562cf396439c2._comment8
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_4_417c1e8e27ee1a1f9ebf9160560605c5._comment96
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_5_eb5a2717a1f0c7bb761d2a7866b23def._comment8
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_6_89f756db1f3f2e60a3bd1f35f55fee43._comment40
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_7_5aaf8766a7ba05c4f92715e5d5175a8f._comment13
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_8_e856b350632cc865d16d1995a6cdf065._comment14
-rw-r--r--doc/bugs/Unnecessary_remote_transfers/comment_9_64f831545b34b78452952cf49b5f5b05._comment25
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key.mdwn34
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_1_7bb01d081282e5b02b7720b2953fe5be._comment8
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_2_9c0c40360f0058a4bd346c1362e302b6._comment8
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_3_8f69f58107246595f5603f35c4aa7395._comment8
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_4_78b3c52ba85edfa6ee6e273bec3bea5c._comment13
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_5_a85ccf2f09ebe87147f8761b81a02326._comment8
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_6_8b89eb5e6386acd0a922310c04f863ac._comment12
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_7_20dc5a7ce7cb6ca97ccdfb923c3b24bb._comment10
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_8_9dc921dc6077f828454a4444088b9a43._comment15
-rw-r--r--doc/bugs/Using_a_revoked_GPG_key/comment_9_f50c802d78041fd1522f0e7599ce6a45._comment42
-rw-r--r--doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_2_6d360a15818866242f9cbcf383094f8a._comment11
-rw-r--r--doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_3_1a7542249b9c37507126e97441057c12._comment12
-rw-r--r--doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git.mdwn384
-rw-r--r--doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git/comment_1_155e0c4d3aa41eebfe27533ab70a91d3._comment68
-rw-r--r--doc/bugs/Windows_build_test_failures.mdwn2
-rw-r--r--doc/bugs/Windows_build_test_failures/comment_1_ea7523fdbafdc8be2971df52d9038826._comment10
-rw-r--r--doc/bugs/Windows_installer_includes_curl_and_wget__44___but_not_required_DLLs.mdwn2
-rw-r--r--doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail.mdwn131
-rw-r--r--doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_1_c87bae87b7902db60a3fef41e1fca85d._comment9
-rw-r--r--doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_2_9e3c1f1ba05d8996b5a95829ce32c07e._comment10
-rw-r--r--doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_3_3a0787912f4a3a8797b7786f5ce38590._comment8
-rw-r--r--doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_4_c4249f32d65594d79ea01145b93ec948._comment9
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes.mdwn44
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_1_0f8b248025722309e9577d7dad74b76b._comment10
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_2_f5f7db688a2a93ee7453674fb742043b._comment52
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_3_ffcae976aa3dc2426188797c1aaffb82._comment10
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_4_8a7ff6841ad7c27ead06bf12f46b20a0._comment49
-rw-r--r--doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_5_406fdee0728680774a69d28446163f10._comment26
-rw-r--r--doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error..mdwn39
-rw-r--r--doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_1_6d821af99ab3c83a5b0f52d3713ab8e2._comment10
-rw-r--r--doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_2_206b6c8cce8350fc088f01c42fc4715b._comment8
-rw-r--r--doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_3_ed36f503f88611382b50687608b9b7e7._comment10
-rw-r--r--doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu.mdwn22
-rw-r--r--doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu/comment_1_f4656f8a0f36535def0772db06098c5f._comment13
-rw-r--r--doc/bugs/__96__git_annex_import__96___clobbers_mtime.mdwn2
-rw-r--r--doc/bugs/__96__git_annex_import__96___clobbers_mtime/comment_4_7235130786e764ec3ad5facfecde62da._comment (renamed from doc/install/Android/comment_7_c6dc23d0e6f4138c4bf8e3452755676f._comment)6
-rw-r--r--doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories.mdwn113
-rw-r--r--doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_1_94ccd548c084286163eeb2af1ddc18e3._comment8
-rw-r--r--doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_2_befde3ef3d2b171ebb691915ff3af172._comment8
-rw-r--r--doc/bugs/__96__git_annex_sync__96___ignores_remotes.mdwn106
-rw-r--r--doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_1_39421e6935233cd8f45949ebdef369fe._comment9
-rw-r--r--doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_2_53fb15d6fbf96d43564ff7c866239d18._comment8
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow.mdwn6
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_3_12b20cbbc2b4cd1ab8af7e3eec9589b4._comment30
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_4_a50b43c15d2650df90f0fa1ced47f532._comment10
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_5_7328bc51bd001f2b732a92a2ae175839._comment114
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_6_880ef2ee797221332dbb629b2d55522f._comment10
-rw-r--r--doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_7_826fd82cdf9b1c79c9b555ca26c2c176._comment8
-rw-r--r--doc/bugs/addurl_fails_on_the_internet_archive.mdwn65
-rw-r--r--doc/bugs/addurl_fails_on_the_internet_archive/comment_1_e227aa25eea0b41f1176037a601c5844._comment10
-rw-r--r--doc/bugs/addurl_fails_on_the_internet_archive/comment_2_6d4fd58f0caa1f75ee2dd3f0a909cd91._comment8
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit.mdwn28
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_1d841ff0b0ffd814efed2449dc1f35f3._comment10
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_cd101e0af45d8f463011fb0d04b3b822._comment9
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_11_8595041cfe703d9bea49e792732dc15f._comment8
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_1_8e7bc6965ea967a8d43240791a30c5bc._comment9
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_2_891c1073f908b204651899d41599f944._comment8
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_3_de02b8f1b5928fa1a7078c4aa2124bea._comment11
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_6_506acc4275a81ed9e9b08e8a40fcf96a._comment9
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_7_d38d6f40db4c9437764c7b2ddf36b5a9._comment10
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_8_9bb23e9cbc77ecca4b1209b0f66bc2b0._comment8
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_d1ce7fc251db076da61eed5bb9d71b9a._comment9
-rw-r--r--doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_feb71c1022ff65d82e66a3958a41dfb2._comment8
-rw-r--r--doc/bugs/assistant_always_assumes_port_22__63__.mdwn39
-rw-r--r--doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac.mdwn53
-rw-r--r--doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_1_4ea192e57f86a33087997746722e6acf._comment10
-rw-r--r--doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_2_622ad5b34780fc8468c5c515ad9f27fa._comment8
-rw-r--r--doc/bugs/assistant_does_not_allow_adding_an_existing_repo.mdwn8
-rw-r--r--doc/bugs/assistant_does_not_allow_adding_an_existing_repo/comment_1_87e84d56d56abefe8cac8a52b76c9003._comment8
-rw-r--r--doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_3_f9b2a700c060707fae1bcb2ec0e4e4dc._comment9
-rw-r--r--doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_4_014d213a959dd7993bdd247722a8817e._comment8
-rw-r--r--doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_5_440f349781d7d9ca2d1ed81386f7dd26._comment8
-rw-r--r--doc/bugs/assistant_doesn__39__t_sync_file_permissions/comment_3_4d5ae51b4c7e6177d934d7c9f21b912c._comment8
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual.mdwn24
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_1_37acb3afafb1b4c4da7c778130cf3035._comment8
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_2_9d58887ee0184663852bde83b8d497c7._comment10
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_3_b70881c8026e30fd3ddc051bd01a888b._comment8
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_4_43f756e2e6ff985c8e050da0e369d486._comment25
-rw-r--r--doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_5_eda947eb7f8c46b9a61d6430b5f9ebfd._comment25
-rw-r--r--doc/bugs/assistant_ignore_.gitignore/comment_2_22f75af80c779dcb4d6033b90373f74e._comment10
-rw-r--r--doc/bugs/assistant_ignore_.gitignore/comment_3_8b2a400e1d44a1c9b183e2b7861efbe3._comment8
-rw-r--r--doc/bugs/authentication_to_rsync.net_fails.mdwn30
-rw-r--r--doc/bugs/authentication_to_rsync.net_fails/comment_1_9db65f89415c8d825f268afb75244998._comment10
-rw-r--r--doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_3_51da7f5881f65422328d341e5ab0d250._comment33
-rw-r--r--doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_4_ba384314c1e47ec4b72e1843e0500df9._comment10
-rw-r--r--doc/bugs/box.com_never_stops_syncing..mdwn63
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_1_124a5edcd89cc6b61e1a41f5b4d640d7._comment10
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_2_42574181aa721319ba54eadf0a15ddff._comment11
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_3_2ad727849070cfd52d6c719478e9cce3._comment8
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_4_83ce23e45f5a5845d4f04519ee14ec65._comment9
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_5_ef1c9d87b04db5047ab72167d3269687._comment8
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_6_c9cb39eba941678035f9b2888da1085c._comment10
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_7_4b0632a4e37c96959a8e6434e9fd86fb._comment17
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_8_d9d318b8c958de6031ae323da20af625._comment55
-rw-r--r--doc/bugs/box.com_never_stops_syncing./comment_9_689ac6a4a305197cf5566f98dab47b4b._comment8
-rw-r--r--doc/bugs/build_fails_in_Assistant__47__WebApp__47__Gpg.hs.mdwn57
-rw-r--r--doc/bugs/cabal_install_fails_to_install_manpage.mdwn43
-rw-r--r--doc/bugs/can__39__t_annex_get_from_annex_in_direct_mode.mdwn2
-rw-r--r--doc/bugs/cannot_determine_uuid_for_origin.mdwn135
-rw-r--r--doc/bugs/cannot_link_executable_on_android.mdwn28
-rw-r--r--doc/bugs/clicking_back_in_the_web_browser_crashes.mdwn23
-rw-r--r--doc/bugs/clicking_back_in_the_web_browser_crashes/comment_1_c962218657a28494ff837a471d71b43f._comment8
-rw-r--r--doc/bugs/clicking_back_in_the_web_browser_crashes/comment_2_643b2c99ecfe851c576a023ce4385dbb._comment10
-rw-r--r--doc/bugs/clicking_back_in_the_web_browser_crashes/comment_3_6e85c50439da81212f4239c74947b75e._comment12
-rw-r--r--doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work.mdwn74
-rw-r--r--doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work/comment_1_77629f620b28ac62364de44b41fa539d._comment8
-rw-r--r--doc/bugs/cross_platform_permissions_woes.mdwn36
-rw-r--r--doc/bugs/cross_platform_permissions_woes/comment_1_7f01104de38a6a319a8f36aa1dc8b4b3._comment14
-rw-r--r--doc/bugs/cross_platform_permissions_woes/comment_2_0a34e11b466fad287325425e76487fa1._comment73
-rw-r--r--doc/bugs/cross_platform_permissions_woes/comment_3_278f91b4bc4c32717ab1c39c2abf9305._comment8
-rw-r--r--doc/bugs/cross_platform_permissions_woes/comment_4_eb6a271cb63c71341469c9ff89dc0eb9._comment9
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos.mdwn199
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_1_294c33af08649256908a97894f93c05d._comment10
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_2_02a2b69adbb04b557146e713b70b34d2._comment14
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_3_d296ef26fc90f4e3166bba6d2de0a1ee._comment8
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_4_33ba2c890c962a71ae9fadc417359f8e._comment8
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_5_39eb0bb96fd271bd0de4a3a40814ae1b._comment11
-rw-r--r--doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_6_d80c4b631bdf58901a06f29a2c5682e2._comment8
-rw-r--r--doc/bugs/direct_mode_assistant_in_subdir_confusion.mdwn31
-rw-r--r--doc/bugs/direct_repository_on_FAT32_fails_to_addurl_containing___63__.mdwn44
-rw-r--r--doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__.mdwn51
-rw-r--r--doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_1_69dfbf566c75396cdaaf5ad70f1a94a8._comment19
-rw-r--r--doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_2_8d09cc0e06548c4ebde7956edd1b5d85._comment8
-rw-r--r--doc/bugs/encrpyted_ssh_remote_on_macosx.mdwn42
-rw-r--r--doc/bugs/encrpyted_ssh_remote_on_macosx/comment_1_46c37aacb7ae41864488fb7c7d87d437._comment10
-rw-r--r--doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__.mdwn63
-rw-r--r--doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_1_e6f39b2ef55b0daa491f4b6329a906bc._comment8
-rw-r--r--doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_2_b47d6d188f38a8e4ca5ef5f70afadf6a._comment48
-rw-r--r--doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_4_b533b1de535a057b7ebf99afc92691ed._comment13
-rw-r--r--doc/bugs/file_modification_times.mdwn13
-rw-r--r--doc/bugs/gcrypt_initremote_pushes_git-annex_but_not_master.mdwn19
-rw-r--r--doc/bugs/get_from_bup-remote_with_pubkey_failing.mdwn93
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied.mdwn48
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_1_f4584158b35b80ece1060308883e2dc4._comment8
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_2_a4d7aae848340771a9b8e2c87abeea42._comment26
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_3_06bda101ad584b4b882de8b2e202d679._comment8
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_4_4fc6b25401b645cabc04b510bdfa6863._comment10
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_5_4e193306801680bba433e75eb4dcba05._comment12
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_6_76ccdf0542e76e4dbd61f3b3228d40ba._comment10
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_7_cd964d0a375c5cba299bf2bbbbb86acb._comment12
-rw-r--r--doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_8_9bac87c85deb5bb15795df28533d0cde._comment10
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long.mdwn40
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_1_3f83ea525436b2379ab29a0f860c4669._comment8
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_2_b417c94169378ef7d0d278ebae517fa1._comment8
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_3_fa925cca216cb810ad80482b19fc6053._comment8
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_4_8bd2996107b2d272c32810658e07e715._comment8
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_5_378de7d7503a64611eab62f2f5cffef3._comment15
-rw-r--r--doc/bugs/git-annex:_Argument_list_too_long/comment_6_a94e17151348d02999442dd1219babfb._comment10
-rw-r--r--doc/bugs/git-annex:_fd:14:_hGetLine:_end_of_file.mdwn2
-rw-r--r--doc/bugs/git-annex:_status:_1_failed.mdwn25
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_10_7cd9de88e55633fc75460f4fe0400f09._comment8
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_11_504a944aab34155046f2fd82c2878f3e._comment18
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_1_c235cc83c75474e6393e08d2d94b119d._comment10
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_2_932f6aaa712298a47868002872e16310._comment10
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_3_4bf55320439de152a65e2f21d4a0604b._comment14
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_4_cb2cfb798c6171f77eb7c4c4061c0f0c._comment8
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_5_05c84dde377298adfd3fc20749b3108f._comment10
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_6_bb5141e29c665bc0bb82611ea27d4be8._comment11
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_7_5fd39168c9e1bf43909ee0ab3c75c40c._comment35
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_8_e493f6bddb0bfcd9478d5f4d9fc170e0._comment8
-rw-r--r--doc/bugs/git-annex:_status:_1_failed/comment_9_573377d444aee0895b231082bc6839a4._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3.mdwn4
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_10_e47c073f1614f7b57f86acedeeb1cadc._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_11_ce34578c45060b7c8b759efd1c1d8df8._comment13
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_12_75965395dc33046ce34ac5ba972b7d64._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_13_f07bc76dd3c5580fc0855a33ae835c8d._comment12
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_14_637c59becc68a1e4f60069d8873489ff._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_15_d80b87055f72873f5678a01d2630bea4._comment10
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_16_57ac84868b223b30f005704eefa01b8d._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_17_a41f4d8a72c07ad770e6479e9b8c7f1d._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_18_7d36637f11cda51de395303d5c1c6a3f._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_19_c8609c3f7f62ae5427fd8c60bc9546ed._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_20_0886bca6d0c6a9415a7794d256be2e9d._comment14
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_21_2b39729f95c9c4bba620ecdd3d1558ed._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_22_8d90d92951919aa70638b31e9248bec5._comment16
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_23_6398271f5cd9e94996202ef3bce6f6ed._comment20
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_24_c9e399833cc6235077161f490dfa866f._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_25_cf093737eefb2b99f6f0eac9bf3e74b3._comment9
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_26_c122ce53175fc9e0e114a8acd2385c0d._comment29
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_27_237e41e61781bb058f5fd39362a904e4._comment10
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_28_97f423a41ee9d2d74291594fae20dd4e._comment10
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_29_7b3fbe7e38f637fcea511441ac243d93._comment10
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_2_53e2d095b2501844cadec910de286814._comment14
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_30_26c04584c3c6dacf59e1b6c82042c97c._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_3_ddc9cbae1a721400a9acf2153e18f4f0._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_4_593235735e32238094121b1f79355bbd._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_5_f806fd5930e90920db24456297465bae._comment9
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_6_5741b6a5997328fdcd5cc99f841b18d3._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_7_3e0d9949dd810069af0b8076807e5924._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_8_f58897eff6b4693f0c73474ccfe6e733._comment8
-rw-r--r--doc/bugs/git-annex_broken_on_Android_4.3/comment_9_ddba87b2f20d8a63f7b8ebdb9bd13515._comment18
-rw-r--r--doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__.mdwn58
-rw-r--r--doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_1_5dd4d1cec069c13184f5dd9efca6721b._comment8
-rw-r--r--doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_2_d9b65fe4cb4bfd58f37e7da5350c6401._comment14
-rw-r--r--doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_3_1027187b203addd65af8cf1faf28727d._comment10
-rw-r--r--doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_4_ac65028203ff0cbdb978200235fb4e9c._comment10
-rw-r--r--doc/bugs/git-annex_merge_stalls.mdwn16
-rw-r--r--doc/bugs/git-annex_merge_stalls/comment_1_31578a754945bdcb902c62ff58704bcb._comment17
-rw-r--r--doc/bugs/git-annex_merge_stalls/comment_2_f3b6bf180466b5931bfd20b2f0229422._comment10
-rw-r--r--doc/bugs/git-annex_merge_stalls/comment_3_ced9b0d724fb55c756106b64c3721003._comment18
-rw-r--r--doc/bugs/git-annex_opens_too_many_files.mdwn40
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_1_37f6f5838c41c533df4be1f927b9b03d._comment26
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_2_347ef233b9845b84d7c4d49ed166e797._comment10
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_3_d5f644d97cd2db471deb5dcd728cae60._comment8
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_4_c03bde64be8fdd962826bc7afa07d2a9._comment137
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_5_33a2e783e5355e981497b9861997570b._comment18
-rw-r--r--doc/bugs/git-annex_opens_too_many_files/comment_6_b3a5a4e4ca29c5cd2840bfeb4c63ea68._comment15
-rw-r--r--doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__.mdwn358
-rw-r--r--doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_1_97abb8442329d19c9687002f43afac74._comment23
-rw-r--r--doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_2_3405f3cd699860ee239cf23ade19e92c._comment10
-rw-r--r--doc/bugs/git-annex_sync_may_fail_when_the_directory_I__39__m_in_disepeared.mdwn15
-rw-r--r--doc/bugs/git_annex_add_error_with_Andrew_File_System.mdwn28
-rw-r--r--doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_1_bc783e551fc0e8da87bc95bff5b8f73a._comment8
-rw-r--r--doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_2_faefcf69bd61c47566131cb31b78cc19._comment10
-rw-r--r--doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_3_d5014c8b78437b9fddbb1e83d3679081._comment10
-rw-r--r--doc/bugs/git_annex_copy_trying_to_connect_to_remotes_uninvolved.mdwn2
-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__.mdwn42
-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__/comment_1_7ee08a60e4b2516c010d3c2163049681._comment15
-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__/comment_2_c29525bfda08717f68aaac83014e6b08._comment8
-rw-r--r--doc/bugs/git_annex_describe_can_break_uuid.log.mdwn46
-rw-r--r--doc/bugs/git_annex_describe_can_break_uuid.log/comment_2_9ead36f13cbde6c822b231441de636ae._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_10_141819a6b67de2602673698f6f148106._comment13
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_11_8be96359fd2bd33ed2961e499dc2685e._comment12
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_12_26950a37e86d4dd83dd59fb2564d0a2e._comment11
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_13_cbf8150dbe0da64bde7f6af8e041eda8._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_14_0c203f90d911cf6869894dae89575a49._comment13
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_15_68cbb7268bdad73357da2d11e05d73c4._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_16_816d552f871a1b06306f04d575adb2e5._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_17_7905b097a9c582452fb04cdc88ed4285._comment14
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_18_bd5ac9bb2eaab66af6aa13b39172b49d._comment9
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_19_9881db7bb6fef4e47c54cdc23e995f17._comment13
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_20_41e2ea458669f59f96b5860825745910._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_21_515039e321e0595f95430d8082bd54a5._comment20
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_6_94144c0cbdbccc72c13e12daf7657a29._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_7_9eb064ffdc3fdb70e85572185e151a3f._comment8
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_8_cde756e8a9b18fe2ca9cda25967bc7fb._comment10
-rw-r--r--doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_9_1fd6a4374a334bc03914c3e0df95ef95._comment10
-rw-r--r--doc/bugs/git_annex_import_destroys_a_fellow_git_annex_repository.mdwn130
-rw-r--r--doc/bugs/git_annex_importfeed_fails.mdwn64
-rw-r--r--doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn78
-rw-r--r--doc/bugs/git_annex_indirect_can_fail_catastrophically/comment_1_0b085e7e8c8e364f479574bc00c7c394._comment21
-rw-r--r--doc/bugs/git_annex_migrate_leaves_old_backend_versions_around/comment_1_f3e418144e5a5a9b3eda459546fc2bb0._comment8
-rw-r--r--doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated.mdwn11
-rw-r--r--doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated/comment_1_2a5a07498df9d38531d4570f7b463b9a._comment8
-rw-r--r--doc/bugs/immediately_drops_files.mdwn222
-rw-r--r--doc/bugs/immediately_drops_files/comment_1_9ef6e694ef8a8eee7a42f88554475db7._comment10
-rw-r--r--doc/bugs/immediately_drops_files/comment_2_76e4f8b73ab60b2540dd2a3e5379791d._comment8
-rw-r--r--doc/bugs/immediately_drops_files/comment_3_788db083f5ba2e5589c3b952203ec954._comment21
-rw-r--r--doc/bugs/immediately_drops_files/comment_4_425b79865eb77d69d0b7a71a14639f81._comment10
-rw-r--r--doc/bugs/immediately_drops_files/comment_5_7c9f660b6bcec31827a44a650e9d4622._comment10
-rw-r--r--doc/bugs/importfeed_fails__44___bad_feed_content.mdwn36
-rw-r--r--doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast.mdwn77
-rw-r--r--doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast/comment_1_4ccfabbaf75e139b32f6fa6f7bc6a7fe._comment8
-rw-r--r--doc/bugs/importfeed_should_allow_pubdate_in_the_template.mdwn5
-rw-r--r--doc/bugs/importfeed_uses___34____95__foo__34___as_extension.mdwn17
-rw-r--r--doc/bugs/inconsistent_use_of_SI_prefixes.mdwn55
-rw-r--r--doc/bugs/internal_server_error:_hGetContents:_invalid_argument___40__invalid_byte_sequence__41__.mdwn29
-rw-r--r--doc/bugs/internal_server_error:_unknown_UUID_on_webapp.mdwn147
-rw-r--r--doc/bugs/manpage_has_slight_indentation_error.mdwn38
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos.mdwn26
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_1_6d47485728ea65a9b555f8be7159dea5._comment10
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_2_06723d13ecdaf87de5ff2b209e3c5198._comment10
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_3_9f83ef190547b291a715cda55b7977d4._comment10
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_4_0e32ae0300472c56079cfbcd78a3e386._comment9
-rw-r--r--doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_5_e8998716107e7ae8d0e8d332812517ad._comment14
-rw-r--r--doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build.mdwn36
-rw-r--r--doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_1_0527581ea60d28bb28504fa2a355ed87._comment10
-rw-r--r--doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_2_926a87b60e20d286d49639c8dad13a1a._comment8
-rw-r--r--doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_3_c509fba1a9adacfd26a2bd12b4aea988._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange.mdwn40
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_1_6ac691645edb483797bee05043fd83b3._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_2_5d67e3a60b7cc30c2b1857f50895d363._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_3_78f1e081b92f418c20893d86a8715501._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_4_1e2a59e0eec89ef1a57d1488ff40dcf0._comment12
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_5_5e74431048b07631e0dbeca90fdb365b._comment47
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_6_3724e1c1a5fc6d3589452478249792ec._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_7_7f841ea7bf7d44f3d810ca097ac9eb47._comment8
-rw-r--r--doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_8_c53ce2274388711ffbde1595b64f932b._comment10
-rw-r--r--doc/bugs/remote_not_showing_up_in_webapp.mdwn88
-rw-r--r--doc/bugs/remote_not_showing_up_in_webapp/comment_1_2a269732fd528f505777542d3556437a._comment17
-rw-r--r--doc/bugs/rename:_permission_denied__44___after_direct_mode_switch.mdwn81
-rw-r--r--doc/bugs/rename:_permission_denied__44___after_direct_mode_switch/comment_1_14cec6448831c67794b62926a03b2fc5._comment13
-rw-r--r--doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo.mdwn44
-rw-r--r--doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo/comment_1_52180983b59c247389a55a9523ec435b._comment14
-rw-r--r--doc/bugs/submodule_path_problem/comment_6_cacc91afcb1739dfca3a60590bb70356._comment67
-rw-r--r--doc/bugs/test_suite_failure_on_samba_mount.mdwn278
-rw-r--r--doc/bugs/test_suite_failure_on_samba_mount/comment_1_e074b20801b921ee2661025a050a8af2._comment12
-rw-r--r--doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build.mdwn9
-rw-r--r--doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build/comment_1_e8df4b36a89b37edd94f3a318ae93a32._comment8
-rw-r--r--doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn3
-rw-r--r--doc/bugs/unfinished_repos_in_webapp.mdwn31
-rw-r--r--doc/bugs/unfinished_repos_in_webapp/comment_1_9628b100e39489be9f28ef75276a7341._comment11
-rw-r--r--doc/bugs/unfinished_repos_in_webapp/comment_2_ba0fbff536b1d067c4098db401dc49f2._comment10
-rw-r--r--doc/bugs/unfinished_repos_in_webapp/comment_3_fd554aa7d93117177784a29270ccf790._comment12
-rw-r--r--doc/bugs/unfinished_repository_when_using_annex-ignore_true_.mdwn25
-rw-r--r--doc/bugs/utf8.mdwn5
-rw-r--r--doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working.mdwn28
-rw-r--r--doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working/comment_1_ce06ba4f65f322362b23797f6190c7c3._comment17
-rw-r--r--doc/bugs/web_app_loops_over_a_non-addable_file.mdwn56
-rw-r--r--doc/bugs/webapp:_difficult_to_abort_adding_a_repository.mdwn24
-rw-r--r--doc/bugs/webapp_usability:_put_the_notices_on_the_right.mdwn18
-rw-r--r--doc/bugs/webapp_usability:_put_the_notices_on_the_right/comment_1_ec7a444e09a028b5225bd41fb83442e8._comment9
-rw-r--r--doc/bugs/windows_fails_test___34__recoverEncode__34__.mdwn39
-rw-r--r--doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_1_424b3536e21e02f192f7f2b8e833ed18._comment67
-rw-r--r--doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_2_78db183aa401e2023d7faec5f7a4a573._comment10
-rw-r--r--doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_3_ed2da19eaf0bd0864f6b28816a79bc23._comment8
-rw-r--r--doc/bugs/youtube_support_suddenly_stopped_working.mdwn62
-rw-r--r--doc/builds.mdwn20
-rw-r--r--doc/contact/comment_1_12d60f767d90bea94974e1ff6b206d31._comment8
-rw-r--r--doc/contact/comment_2_95b6d868b913418de50ba121d71d2390._comment10
-rw-r--r--doc/contact/comment_3_2cf43bd406673294e6cdbd785c4a0d0c._comment16
-rw-r--r--doc/contact/comment_4_586a506e27379d74fbc0f4b654e89c7d._comment10
-rw-r--r--doc/copies/comment_1_af9bee33777fb8a187b714fc8c5fb11d._comment8
-rw-r--r--doc/design.mdwn2
-rw-r--r--doc/design/assistant.mdwn24
-rw-r--r--doc/design/assistant/blog.mdwn17
-rw-r--r--doc/design/assistant/blog/day_18__merging/comment_1_7a553ad559519f3b3e3cd20115b4c44e._comment15
-rw-r--r--doc/design/assistant/blog/day_224__annex.largefiles/comment_2_b24d1da2bc4307ded0216daffb8f9336._comment8
-rw-r--r--doc/design/assistant/blog/day_311__Windows_porting.mdwn10
-rw-r--r--doc/design/assistant/blog/day_311__Windows_porting/comment_1_8e738f54a72557bee1e19970472b925c._comment8
-rw-r--r--doc/design/assistant/blog/day_312__DebConf_midpoint.mdwn30
-rw-r--r--doc/design/assistant/blog/day_313__back.mdwn34
-rw-r--r--doc/design/assistant/blog/day_313__back/comment_1_fbf3fdf9688c18156753d446facd942d._comment10
-rw-r--r--doc/design/assistant/blog/day_314__quvi.mdwn27
-rw-r--r--doc/design/assistant/blog/day_314__quvi/comment_1_3fdfb0742cb5422530ddd97b904f2a42._comment8
-rw-r--r--doc/design/assistant/blog/day_315__backlog.mdwn12
-rw-r--r--doc/design/assistant/blog/day_316__day_off.mdwn6
-rw-r--r--doc/design/assistant/blog/day_317__misc.mdwn17
-rw-r--r--doc/design/assistant/disaster_recovery.mdwn160
-rw-r--r--doc/design/assistant/disaster_recovery/comment_1_955dc807196863da23aa8dbd15e04364._comment10
-rw-r--r--doc/design/assistant/encrypted_git_remotes.mdwn9
-rw-r--r--doc/design/assistant/gpgkeys.mdwn19
-rw-r--r--doc/design/assistant/polls/2013_user_survey.mdwn1
-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/encryption.mdwn13
-rw-r--r--doc/design/gcrypt.mdwn8
-rw-r--r--doc/design/roadmap.mdwn18
-rw-r--r--doc/devblog.mdwn10
-rw-r--r--doc/devblog/day_-1__drop_dead.mdwn5
-rw-r--r--doc/devblog/day_-3__.mdwn29
-rw-r--r--doc/devblog/day_-4__forgetting.mdwn80
-rw-r--r--doc/devblog/day_-4__forgetting/comment_1_f3cc7a25af4c59fda3924c737a789419._comment8
-rw-r--r--doc/devblog/day_10__lazy_Sunday.mdwn23
-rw-r--r--doc/devblog/day_11__webapp_encrypted_drives.mdwn12
-rw-r--r--doc/devblog/day_12__gpg_key_generation.mdwn35
-rw-r--r--doc/devblog/day_12__gpg_key_generation/comment_1_48cdfe3bd71fb348ae05fd90e8cf1dab._comment8
-rw-r--r--doc/devblog/day_13__encrypted_sneakernet_working.mdwn13
-rw-r--r--doc/devblog/day_14__gcrypt_refinements_and_OOM_fixes.mdwn26
-rw-r--r--doc/devblog/day_15-17__Android_rebuild.mdwn67
-rw-r--r--doc/devblog/day_19__moving_on.mdwn37
-rw-r--r--doc/devblog/day_19__moving_on/comment_1_870106f671f9a055b81e6fc83e0850b5._comment8
-rw-r--r--doc/devblog/day_19__moving_on/comment_2_fad055c8860385ac6c012f897c96408f._comment10
-rw-r--r--doc/devblog/day_19__moving_on/comment_3_69e47d612159587f080ab761566d1830._comment18
-rw-r--r--doc/devblog/day_1__inauspicious_beginning.mdwn11
-rw-r--r--doc/devblog/day_1__inauspicious_beginning/comment_1_cc4dea43caf3126c6f814b589b701d70._comment10
-rw-r--r--doc/devblog/day_20__gcrypt_and_git-annex-shell.mdwn14
-rw-r--r--doc/devblog/day_21__bugfix_day.mdwn5
-rw-r--r--doc/devblog/day_22__gcrypt_on_rsync.net.mdwn20
-rw-r--r--doc/devblog/day_23__GNU_day.mdwn23
-rw-r--r--doc/devblog/day_24__nearly_done_with_gcrypt.mdwn23
-rw-r--r--doc/devblog/day_25__finishing_up_gcrypt.mdwn25
-rw-r--r--doc/devblog/day_26__gcrypt_really_done_this_time.mdwn17
-rw-r--r--doc/devblog/day_27__locking_fun.mdwn49
-rw-r--r--doc/devblog/day_27__locking_fun/comment_1_0eb247235fbf8f563934f3548e1d2e10._comment8
-rw-r--r--doc/devblog/day_27__locking_fun/comment_2_e8b1dfe1b0641e031d05733448b7bc8b._comment8
-rw-r--r--doc/devblog/day_27__locking_fun/comment_3_b67f8ef4ed42b49c8c2e6c4e53163b16._comment18
-rw-r--r--doc/devblog/day_27__locking_fun/comment_4_0759644baf26b75f4e48dbb387d725a5._comment10
-rw-r--r--doc/devblog/day_28__lazy_saturday.mdwn17
-rw-r--r--doc/devblog/day_29__scheduling.mdwn10
-rw-r--r--doc/devblog/day_2__new_laptop.mdwn8
-rw-r--r--doc/devblog/day_2__new_laptop/comment_1_93447dbd4eb09b4db96770644ea663cb._comment10
-rw-r--r--doc/devblog/day_2__new_laptop/comment_2_e1d022b25f2c16dbe72db07ad4b10a2d._comment8
-rw-r--r--doc/devblog/day_30__cronner.mdwn17
-rw-r--r--doc/devblog/day_30__cronner/comment_1_53dfd9310e92f5225db52a13e20a46d4._comment10
-rw-r--r--doc/devblog/day_30__cronner/comment_2_f98357c6f7a6da23873ac27c2e1e9638._comment10
-rw-r--r--doc/devblog/day_31__blah.mdwn17
-rw-r--r--doc/devblog/day_32__fsck_config_UI.mdwn20
-rw-r--r--doc/devblog/day_33__fsck_on_connect.mdwn9
-rw-r--r--doc/devblog/day_34__wrapping_up_fsck.mdwn7
-rw-r--r--doc/devblog/day_35__anacron_and_bugfixing.mdwn15
-rw-r--r--doc/devblog/day_36__bugfixing.mdwn1
-rw-r--r--doc/devblog/day_37__long_day.mdwn6
-rw-r--r--doc/devblog/day_38__starting_git_repo_repair.mdwn11
-rw-r--r--doc/devblog/day_38__starting_git_repo_repair/comment_1_321468d9686db5dde072500bdaeb7d29._comment10
-rw-r--r--doc/devblog/day_39__git-recover-repository.mdwn54
-rw-r--r--doc/devblog/day_3__gcrypt_uuids.mdwn63
-rw-r--r--doc/devblog/day_40__another_fine_mess.mdwn15
-rw-r--r--doc/devblog/day_41__onward.mdwn17
-rw-r--r--doc/devblog/day_41__onward/comment_1_a716c7b5a9ea3c949ff047cfb4e9a0a4._comment8
-rw-r--r--doc/devblog/day_41__onward/comment_2_33149e424cd5f03fac376288bcc4dfdc._comment8
-rw-r--r--doc/devblog/day_41__onward/comment_3_3b07503bd79089ad3ce3ddd7535ed116._comment14
-rw-r--r--doc/devblog/day_42__repair_milestone.mdwn35
-rw-r--r--doc/devblog/day_43__bugfix_day.mdwn26
-rw-r--r--doc/devblog/day_44__automatic_removable_drive_repair.mdwn16
-rw-r--r--doc/devblog/day_45__command_line.mdwn9
-rw-r--r--doc/devblog/day_46__wrapping_up_the_month.mdwn18
-rw-r--r--doc/devblog/day_47__fell_off_the_blogging_wagon.mdwn3
-rw-r--r--doc/devblog/day_48__direct_mode_guard_design.mdwn29
-rw-r--r--doc/devblog/day_48__direct_mode_guard_design/comment_1_ec0147ccc55bad3a38652383f4098a65._comment8
-rw-r--r--doc/devblog/day_49__direct_mode_guard_implementation.mdwn14
-rw-r--r--doc/devblog/day_49__direct_mode_guard_implementation/comment_1_3ebe5c3f708070f164ecaf36b79f7bfc._comment8
-rw-r--r--doc/devblog/day_4__unexpected_windows_day.mdwn10
-rw-r--r--doc/devblog/day_50__grab_bag.mdwn34
-rw-r--r--doc/devblog/day_50__grab_bag/comment_1_01846f6494fe843889391fd09fd127a0._comment8
-rw-r--r--doc/devblog/day_50__grab_bag/comment_2_12736014aa2c1af81e4b83072505e7d5._comment8
-rw-r--r--doc/devblog/day_51__direct_mode_guard_finished.mdwn6
-rw-r--r--doc/devblog/day_52__slowly_but_surely.mdwn5
-rw-r--r--doc/devblog/day_54__android_bisection_minions.mdwn9
-rw-r--r--doc/devblog/day_54__android_bisection_minions/comment_1_bea8fbe2b87d4a4865b92fa796298fa0._comment8
-rw-r--r--doc/devblog/day_55__fireside_porting.mdwn22
-rw-r--r--doc/devblog/day_55__fireside_porting/comment_1_d690a52db82f9594d99ae65fe51e1f1a._comment8
-rw-r--r--doc/devblog/day_56__git-annex_user_survey.mdwn20
-rw-r--r--doc/devblog/day_5__gcrypt_special_remote_part_1.mdwn7
-rw-r--r--doc/devblog/day_6__gcrypt_fully_working.mdwn8
-rw-r--r--doc/devblog/day_6__gcrypt_fully_working/comment_1_136bb7537a9ba93d400ce6f6ea1932ac._comment8
-rw-r--r--doc/devblog/day_6__gcrypt_fully_working/comment_2_1f8faa65bbd56a12588b43a5bc822d96._comment10
-rw-r--r--doc/devblog/day_7__release_day.mdwn10
-rw-r--r--doc/devblog/day_7__release_day/comment_1_12bb94d903868ecddb3e348c9c4afeaf._comment8
-rw-r--r--doc/devblog/day_7__release_day/comment_2_d3e38d6f6bba179dab40d4d75ff061de._comment8
-rw-r--r--doc/devblog/day_8__ill.mdwn20
-rw-r--r--doc/devblog/day_9__Friday_the_13th.mdwn21
-rw-r--r--doc/devblog/day_9__Friday_the_13th/comment_1_07195b4ec399ba1be6c8bdb3ae0fa50b._comment12
-rw-r--r--doc/devblog/moving_blogs.mdwn5
-rw-r--r--doc/devblog/moving_blogs/comment_1_6caa7e67461a6ea5de8155ae9cf75fab._comment8
-rw-r--r--doc/devblog/moving_blogs/comment_2_e3e2048fc2397b87a2f29c9fe49394cb._comment10
-rw-r--r--doc/direct_mode.mdwn52
-rw-r--r--doc/direct_mode/comment_11_1c79c93f4b17cfc354ab920e3775cc60._comment26
-rw-r--r--doc/direct_mode/comment_12_1b5218fdb6ee362d6df68ff1229590d4._comment10
-rw-r--r--doc/direct_mode/comment_13_55108ac736ea450df89332ba5de4a208._comment12
-rw-r--r--doc/direct_mode/comment_14_ff4ffc2aabc5fd174d7386ef13860f78._comment10
-rw-r--r--doc/direct_mode/comment_15_1cd32456630b25d5aaa6d2763e6eb384._comment8
-rw-r--r--doc/direct_mode/comment_1_93fc31e8dc0ad16248a2593a1482d375._comment8
-rw-r--r--doc/direct_mode/comment_2_7f7086b34ed136851963f145868a1d23._comment12
-rw-r--r--doc/direct_mode/comment_4_97c26bd82f623a3b2d56bab4afff0126._comment1
-rw-r--r--doc/direct_mode/comment_7_5355ac418bfb26e990762b80f4c36b77._comment12
-rw-r--r--doc/direct_mode/comment_8_6cd15e2c5fd0bef48f60c6993322c2fc._comment9
-rw-r--r--doc/ekg.mdwn14
-rw-r--r--doc/ekg/ekg.pngbin0 -> 57392 bytes
-rw-r--r--doc/encryption.mdwn114
-rw-r--r--doc/footer/column_a.mdwn4
-rw-r--r--doc/forum/--print0_option_as_in___34__find__34__.mdwn5
-rw-r--r--doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__.mdwn12
-rw-r--r--doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_1_fe291cd6cd8e2d5b8e23f8e3689d824b._comment15
-rw-r--r--doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_2_f0dbc3c723999bf0f22502e3a89d1d4a._comment8
-rw-r--r--doc/forum/Accessing_files_directly_on__a_USB_device.mdwn11
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with.mdwn16
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_1_30b9a70d367dd5b8781e9a86e42d4c3e._comment10
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_2_a8525c1a7e5f89c30c9503fe8bfed02e._comment8
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_3_c3878989f74e740c0ed42f440750f3a4._comment8
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_4_c06cc86496f9d4c0c42a8c89aa5a7b35._comment8
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_5_0a1c2dd0929511ff824be8de2c8d85eb._comment9
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_6_1444c2f89885f028f20a4d3ce225a403._comment23
-rw-r--r--doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_7_1c30944010d541096baff18198a5560d._comment23
-rw-r--r--doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__.mdwn3
-rw-r--r--doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_1_7880fc38792a1fcbf3e5c47e8bcaabce._comment8
-rw-r--r--doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_2_840fbce18b4fdec21ee557fdf52c366e._comment10
-rw-r--r--doc/forum/Annex_contents_just_disappeared__63__.mdwn12
-rw-r--r--doc/forum/Annex_contents_just_disappeared__63__/comment_1_4ab5ca00f912c0c95fabc10f2d9600d3._comment12
-rw-r--r--doc/forum/Annex_contents_just_disappeared__63__/comment_2_657f737c5d64d440aa133ddb41408fbc._comment8
-rw-r--r--doc/forum/Annex_contents_just_disappeared__63__/comment_3_9b4c35feb14b37d43d053d7430da9abf._comment12
-rw-r--r--doc/forum/Annex_contents_just_disappeared__63__/comment_4_c3625409652bff5f2165260803269a8a._comment10
-rw-r--r--doc/forum/Annex_dropping_files.mdwn12
-rw-r--r--doc/forum/Annex_dropping_files/comment_1_62fbea95248fda2ff075b5a8952a728f._comment8
-rw-r--r--doc/forum/Assistant:_configure_auto-sync.mdwn11
-rw-r--r--doc/forum/Assistant:_configure_auto-sync/comment_1_c8cabd38114582bbdbad49f2d81959d7._comment13
-rw-r--r--doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days.mdwn72
-rw-r--r--doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days/comment_1_6ca872c241399b9129cf9a18f42ebd43._comment8
-rw-r--r--doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook.mdwn41
-rw-r--r--doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_1_8b71cb6772b219c27c17392d5099907a._comment12
-rw-r--r--doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_2_af2a2634d8d128868022d033d6adb549._comment13
-rw-r--r--doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_3_31ec762a0684d2ce87d229ed2924db93._comment16
-rw-r--r--doc/forum/Can_we_have_remotes_that_aren__39__t_tracked__63___/comment_1_35e5a963b9e58ed7773dfcb884f8ecbd._comment10
-rw-r--r--doc/forum/Change_remote_server_address.mdwn6
-rw-r--r--doc/forum/Change_remote_server_address/comment_1_401c3d2530ac7ba41dd3857ab4737ed5._comment10
-rw-r--r--doc/forum/Effectively_replicating_backup_files.mdwn25
-rw-r--r--doc/forum/Effectively_replicating_backup_files/comment_1_b1ab0da82db076c5244b0dcc95282ddd._comment14
-rw-r--r--doc/forum/Effectively_replicating_backup_files/comment_2_472ab9c973b475f7f3ce7e3934f94281._comment19
-rw-r--r--doc/forum/Effectively_replicating_backup_files/comment_3_826493bd59b81786c1f6a56f1c438004._comment10
-rw-r--r--doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn1
-rw-r--r--doc/forum/Feature_Request:_add_filename_to_hash_objects.mdwn6
-rw-r--r--doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_1_73dc0a9cad486cf2d34faf064c6193b1._comment10
-rw-r--r--doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_2_f818b3ecfeb1d1dd83df4668c061718a._comment8
-rw-r--r--doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files.mdwn1
-rw-r--r--doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_1_702b1b94c735f1b9cde16daa77a80c12._comment8
-rw-r--r--doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_2_3df7fcbcd482bb9377ead238b314995b._comment8
-rw-r--r--doc/forum/GPG_passphrase_handling.txt76
-rw-r--r--doc/forum/GPG_passphrase_handling/comment_1_11ba130e8bea6698858d0a1a5b01830f._comment15
-rw-r--r--doc/forum/GPG_passphrase_handling/comment_2_ef9d58d15b7bbe0b3c7140bb01d73a31._comment15
-rw-r--r--doc/forum/GPG_passphrase_handling/comment_3_84eb129c8483b87b3ae6ecaf8b4a8309._comment12
-rw-r--r--doc/forum/GPG_passphrase_handling/comment_4_8724297f6d7ac140ab395a940bab0d7d._comment8
-rw-r--r--doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__.mdwn11
-rw-r--r--doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__/comment_1_d0a3d0090928790d5a05e9f8e5f05320._comment12
-rw-r--r--doc/forum/Git_annex___39__corrupting__39___itself.mdwn34
-rw-r--r--doc/forum/Git_annex___39__corrupting__39___itself/comment_1_bcf50a215e2f8771e098aadfff4c300c._comment43
-rw-r--r--doc/forum/Git_annex___39__corrupting__39___itself/comment_3_75f957e7be6c1ad8936c0a2a5374db3e._comment20
-rw-r--r--doc/forum/Git_annex___39__corrupting__39___itself/comment_3_ab062b1df3b55fd49852a6220c98249e._comment10
-rw-r--r--doc/forum/Git_annex_assistant_on_EC2.mdwn5
-rw-r--r--doc/forum/Git_annex_assistant_on_EC2/comment_1_bbdb4611373117a2176c225378110a05._comment8
-rw-r--r--doc/forum/Git_annex_assistant_on_EC2/comment_2_614ed11f7134137d6376d36a61c293f5._comment8
-rw-r--r--doc/forum/Git_annex_on_Windows.mdwn11
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_1_da24ba0219a164f9ab93fe75dd85127e._comment11
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_2_c0880ce3ee13d388ab5b46a740170845._comment50
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_3_70c22716fde60d14fd0c7e74acf4a224._comment11
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_4_b9232deab6bc5036d7339aa202013218._comment12
-rw-r--r--doc/forum/Git_annex_on_Windows/comment_5_27af3c431b50b540d2bd1d3af3f21080._comment8
-rw-r--r--doc/forum/Help_Windows_walkthrough.mdwn177
-rw-r--r--doc/forum/Help_Windows_walkthrough/comment_1_5fc22393a1b28235eabb2871ad83d0a7._comment12
-rw-r--r--doc/forum/Help_on_my_usecase.mdwn22
-rw-r--r--doc/forum/Help_on_my_usecase/comment_1_a35b35c7927640f21d47c3df4f91dabb._comment12
-rw-r--r--doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__.mdwn1
-rw-r--r--doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__/comment_1_e14757c2c106770c2d7069ace4987b3b._comment8
-rw-r--r--doc/forum/How_to_cancel_an_add__63__.mdwn5
-rw-r--r--doc/forum/How_to_cancel_an_add__63__/comment_1_f768ce5dc7c76f96ee6eb352f167be44._comment8
-rw-r--r--doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__.mdwn14
-rw-r--r--doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__/comment_1_7973928b1aa9e0fcfeb6bf80885441f5._comment10
-rw-r--r--doc/forum/How_to_delete_a_remote__63__/comment_2_33c429ffa7e9e2ed9c5fac760ee8e82c._comment12
-rw-r--r--doc/forum/How_to_delete_a_remote__63__/comment_3_e9c5508092ca2983f458b16bf1e07082._comment14
-rw-r--r--doc/forum/Import_options.txt14
-rw-r--r--doc/forum/Import_options/comment_1_118a5f978090a3909299876a01c0adec._comment21
-rw-r--r--doc/forum/Import_options/comment_2_21da91f08cb6b28ae3e79ade033db516._comment17
-rw-r--r--doc/forum/Is_git-annex_in_a_precarious_state_before_the_initial_commit__63__/comment_4_4bf460c5826c36b205e418c4f3f7d770._comment15
-rw-r--r--doc/forum/Is_it_possible_to_make_git-sync_not_nullify_symlinks__63__/comment_1_d6f2d2cdc5f4ffde9eee9f3a8c215a06._comment10
-rw-r--r--doc/forum/Links_or_actual_files__63___Confused__33__.mdwn21
-rw-r--r--doc/forum/Links_or_actual_files__63___Confused__33__/comment_1_779cee2448d7070b1dd636d01296c01e._comment8
-rw-r--r--doc/forum/Links_or_actual_files__63___Confused__33__/comment_2_bccda88697ab7beec0b9fe9ee0230688._comment18
-rw-r--r--doc/forum/Links_or_actual_files__63___Confused__33__/comment_3_c2a9da3f03b55ff294dc0d2010380119._comment8
-rw-r--r--doc/forum/Manual_Setup_of_a_Central_Repo.mdwn1
-rw-r--r--doc/forum/Manual_Setup_of_a_Central_Repo/comment_1_3a163fd5629dc40423f1290a78ae1c07._comment12
-rw-r--r--doc/forum/Manual_mode_option_in_assistant_auto-syncs.mdwn11
-rw-r--r--doc/forum/Manual_mode_option_in_assistant_auto-syncs/comment_1_4a0468b6ca2ffff8ef8f19800597567d._comment10
-rw-r--r--doc/forum/Manual_webapp_behaviour_on_ARM.mdwn15
-rw-r--r--doc/forum/Missing_git-annex.linux__47__runshell.mdwn44
-rw-r--r--doc/forum/Missing_git-annex.linux__47__runshell/comment_1_f29a5105649579ef15e79d983c4e1f8e._comment8
-rw-r--r--doc/forum/My_first_impressions_after_some_weeks_with_git-annex_assistant/comment_2_109534a45881ce94a4586c8a83945f9f._comment85
-rw-r--r--doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_3_92a52b523ed4c68b70ddcabc2a050b76._comment12
-rw-r--r--doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_4_c52a75761ea107f6d69c09bac64f0f0a._comment12
-rw-r--r--doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_5_2685e3a87464ccd37d593516d94ba5cf._comment10
-rw-r--r--doc/forum/OSX_Mavericks_anyone__63__.mdwn3
-rw-r--r--doc/forum/OSX_Mavericks_anyone__63__/comment_1_3075b02aeb57adcbf4addf9fb4c123ba._comment11
-rw-r--r--doc/forum/OSX_Mavericks_anyone__63__/comment_2_c2b6110fc4a3d3481ed8a4b48efb9635._comment17
-rw-r--r--doc/forum/OSX_Mavericks_anyone__63__/comment_3_7df9ba63cb1f385681242b4b58d6a87c._comment8
-rw-r--r--doc/forum/OSX_Mavericks_anyone__63__/comment_4_740fee31c4ca9d84428f97f63ffc075a._comment8
-rw-r--r--doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__.mdwn36
-rw-r--r--doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_1_6c74f0b43c457fe97b2d8630ca4fde29._comment10
-rw-r--r--doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_2_b7a384e853e1756a684774348fad29e6._comment22
-rw-r--r--doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_3_3a8a7f51cb04a92c576549d379b57248._comment12
-rw-r--r--doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_4_582ad3ba0c62a77b08a10b37a780c670._comment15
-rw-r--r--doc/forum/Please_publish_new_releases_not_shorter_than_11_days.mdwn6
-rw-r--r--doc/forum/Please_publish_new_releases_not_shorter_than_11_days/comment_1_da3d39de5be47ebe8b25a42ed1f36510._comment8
-rw-r--r--doc/forum/Poor_man__39__s_IMAP.mdwn6
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_1_258ff23c462dc88b88ced405c4f5040f._comment11
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_2_c88d1abdda4cb526a6ee45a710c75bc4._comment10
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_3_3847e371db1c2788c075e7dca1fbd33e._comment8
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_4_cf6cc21f2cf2aa5c949844e24a7b4075._comment8
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_5_d861fa69475ce526841b3195be8ee356._comment10
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_6_1e81bd4bb62652bc674cdcd7ed57ac5c._comment12
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_7_b3929281dff6078d77f1b9ae42e25bb6._comment16
-rw-r--r--doc/forum/Poor_man__39__s_IMAP/comment_8_69506e8c519196f44b9ed15b32f00106._comment22
-rw-r--r--doc/forum/Problem_with_bup:_cannot_lock_refs.mdwn5
-rw-r--r--doc/forum/Pruning_out_unwanted_Git_objects.mdwn3
-rw-r--r--doc/forum/Pruning_out_unwanted_Git_objects/comment_1_0cf7a12bfa2957260f4b2f79b0cadf2f._comment8
-rw-r--r--doc/forum/Pruning_out_unwanted_Git_objects/comment_2_7472943c02cfe2808b0d566e06caa1a5._comment8
-rw-r--r--doc/forum/Pruning_out_unwanted_Git_objects/comment_3_6a1e7a83d94394454fc085f6d2728cd7._comment8
-rw-r--r--doc/forum/Purge_a_remote.txt2
-rw-r--r--doc/forum/Purge_a_remote/comment_1_78b3b77f457c65d31fd8a5abf714905d._comment8
-rw-r--r--doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment10
-rw-r--r--doc/forum/Purge_a_remote/comment_3_63e0280273b816fa4b837724e102f813._comment8
-rw-r--r--doc/forum/Purge_a_remote/comment_4_7fad1c4798ca03a4095ac3241c279f6d._comment11
-rw-r--r--doc/forum/Relocating_annex_directory.mdwn1
-rw-r--r--doc/forum/Relocating_annex_directory/comment_1_13ff5438baa1db110beb6aab3a783def._comment11
-rw-r--r--doc/forum/Relocating_annex_directory/comment_2_6d88ff03fcf00ae872442e8a86c968ed._comment10
-rw-r--r--doc/forum/Retrieve_previous_version_in_direct_mode.mdwn5
-rw-r--r--doc/forum/Retrieve_previous_version_in_direct_mode/comment_1_ca3a999ed64c42b8df810115de205d2f._comment12
-rw-r--r--doc/forum/Retrieve_previous_version_in_direct_mode/comment_2_1292b34ff6d9976b2bd08748e1ba4e7a._comment8
-rw-r--r--doc/forum/Retrieve_previous_version_in_direct_mode/comment_3_699e816c0397f6db924feeab906f1151._comment8
-rw-r--r--doc/forum/Retrieve_previous_version_in_direct_mode/comment_4_d900388753de5870b7b9c0e8b8c06ed7._comment8
-rw-r--r--doc/forum/Revert_file_linkage_to_original_files.mdwn9
-rw-r--r--doc/forum/Revert_file_linkage_to_original_files/comment_1_898ca2c9976e92d22470c7404aa9813f._comment10
-rw-r--r--doc/forum/Running_assistant_steps_manually/comment_2_3192f614c929b8060d4fbde56a7adec1._comment14
-rw-r--r--doc/forum/Running_out_of__inodes.mdwn17
-rw-r--r--doc/forum/Running_out_of__inodes/comment_1_abc73d9ad662ef642337b683bf0a0253._comment12
-rw-r--r--doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__.mdwn6
-rw-r--r--doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__/comment_1_ec0d56cb31b918023a9184cee168b406._comment8
-rw-r--r--doc/forum/Share_with_friend_copies_only_sym_links.mdwn38
-rw-r--r--doc/forum/Share_with_friend_copies_only_sym_links/comment_1_a8d22dfefb219f0c9130cc294364b198._comment17
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts.mdwn18
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_10_bcb883d46a637dd1a8ef9a92733d202a._comment10
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_11_b7a8b9eaf114f883866fbf2be51b622f._comment8
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_1_6236bcfa9beba705ead3ec2141c5d835._comment8
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_2_ea935b37ca93e73c85d04df7c9bf6057._comment12
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_3_f89a8e38283ac4c8c4a3b74c413d67a1._comment8
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_4_07a0a754a089c46ff69dc97ea7ba9384._comment22
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_5_e884c001a556a0c693d1cc9a97c068ac._comment8
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_6_3e8674b5857e4994dfbc26be4f4b2855._comment25
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_7_7aeabc2e52a39423e83fbd04560e8f91._comment8
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_8_53b95449cfad2fe0f72d2ad642822c03._comment15
-rw-r--r--doc/forum/Slightly_finer_control_over_file_whereabouts/comment_9_a17c102a45e4fc3f101a79acb8eb4081._comment18
-rw-r--r--doc/forum/Suggestion:_Put_ssh_server_back_into_android_version.mdwn9
-rw-r--r--doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_1_5c2f376a82458c6387560355940419d3._comment12
-rw-r--r--doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_2_6321dec0b2f22f841f3cb986e063113f._comment8
-rw-r--r--doc/forum/Sync_with_one_offline_peer.txt11
-rw-r--r--doc/forum/Sync_with_one_offline_peer/comment_1_3859d842d4f7e2ef44877b05ebe881fb._comment20
-rw-r--r--doc/forum/Sync_with_one_offline_peer/comment_2_c9ba3983b37b0c1868269616fd81e518._comment14
-rw-r--r--doc/forum/Sync_with_one_offline_peer/comment_3_28b9c003b4560c3ce90c9ebf808b091b._comment10
-rw-r--r--doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__.mdwn4
-rw-r--r--doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_1_cd55d06a4065b9d3f14d50674c3fcaf7._comment8
-rw-r--r--doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_2_25cbdf478091af9923090e049c432a7d._comment22
-rw-r--r--doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_3_7e71d355457d6b1a0391d4cdae6895e6._comment16
-rw-r--r--doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_4_a73f67f2fcf0762fbd7c8366b3844af6._comment11
-rw-r--r--doc/forum/Truly_purging_dead_repositories/comment_4_477e3c213c5a5d4a33afd42a5b94c718._comment10
-rw-r--r--doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__.mdwn18
-rw-r--r--doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_1_b8702892280447193e6e80be22a580a0._comment11
-rw-r--r--doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_2_50cafde7e30b928480d1f142ddd763d2._comment10
-rw-r--r--doc/forum/USB_backup_with_files_visible/comment_6_add048a16837f7940a859f21426cdbe9._comment8
-rw-r--r--doc/forum/USB_backup_with_files_visible/comment_7_de227ca9911fe57d7a6d3e037f574fe9._comment14
-rw-r--r--doc/forum/USB_backup_with_files_visible/comment_8_0c0ed0e038f7f0e2d2d4ed69b7b29fbc._comment10
-rw-r--r--doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.txt22
-rw-r--r--doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant/comment_1_0a6f6054d70009979f4a036e24b7c500._comment10
-rw-r--r--doc/forum/Un-git-annex__63__.mdwn6
-rw-r--r--doc/forum/Un-git-annex__63__/comment_1_6059265afb66190d325083e0f28bcf33._comment10
-rw-r--r--doc/forum/Un-git-annex__63__/comment_2_fac4bfb81dbbf0dc82059aace261eb51._comment10
-rw-r--r--doc/forum/Use_case_with_syncing_only_a_subset_possible__63__.mdwn13
-rw-r--r--doc/forum/Use_case_with_syncing_only_a_subset_possible__63__/comment_1_a0a272a0931b27e5c94b93e42656b62c._comment10
-rw-r--r--doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_1_85806316ed28d7a891f04fab4027141b._comment8
-rw-r--r--doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_2_ecb411a2c4d67917b734a90bd460d44b._comment10
-rw-r--r--doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__.mdwn36
-rw-r--r--doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__/comment_1_c61c28600f1079fb03ddabc950307f27._comment11
-rw-r--r--doc/forum/Using_git-annex_via_command_line_in_OS_X.mdwn3
-rw-r--r--doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_1_1c9e121f60fb6868c07f1a53b03c4ed0._comment8
-rw-r--r--doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_2_52d8ffba82e29ac2722a8e43e469cc47._comment9
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks.mdwn8
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_1_b9f202a30ba7e3bc264064d24454c099._comment12
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_2_1334a8d9f4bb60f3bf3ebabc656d98d9._comment18
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_3_076f22d05fad140068a540e4d835106f._comment8
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_4_c8446ee1b817f1824fa0df07e742015c._comment12
-rw-r--r--doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_5_f746c1b85ee8e4b57b6819ccceabd28b._comment8
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs.mdwn5
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_1_bd73c8d10028e1b45da9ea8f657e5064._comment10
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_2_16c3c994ee8fcb466e52ca0e812e5915._comment8
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_3_ac60f6edb76bdd541711e472eec9591a._comment10
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_4_2194f0600d9a90f0d9c947ea9cc213a3._comment8
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_5_eb7d13f6b6fa674a2536bde51bfc3fd1._comment48
-rw-r--r--doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_6_ae323b16ddb9342e91be955408eca3b1._comment8
-rw-r--r--doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__.mdwn16
-rw-r--r--doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_1_cdac15fec6fc41d5487b7f653fa718a4._comment14
-rw-r--r--doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_2_82050b7dc367ca5968ab0306db9bd7e3._comment10
-rw-r--r--doc/forum/Wishlist:_Bittorrent-like_transfers.mdwn2
-rw-r--r--doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__.mdwn45
-rw-r--r--doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_1_01cbfc513c790faef3a3ede5315d3589._comment10
-rw-r--r--doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_2_fe28dfb360caa12d5d5bc186def3eb45._comment35
-rw-r--r--doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_3_9bb30ab62febe4ef63bed49f831a473a._comment8
-rw-r--r--doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_4_7832f0347a41b8204538c01b72487803._comment19
-rw-r--r--doc/forum/__34__Pairing__34___more_than_two_computers.mdwn11
-rw-r--r--doc/forum/__34__Pairing__34___more_than_two_computers/comment_1_80f7a4bb3c66b11e566043407b611bbf._comment10
-rw-r--r--doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__.mdwn10
-rw-r--r--doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_1_d90d1d599ce557af03c6f0f2ea188212._comment10
-rw-r--r--doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_2_58b1af497cab132acb28cb5f9283ec2a._comment8
-rw-r--r--doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__.mdwn38
-rw-r--r--doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_1_70200f871b9df49261f32752a6bb0e67._comment14
-rw-r--r--doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_2_173da510b45f0320ae8aa2df9f14ae7b._comment11
-rw-r--r--doc/forum/bash_completion.mdwn1
-rw-r--r--doc/forum/bash_completion/comment_1_5c42c0c8e7fc3224bf5406880f9fd0c4._comment8
-rw-r--r--doc/forum/bash_completion/comment_2_6cbe3c825db99bf9188a0de8bb937d5b._comment8
-rw-r--r--doc/forum/bash_completion/comment_3_948c40f1e46ca220d61365aebcd4f6d7._comment136
-rw-r--r--doc/forum/bash_completion/comment_4_dbae348b230b780cda91ed8576b8f9fa._comment8
-rw-r--r--doc/forum/cabal_install_fails_on_uuid.mdwn23
-rw-r--r--doc/forum/cabal_install_fails_on_uuid/comment_1_2a3963e21bc7ff526124b902cb0b6ad2._comment8
-rw-r--r--doc/forum/cabal_install_fails_on_uuid/comment_2_1609525998e2b36c04d67f4d988139c0._comment10
-rw-r--r--doc/forum/can_I_only_add_my_own_files__63__.mdwn27
-rw-r--r--doc/forum/can_I_only_add_my_own_files__63__/comment_1_767d647af9d0345f337338d6319071fa._comment10
-rw-r--r--doc/forum/can_I_only_add_my_own_files__63__/comment_2_0c3306ffb38b97b54e1e0436d12c1876._comment8
-rw-r--r--doc/forum/correct_way_to_add_two_preexisting_datasets.mdwn25
-rw-r--r--doc/forum/correct_way_to_add_two_preexisting_datasets/comment_1_c5c3ff25c9f5e34db222b5f4ae58b093._comment10
-rw-r--r--doc/forum/correct_way_to_add_two_preexisting_datasets/comment_2_ee3ecc86990ac5a8d0c4fdfb482a7594._comment16
-rw-r--r--doc/forum/correct_way_to_add_two_preexisting_datasets/comment_3_e29bf8b848da04c761dc601ac979ac14._comment11
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment.mdwn28
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_1_9f74449ec91577dbf6095f4beafac293._comment10
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_2_e034585c8b51cc30b35c1f7ae68205bf._comment14
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_3_fbbd47c3dbe8de24b0df664e4afd5cb8._comment14
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_4_55da5c3c41c13b08590ce1ff8117cef6._comment23
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_5_f67823351164ddfe7d595685c3679652._comment10
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_6_d5cc91164772849d027fed5f962d9000._comment10
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_7_cb4ec7ed3c39d0649133191a85ea6ab3._comment17
-rw-r--r--doc/forum/git-annex___38___ikiwiki_experiment/comment_8_86565e5e1508ff1862f88975446650a2._comment12
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working.mdwn12
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_1_209956f3812450a43986d4ca5e647da6._comment10
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_12a58b8efe545e09b64760c87849839b._comment12
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_e0f7328603256f25c3be3706ecc9c76c._comment12
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_4_6bb8e4522241556fb82784d9b834cbfe._comment10
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_5_89a5296b461d400b51006074a13a4560._comment8
-rw-r--r--doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_6_62daef4b4392c951b914a01b3effac11._comment8
-rw-r--r--doc/forum/git-annex_on_archlinuxarm__44___armv6.mdwn20
-rw-r--r--doc/forum/git-annex_on_archlinuxarm__44___armv6/comment_1_88fa644df8614c2db0d092b3eb1d3156._comment10
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram.mdwn24
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_1_ff16c7932b60b85c744bafc48bb040e4._comment13
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_2_5599cddf579d18f70cab6e48d04ae99d._comment12
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_3_412941e9385f63153b23695641e71deb._comment15
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_4_112ad140d9006c530db2121bec24de30._comment10
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_5_9178023b95683a649355f291165a1467._comment8
-rw-r--r--doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_6_9251203421c1c3c3aed7828c4b97ecb8._comment17
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files.mdwn34
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_1_2152cfb09675e46e7492e198dd3ea094._comment8
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_2_97e666dbac9de2a5e688921cba8a42e9._comment20
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_3_d7b0e9515bface28f3650b8aa20ec2f4._comment8
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_4_5816f6cab42e27e724e735368f693b09._comment8
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_5_8e97f39225515f0bf8b168dfd6a0efab._comment10
-rw-r--r--doc/forum/git-annex_unused_not_dropping_deleted_files/comment_6_bef37f8ec9c337387b79ffd6d56fe425._comment10
-rw-r--r--doc/forum/git-status_typechange_in_direct_mode.mdwn48
-rw-r--r--doc/forum/git-status_typechange_in_direct_mode/comment_1_12c8b67aadbfa2b073e12997a55d49a7._comment12
-rw-r--r--doc/forum/git-status_typechange_in_direct_mode/comment_2_005d1b17f3c2ae192aa30c6e5163989e._comment8
-rw-r--r--doc/forum/git_annex_assistant__44___share_with_other_devices.mdwn2
-rw-r--r--doc/forum/git_annex_sync_dies___40__sometimes__41__.mdwn22
-rw-r--r--doc/forum/git_annex_sync_dies___40__sometimes__41__/comment_1_48bbac0545bf13bbf04da723e418d037._comment14
-rw-r--r--doc/forum/git_annex_test_on_windows.mdwn5
-rw-r--r--doc/forum/howto_update_feed.mdwn14
-rw-r--r--doc/forum/howto_update_feed/comment_1_bec356619f370a618f19a187d09d2e35._comment8
-rw-r--r--doc/forum/howto_update_feed/comment_2_84dfb80ba3db8d41164eb97022becae3._comment8
-rw-r--r--doc/forum/howto_update_feed/comment_3_20166db298c10074e062aecad59ffd71._comment20
-rw-r--r--doc/forum/howto_update_feed/comment_4_f040e31b763fc9a7aa092442b4d6b8e8._comment20
-rw-r--r--doc/forum/known_and_local_annex_keys.mdwn14
-rw-r--r--doc/forum/known_and_local_annex_keys/comment_1_3cb4828dc7116e4cf49e119f055ae9a3._comment20
-rw-r--r--doc/forum/known_and_local_annex_keys/comment_2_68f20c881eafe986694bde10571cf1c0._comment10
-rw-r--r--doc/forum/known_and_local_annex_keys/comment_3_e195a7091a06ce0427bb28aca9a17d04._comment8
-rw-r--r--doc/forum/known_and_local_annex_keys/comment_4_d81f0bf7465832cb676fd89f5d53ec18._comment8
-rw-r--r--doc/forum/lost_in_walkthrough....txt78
-rw-r--r--doc/forum/lost_in_walkthrough.../comment_1_51b703b961ca762f0359e1c169f1ee75._comment8
-rw-r--r--doc/forum/lost_in_walkthrough.../comment_2_a9de0401a103bdd4401ba2d5983dc54a._comment11
-rw-r--r--doc/forum/manual_update_of_.git__47__annex__47__objects.txt8
-rw-r--r--doc/forum/manual_update_of_.git__47__annex__47__objects/comment_1_ea6ec91150c8962e2711631f2422bf3a._comment10
-rw-r--r--doc/forum/many_remotes.mdwn24
-rw-r--r--doc/forum/nfs_mounted_repo_results_in_errors_on_drop__47__move.mdwn4
-rw-r--r--doc/forum/nntp__47__usenet_special_remote/comment_2_48736ed17c98ffcfb13ec00b901b2dd6._comment13
-rw-r--r--doc/forum/non-bare_repo_on_cloud_remote/comment_2_71baea93f6caaf7b81a9ac00bee91e5e._comment67
-rw-r--r--doc/forum/preferred_content.mdwn11
-rw-r--r--doc/forum/preferred_content/comment_1_9c9e5f2ee5ae4d8459358ad16f879ef1._comment10
-rw-r--r--doc/forum/purge_files_with_no_copies.mdwn3
-rw-r--r--doc/forum/purge_files_with_no_copies/comment_1_12b578689eb8d5d38c06261ec65e2109._comment12
-rw-r--r--doc/forum/receiving_indirect_renames_on_direct_repo___63__.mdwn254
-rw-r--r--doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_1_f4b0a14373c75cb752597c832e296bcc._comment17
-rw-r--r--doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_2_8c86dfc99f0b9040402c9d746decda53._comment41
-rw-r--r--doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_3_0246fff6c7c75f6be45bd257ec3872a5._comment75
-rw-r--r--doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote.mdwn8
-rw-r--r--doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote/comment_1_c1962d757dd22f49e774afa13a9862ca._comment10
-rw-r--r--doc/forum/safely_dropping_git-annex_history/comment_11_383882fafd32f25ed22b5eb2fb3691b9._comment18
-rw-r--r--doc/forum/safely_dropping_git-annex_history/comment_12_47794a2abf29bf4ea2763ff89d872ab4._comment8
-rw-r--r--doc/forum/speed_up_assistant_startup_on_large_repositories.mdwn1
-rw-r--r--doc/forum/speed_up_assistant_startup_on_large_repositories/comment_1_5ba637a0f6d01ba24fe25e6265134e0a._comment10
-rw-r--r--doc/forum/speed_up_assistant_startup_on_large_repositories/comment_2_d65746697977f8971a4b59f5b413f926._comment13
-rw-r--r--doc/forum/speed_up_assistant_startup_on_large_repositories/comment_3_be6c4fe5a0c745688438b716973791cc._comment12
-rw-r--r--doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__.mdwn3
-rw-r--r--doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_1_7244794579a191a677190c60758f32e7._comment8
-rw-r--r--doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_2_277cf12907bd7c5930eb4f137b115e29._comment8
-rw-r--r--doc/forum/start_assistant_from_command_line.mdwn11
-rw-r--r--doc/forum/start_assistant_from_command_line/comment_1_f8dfce1fca9f1212ccaf84e431db71a9._comment12
-rw-r--r--doc/forum/start_assistant_from_command_line/comment_2_e769c5d09afbff85961363ddc5eb4019._comment10
-rw-r--r--doc/forum/taskwarrior.mdwn11
-rw-r--r--doc/forum/taskwarrior/comment_1_1c3a29e7d292cb602d9d349f8009b51e._comment10
-rw-r--r--doc/forum/ui/comment_2_b493ee97eb2378e72c12f3d137109580._comment15
-rw-r--r--doc/forum/unknown_response_from_git_cat-file.mdwn8
-rw-r--r--doc/forum/unknown_response_from_git_cat-file/comment_1_f26ba569e715fe69b6de3093930362ee._comment8
-rw-r--r--doc/forum/unlock__47__lock_always_gets_me/comment_2_f89b4349dde840c355a3bc28908decdf._comment8
-rw-r--r--doc/forum/webapp___47___assistant_without_watch.mdwn9
-rw-r--r--doc/forum/webapp___47___assistant_without_watch/comment_1_1bcd99aa81f937ded683e19a69d33dd9._comment10
-rw-r--r--doc/forum/webapp___47___assistant_without_watch/comment_2_9f5b3f5bf7fedcd5baec519d97d3aa8c._comment16
-rw-r--r--doc/git-annex-shell.mdwn4
-rw-r--r--doc/git-annex.mdwn605
-rw-r--r--doc/git-recover-repository.mdwn40
-rw-r--r--doc/how_it_works/comment_1_b3bdd6a06d5764db521ae54878131f5f._comment14
-rw-r--r--doc/install.mdwn4
-rw-r--r--doc/install/Android.mdwn36
-rw-r--r--doc/install/Android/comment_10_225f2c6fe255be93702cfbd4dc172f3b._comment8
-rw-r--r--doc/install/Android/comment_11_4e970633d9073fcf4bc33f3fff2525b2._comment10
-rw-r--r--doc/install/Android/comment_12_87da4f379a0276b662583e7e22061218._comment8
-rw-r--r--doc/install/Android/comment_5_40cb6cb72c4ad4aa19a4a40f41a6a757._comment13
-rw-r--r--doc/install/Android/comment_6_b0f723538e7328d5070c563f070858bd._comment8
-rw-r--r--doc/install/Android/comment_8_34f7c42050fa48769a6bfae60d72e477._comment8
-rw-r--r--doc/install/Android/comment_9_f3d289b78d6bdb3cc65689495a8439a5._comment11
-rw-r--r--doc/install/ArchLinux/comment_2_e5f923e6d81cfb3fba7a72f60baaf4ab._comment16
-rw-r--r--doc/install/ArchLinux/comment_3_8e607cd883ec174571e9dfe3b25bfd05._comment8
-rw-r--r--doc/install/ArchLinux/comment_4_a378391dd218859f381c479259dd8fe3._comment10
-rw-r--r--doc/install/Debian.mdwn6
-rw-r--r--doc/install/Debian/comment_14_a34e23d9aa3027012ab1236aa4f7d5cb._comment8
-rw-r--r--doc/install/Debian/comment_15_20d8271ba3f6cfe3c8849c3d41607630._comment8
-rw-r--r--doc/install/Fedora/comment_4_93b3402e4c51e1a5c96f907bb528164b._comment16
-rw-r--r--doc/install/Fedora/comment_5_0427e0503764b29e57abf9e97155136b._comment15
-rw-r--r--doc/install/Fedora/comment_6_1b1b38a79251fe2e8c1e4debbe3bc3c5._comment12
-rw-r--r--doc/install/Linux_standalone.mdwn5
-rw-r--r--doc/install/OSX.mdwn18
-rw-r--r--doc/install/OSX/comment_23_3d82a270dd4b0159f4aab5675166e1e3._comment30
-rw-r--r--doc/install/OSX/comment_24_b9d3563a2cc3d769f27876e028dc344d._comment12
-rw-r--r--doc/install/OSX/comment_25_db90984062a07576a4777b2d743161f1._comment24
-rw-r--r--doc/install/OSX/comment_27_2a60108a440231ba83f5a54b6bcc5488._comment14
-rw-r--r--doc/install/OSX/comment_27_d453510b9bb62072a4c663206c12c8a4._comment8
-rw-r--r--doc/install/OSX/comment_28_0970bfd63137ea48701dff6aea1b4bcb._comment18
-rw-r--r--doc/install/OSX/comment_29_8622ed56c6a8034c20fb311418d94003._comment8
-rw-r--r--doc/install/OSX/comment_30_ce58633ef5b2f8f4caa7e626358f33be._comment8
-rw-r--r--doc/install/OSX/comment_31_09084a7b3cf06bfa3add0f4991476ffe._comment10
-rw-r--r--doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment10
-rw-r--r--doc/install/OSX/comment_33_203a36322b3c453c05c8906c64e62e06._comment8
-rw-r--r--doc/install/OSX/comment_34_c9362141d15a2f68a75df9f8bfe29da0._comment17
-rw-r--r--doc/install/OSX/comment_35_8106196c3fef70652cb2106e2d5857db._comment8
-rw-r--r--doc/install/Ubuntu.mdwn12
-rw-r--r--doc/install/Ubuntu/comment_10_490e065314693423ab6969d8ae6978fe._comment8
-rw-r--r--doc/install/Ubuntu/comment_11_4ebac3fb43de854ed1a3b1d2ea94011a._comment10
-rw-r--r--doc/install/Ubuntu/comment_12_38f69dffe2db0d15e4c4e5cb47f40ef8._comment8
-rw-r--r--doc/install/Ubuntu/comment_9_c2f8b35ada873acb1ce593b04e2899fe._comment11
-rw-r--r--doc/install/Windows.mdwn3
-rw-r--r--doc/install/cabal.mdwn18
-rw-r--r--doc/install/cabal/comment_12_b93ca271dffca3f948645d3e1326c1d9._comment12
-rw-r--r--doc/install/cabal/comment_13_3dac019cda71bf99878c0a1d9382323b._comment8
-rw-r--r--doc/install/cabal/comment_14_14b46470593f84f8c3768a91cb77bdab._comment9
-rw-r--r--doc/install/cabal/comment_15_c3a5b0aad28a90e0bb8da31a430578eb._comment8
-rw-r--r--doc/install/cabal/comment_16_4faf214f97f9516898d7c17d743ef825._comment10
-rw-r--r--doc/install/cabal/comment_17_2a9d6807a3a13815c824985521757167._comment10
-rw-r--r--doc/install/cabal/comment_18_1efa0c7a963ec452fc6336fbe4964f6e._comment10
-rw-r--r--doc/install/cabal/comment_19_6f42f9234f9ff6a2ca6bbb4d2643843e._comment44
-rw-r--r--doc/install/cabal/comment_20_0f553be2a4c666e3bed58b2bce549406._comment8
-rw-r--r--doc/install/cabal/comment_21_f91a6ec21e96eced73ea9579fd8cbd15._comment8
-rw-r--r--doc/install/cabal/comment_22_2f27b78215f97ade1986ca806c634cb3._comment16
-rw-r--r--doc/install/cabal/comment_23_c34d2b1d95830a3e58671a5b566a1758._comment8
-rw-r--r--doc/install/cabal/comment_24_40cbde8ec067b3a860e6df1a9bea5f76._comment8
-rw-r--r--doc/install/cabal/comment_25_8a7664e6f9271718dc607a0782366c5b._comment8
-rw-r--r--doc/install/cabal/comment_26_bd455c732639728bce2bfc39e32871d2._comment8
-rw-r--r--doc/install/cabal/comment_27_c080e9239b6eec88d329c28da7bb4141._comment17
-rw-r--r--doc/install/cabal/comment_28_15951dd070a675300420eea137a28ef9._comment10
-rw-r--r--doc/install/fromscratch.mdwn6
-rw-r--r--doc/install/openSUSE.mdwn4
-rw-r--r--doc/internals.mdwn2
-rw-r--r--doc/internals/lockdown.mdwn44
-rw-r--r--doc/news/git_annex_fall_of_code.mdwn27
-rw-r--r--doc/news/version_4.20130621.mdwn40
-rw-r--r--doc/news/version_4.20130627.mdwn17
-rw-r--r--doc/news/version_4.20130709.mdwn35
-rw-r--r--doc/news/version_4.20130723.mdwn36
-rw-r--r--doc/news/version_4.20130802.mdwn44
-rw-r--r--doc/news/version_4.20130827/comment_1_937cbaccf235d6d9118aacd49058bb4f._comment11
-rw-r--r--doc/news/version_4.20130827/comment_2_faa5cf0645728b4ade850a691fa472db._comment25
-rw-r--r--doc/news/version_4.20130827/comment_3_ad156d6199b525884114ff823d265bf7._comment39
-rw-r--r--doc/news/version_4.20130827/comment_4_877061eb24d9d9543cc9cd229906bd64._comment8
-rw-r--r--doc/news/version_4.20130827/comment_5_8991648dda991768e3a58477a4c3c923._comment10
-rw-r--r--doc/news/version_4.20130909.mdwn36
-rw-r--r--doc/news/version_4.20131002.mdwn42
-rw-r--r--doc/news/version_4.20131024.mdwn43
-rw-r--r--doc/news/version_4.20131101.mdwn29
-rw-r--r--doc/news/version_4.20131106.mdwn18
-rw-r--r--doc/polls.mdwn2
-rw-r--r--doc/polls/2013.mdwn5
-rw-r--r--doc/preferred_content.mdwn12
-rw-r--r--doc/preferred_content/comment_10_f0bce3c67f293eaba97b92f0942876b6._comment8
-rw-r--r--doc/preferred_content/comment_9_f82538be42428691d7cab60a7add2e74._comment13
-rw-r--r--doc/related_software.mdwn1
-rw-r--r--doc/shortcuts.mdwn12
-rw-r--r--doc/special_remotes.mdwn14
-rw-r--r--doc/special_remotes/S3.mdwn9
-rw-r--r--doc/special_remotes/S3/comment_15_ceb9048c743135f6beca57a23505f0a3._comment8
-rw-r--r--doc/special_remotes/S3/comment_16_7b79f8b5ef88a2775d61b5ac5774d3e0._comment8
-rw-r--r--doc/special_remotes/bup.mdwn12
-rw-r--r--doc/special_remotes/directory.mdwn13
-rw-r--r--doc/special_remotes/gcrypt.mdwn45
-rw-r--r--doc/special_remotes/glacier.mdwn9
-rw-r--r--doc/special_remotes/hook.mdwn13
-rw-r--r--doc/special_remotes/rsync.mdwn14
-rw-r--r--doc/special_remotes/rsync/comment_10_43e8fa3517c1f5935f02ad06fbed63dc._comment8
-rw-r--r--doc/special_remotes/rsync/comment_11_8cafc1a8b37e6fb056185ec058c0c3e8._comment8
-rw-r--r--doc/special_remotes/rsync/comment_7_e122979ea811d9ef835ba05bb936190f._comment10
-rw-r--r--doc/special_remotes/rsync/comment_8_d566113318d0aa7500d76ffe1bd46069._comment10
-rw-r--r--doc/special_remotes/rsync/comment_9_5dcf10a502b2d4feac46b620d43e9d00._comment8
-rw-r--r--doc/special_remotes/web/comment_1_0bd570025f6cd551349ea88a4729ac8e._comment8
-rw-r--r--doc/special_remotes/web/comment_2_333141cc9ec6c26ffd19aa95303a91e3._comment8
-rw-r--r--doc/special_remotes/webdav.mdwn11
-rw-r--r--doc/special_remotes/xmpp.mdwn15
-rw-r--r--doc/special_remotes/xmpp/comment_3_48ddbba1402d89acaea07cff747c48e0._comment28
-rw-r--r--doc/special_remotes/xmpp/comment_4_59857879abaae22bde444a215e00bf18._comment14
-rw-r--r--doc/special_remotes/xmpp/comment_5_583ee374bd34fcc9ae26c2fd690e8c47._comment73
-rw-r--r--doc/special_remotes/xmpp/comment_6_8f0b5bba1271d031a67e7f0c175d67d5._comment8
-rw-r--r--doc/special_remotes/xmpp/comment_7_ac7acbded03325b015959d82ae77faf1._comment10
-rw-r--r--doc/special_remotes/xmpp/comment_8_81a9636a1e8a36a58185468a26f8633d._comment8
-rw-r--r--doc/sync/comment_5_18c396c59907147bb2bf713e55392b6b._comment8
-rw-r--r--doc/testimonials/comment_1_2bf439f7a3bc3d6fab91849017946182._comment8
-rw-r--r--doc/tips/Decentralized_repository_behind_a_Firewall.mdwn8
-rw-r--r--doc/tips/Git_annex_and_Calibre.mdwn120
-rw-r--r--doc/tips/Internet_Archive_via_S3.mdwn22
-rw-r--r--doc/tips/Internet_Archive_via_S3/comment_1_d53a3848c20dce61867283fc03c2adaa._comment34
-rw-r--r--doc/tips/Internet_Archive_via_S3/comment_2_91c1472da27b00e5d682d22bc1ef04e0._comment10
-rw-r--r--doc/tips/Internet_Archive_via_S3/comment_3_e23cf781c532f80d47d52265f2b2c87e._comment8
-rw-r--r--doc/tips/assume-unstaged.mdwn2
-rw-r--r--doc/tips/assume-unstaged/comment_2_5b589f37cfc03bf7be33a51826cc4dba._comment13
-rw-r--r--doc/tips/beware_of_SSD_wear_when_doing_fsck_on_large_special_remotes/comment_3_72d222020af4a9c6c753eb1ee7e1f1cf._comment8
-rw-r--r--doc/tips/centralized_git_repository_tutorial/comment_1_9072ebc0c61446d7b151fcfab616fea9._comment33
-rw-r--r--doc/tips/centralized_git_repository_tutorial/comment_2_528e92b21f0551fde4adb956654953ae._comment8
-rw-r--r--doc/tips/downloading_podcasts/comment_11_d8d77048c7e2524968c188e1ad517873._comment24
-rw-r--r--doc/tips/downloading_podcasts/comment_12_0859317471b43c88744dd3df95c879f7._comment10
-rw-r--r--doc/tips/downloading_podcasts/comment_13_e8c3c97282d17e2a1d47fb9d5e2b2f7b._comment18
-rw-r--r--doc/tips/downloading_podcasts/comment_14_05a3694052de36848fbbad6eeeada895._comment8
-rw-r--r--doc/tips/downloading_podcasts/comment_15_21028bed8858c2dae1ac9c2d014fd2a1._comment8
-rw-r--r--doc/tips/downloading_podcasts/comment_16_4869fb5c9f896acc477c44de06c36ca7._comment8
-rw-r--r--doc/tips/downloading_podcasts/comment_17_2e278ff200c1c15efd27c46a3e0aed40._comment9
-rw-r--r--doc/tips/downloading_podcasts/comment_18_382f2b970738d9b1af577955c3083e90._comment15
-rw-r--r--doc/tips/downloading_podcasts/comment_19_f76fc6835e5787b0156380bf09fd81ca._comment8
-rw-r--r--doc/tips/downloading_podcasts/comment_20_65ebf3a3bbf0a2aebd2b69640b757e16._comment10
-rw-r--r--doc/tips/finding_duplicate_files/comment_10_2ed5aa8c632048b13e01d358883fa383._comment12
-rw-r--r--doc/tips/finding_duplicate_files/comment_8_3af51722da0980b724facb184f0f66e9._comment10
-rw-r--r--doc/tips/finding_duplicate_files/comment_9_7b4b78a5cd253abfe4f6001049bf64f3._comment10
-rw-r--r--doc/tips/flickrannex.mdwn37
-rw-r--r--doc/tips/flickrannex/comment_13_1596e70dca71c853fd1d6fc9bde02b18._comment12
-rw-r--r--doc/tips/flickrannex/comment_13_cf9dad91ee7d334c720adb3310aa0003._comment130
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt.mdwn127
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_10_4440a80d64c60c7312d5c405d54e607a._comment15
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_1_5c54690586f2a781905ea4b25aa1147f._comment18
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_2_07feedb4348f8c31176cc744c19368a1._comment21
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_3_c2f873dffa015f1d72ad0c3921909316._comment8
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_4_f8a6e4415f4fe6da14f6a3b7334bc952._comment18
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_5_11b8e82d2a234f65b58b823e71c6d6a2._comment10
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_6_3e41948e1beffcf279bb05ef8e61cc07._comment16
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_7_4ce0b26b25b336f07b2e27246cdfba3e._comment16
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_8_49aa34d75d24a2066baa8a585bc9c2e9._comment14
-rw-r--r--doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_9_3784e0c828cd60b6a9075c2d32d070cc._comment14
-rw-r--r--doc/tips/imapannex.mdwn27
-rw-r--r--doc/tips/migrating_two_seperate_disconnected_directories_to_git_annex.mdwn77
-rw-r--r--doc/tips/offline_archive_drives.mdwn69
-rw-r--r--doc/tips/offline_archive_drives/comment_1_3d4fdf42191a9d81434d00f51c3609ff._comment12
-rw-r--r--doc/tips/offline_archive_drives/comment_2_864c752aa8d064791a4b14dbbe2e6882._comment15
-rw-r--r--doc/tips/offline_archive_drives/comment_3_7be2ccaf70c9ecfc9a34384e0e31f490._comment10
-rw-r--r--doc/tips/powerful_file_matching.mdwn2
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository.mdwn17
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_1_f5827be97f78dbae113a5ba0c9ced896._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_2_e98df7275bb032308bb87e3607bdde32._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_3_11bece6dfac090edbcd783b266c482a3._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_4_86e99017f7585ac2f76753051214637e._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_6_c8953732ce353cdf0c4fb81ddc98c04a._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_6_d0da84df0241dc6ccf0aa0c7598917df._comment8
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_7_addf49556e4c33d55a41c393f519d0a4._comment10
-rw-r--r--doc/tips/recovering_from_a_corrupt_git_repository/comment_8_505a2fc2b841fe8eb419801f923ef35f._comment8
-rw-r--r--doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_6_6a5d6af107b297afd008b021f73d787b._comment8
-rw-r--r--doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_7_74d57cf503a86d8f7ace2d769dbb58be._comment10
-rw-r--r--doc/tips/setup_a_public_repository_on_a_web_site.mdwn44
-rw-r--r--doc/tips/shared_git_annex_directory_between_multiple_users.mdwn39
-rw-r--r--doc/tips/using_Amazon_Glacier.mdwn2
-rw-r--r--doc/tips/using_Amazon_S3.mdwn2
-rw-r--r--doc/tips/using_box.com_as_a_special_remote.mdwn2
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_13_75218b7409c0e281cb01c9b2791e8cdf._comment20
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_14_7d4d4515218d1259d32be3baeb5ee56e._comment13
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_15_dc6f21b5a3d5931c8d949a9753411b9e._comment29
-rw-r--r--doc/tips/using_gitolite_with_git-annex/comment_16_8e5039e6655fc80dc863b6cdf44ef02a._comment15
-rw-r--r--doc/tips/using_the_web_as_a_special_remote.mdwn54
-rw-r--r--doc/tips/yet_another_simple_disk_usage_like_utility/comment_1_41b212bde8bc88d2a5dea93bd0dc75f1._comment2
-rw-r--r--doc/tips/yet_another_simple_disk_usage_like_utility/comment_2_73698913837bfd5a58cf15721211e43e._comment8
-rw-r--r--doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_5_677e958c3f2effec7528b484aeb6478d._comment13
-rw-r--r--doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_6_56e53803fdede895cba717e6b6e9a1bb._comment23
-rw-r--r--doc/todo/Bittorrent-like_features.mdwn62
-rw-r--r--doc/todo/Bittorrent-like_features/comment_1_f4c110ef35ebf4fd89f06edf2c4f0c48._comment13
-rw-r--r--doc/todo/Build_for_Synology_DSM/comment_13_314255fd503d125b5aeae2f62acfd592._comment8
-rw-r--r--doc/todo/Build_for_Synology_DSM/comment_15_9525cd0d75ff4c15182d10a855774b69._comment30
-rw-r--r--doc/todo/Deleting_Unused_Files_by_Age.mdwn13
-rw-r--r--doc/todo/Option_for_browser_to_launch_webapp_with.mdwn7
-rw-r--r--doc/todo/Show_repo_type_in_repo_list.mdwn1
-rw-r--r--doc/todo/Show_repo_type_in_repo_list/comment_1_ac6eb1072ef902a094b79dd8e0917c4d._comment10
-rw-r--r--doc/todo/Show_repo_type_in_repo_list/comment_2_6979c487f707a724a048d20e2e5744e6._comment14
-rw-r--r--doc/todo/Show_repo_type_in_repo_list/comment_3_529254a6cc20de7259d60a3cbc5ccaf7._comment8
-rw-r--r--doc/todo/Sync_repo_names__63__.mdwn10
-rw-r--r--doc/todo/Wishlist:_additional_environment_variables_for_hooks.mdwn14
-rw-r--r--doc/todo/Wishlist:_sanitychecker_fix_wrong_UUID__47__duplicate_remote.mdwn7
-rw-r--r--doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex.mdwn3
-rw-r--r--doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex/comment_1_0cc16eb17151309113cec6d1cccf203d._comment20
-rw-r--r--doc/todo/__96__git_annex_status__47__version__96___should_print_the_local_OS.mdwn6
-rw-r--r--doc/todo/__96__git_annex_sync_--auto__96___or___96__git_annex_auto__96___--_synchronize_symlinks__44___tracking_info__44___and_actual_data.mdwn3
-rw-r--r--doc/todo/add_metadata_to_annexed_files.mdwn5
-rw-r--r--doc/todo/add_metadata_to_annexed_files/comment_1_38af9b352020194e9ace34d7dde188cf._comment10
-rw-r--r--doc/todo/checksum_verification_on_transfer.mdwn7
-rw-r--r--doc/todo/checksum_verification_on_transfer/comment_1_30f77e631608b9751f9032f97d58cc30._comment17
-rw-r--r--doc/todo/direct_mode_guard.mdwn83
-rw-r--r--doc/todo/direct_mode_guard/comment_2_85bdb9dc601b87bd7c77150d7b0a5cde._comment8
-rw-r--r--doc/todo/faster_gnupg_cipher.mdwn10
-rw-r--r--doc/todo/faster_gnupg_cipher/comment_3_bd0c975494333dfe558de048d888ace8._comment17
-rw-r--r--doc/todo/faster_rsync_remotes.mdwn3
-rw-r--r--doc/todo/http_git_annex_404_retry.mdwn16
-rw-r--r--doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template.mdwn5
-rw-r--r--doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_1_62752c760fc12eca0c34d67d58753d00._comment10
-rw-r--r--doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_2_21672360060f48bc2eacfa535ff4c94d._comment11
-rw-r--r--doc/todo/keep_annexed_files_for_a_while.mdwn8
-rw-r--r--doc/todo/makefile:_respect___36__PREFIX.mdwn25
-rw-r--r--doc/todo/mdwn2man:_make_backticks_bold.mdwn22
-rw-r--r--doc/todo/nicer_whereis_output.mdwn100
-rw-r--r--doc/todo/redundancy_stats_in_status/comment_2_686ced0684d10511caf07953c64cd5b6._comment10
-rw-r--r--doc/todo/smudge/comment_3_4e7c25fe24a1e71f58a8354fa64f41c2._comment10
-rw-r--r--doc/todo/support_for_lossy_remotes.mdwn6
-rw-r--r--doc/todo/sync_my_local_git-annex_from_a_dump_remote.mdwn6
-rw-r--r--doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_1_81d63854f89f00855cda5ace0fc8262a._comment14
-rw-r--r--doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_2_66822b72b1450e79e8edd0c6c21d5aa6._comment14
-rw-r--r--doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_3_b9f73375e2c732e798495f8ee6970c7c._comment14
-rw-r--r--doc/todo/untracked_remotes.mdwn9
-rw-r--r--doc/todo/whishlist:_git_annex_drop_--dry-run.mdwn5
-rw-r--r--doc/todo/whishlist:_git_annex_drop_--dry-run/comment_1_20ecfa8ffa52c238d21b904076ac69a2._comment10
-rw-r--r--doc/todo/whishlist:_git_annex_drop_--dry-run/comment_2_d19bc268c9467d24baa8d8f77a6e5e09._comment8
-rw-r--r--doc/todo/windows_support.mdwn10
-rw-r--r--doc/todo/wishlist:_Freeing_X_space_on_remote_Y.mdwn1
-rw-r--r--doc/todo/wishlist:___34__quiet__34___annex_get_for_centralized_use_case.mdwn5
-rw-r--r--doc/todo/wishlist:___39__get__39___queue_and_schedule..mdwn30
-rw-r--r--doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__.mdwn5
-rw-r--r--doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_1_c83a6cddd0ce222205a149cfa41ca395._comment10
-rw-r--r--doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_2_353fbc2bcc40cb8c9af42907a34c6e5a._comment11
-rw-r--r--doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp.mdwn6
-rw-r--r--doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_1_b89e90f9a70748c95aaf81740a40b76e._comment8
-rw-r--r--doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_2_d64361380cb18b98ddb43ada1c9f540a._comment8
-rw-r--r--doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods.mdwn5
-rw-r--r--doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods/comment_1_abb6263f3807160222bba1122475c89c._comment8
-rw-r--r--doc/todo/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn (renamed from doc/bugs/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn)0
-rw-r--r--doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync.mdwn1
-rw-r--r--doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_1_db632de391ce9fce42af51a770ed3aeb._comment10
-rw-r--r--doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_2_4a0931d9884054d764fde315d4fe4851._comment14
-rw-r--r--doc/todo/wishlist:_annex.largefiles_support_for_mimetypes/comment_1_304431bb62b5b8a64edc37a11bbaff59._comment8
-rw-r--r--doc/todo/wishlist:_archive_from_remote_with_the_least_free_space.mdwn1
-rw-r--r--doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_1_6813fdc7ecc98765a5d35d34163a1712._comment8
-rw-r--r--doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_2_21a249cedca1ceb80d10784004735524._comment8
-rw-r--r--doc/todo/wishlist:_detection_of_merge_conflicts.mdwn13
-rw-r--r--doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied.mdwn6
-rw-r--r--doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_1_d2665e7347689b520d37561cfddf0aa8._comment8
-rw-r--r--doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_2_db153571a32fb072453ed583e3e9ccf4._comment8
-rw-r--r--doc/todo/wishlist:_display_status_of_remotes_in_the_webapp.mdwn1
-rw-r--r--doc/todo/wishlist:_dropping_git-annex_history.mdwn28
-rw-r--r--doc/todo/wishlist:_dropping_git-annex_history/comment_1_a4bee2e26b22a9bdaadc05b7227769ef._comment10
-rw-r--r--doc/todo/wishlist:_dropping_git-annex_history/comment_2_f6d750bfe0c9d8a2aa6bc218ca5c49cc._comment14
-rw-r--r--doc/todo/wishlist:_encrypted_git_remote_on_hosting_site_from_webapp.mdwn1
-rw-r--r--doc/todo/wishlist:_generic_annex.cost-command.mdwn (renamed from doc/bugs/wishlist:_generic_annex.cost-command.mdwn)0
-rw-r--r--doc/todo/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn (renamed from doc/bugs/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn)0
-rw-r--r--doc/todo/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn (renamed from doc/bugs/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn)0
-rw-r--r--doc/todo/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn (renamed from doc/bugs/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn)0
-rw-r--r--doc/todo/wishlist:_perform_fsck_remotely.mdwn39
-rw-r--r--doc/todo/wishlist:_perform_fsck_remotely/comment_1_db92311dcdb1ef0ab0413f83e191c70c._comment15
-rw-r--r--doc/todo/wishlist:_perform_fsck_remotely/comment_2_2f0dbaf143d94290bfbebb6869eb7241._comment12
-rw-r--r--doc/todo/wishlist:_query_things_like_description__44___trust_level.mdwn (renamed from doc/bugs/wishlist:_query_things_like_description__44___trust_level.mdwn)0
-rw-r--r--doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment (renamed from doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment)0
-rw-r--r--doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment (renamed from doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment)0
-rw-r--r--doc/todo/wishlist:_simple_url_for_webapp.mdwn (renamed from doc/bugs/wishlist:_simple_url_for_webapp.mdwn)0
-rw-r--r--doc/todo/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment (renamed from doc/bugs/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment)0
-rw-r--r--doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote.mdwn10
-rw-r--r--doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_2_81f7f893ac36c145b31f02db6a682a17._comment20
-rw-r--r--doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_3_a7e3cd68c5e5f05139151a58f358df95._comment13
-rw-r--r--doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_4_a57947ed257b28bbe995a68bfeb5eeaa._comment8
-rw-r--r--doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_5_a0612ae05dbda7f7935be648b42b30fc._comment8
-rw-r--r--doc/todo/wishlist:_support_drop__44___find_on_special_remotes.mdwn (renamed from doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn)0
-rw-r--r--doc/todo/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment (renamed from doc/bugs/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment)0
-rw-r--r--doc/todo/wishlist:_unify_directory_scheme_for_the_store.mdwn20
-rw-r--r--doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_1_44da58beaaab359ecaba7fb905ca4ae1._comment10
-rw-r--r--doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_2_bc698c501ecdb56df57171f4f3bb831a._comment16
-rw-r--r--doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_3_e555d0dbbaa05528806905c6a940724b._comment8
-rw-r--r--doc/todo/wishlist:_use_hardlinks_for_local_clones.mdwn9
-rw-r--r--doc/todo/wishlist:_use_hardlinks_for_local_clones/comment_1_85064fafe472a5bd395d60ce8f7acb56._comment12
-rw-r--r--doc/todo/wishlist_degraded_files.mdwn5
-rw-r--r--doc/upgrades.mdwn12
-rw-r--r--doc/upgrades/gcrypt.mdwn25
-rw-r--r--doc/upgrades/gcrypt/comment_1_606c1527735996ae671f78948e4ad84b._comment8
-rw-r--r--doc/use_case/Bob.mdwn4
-rw-r--r--doc/users/anarcat.mdwn41
-rw-r--r--doc/users/chrysn.mdwn12
-rw-r--r--doc/users/clacke.mdwn3
-rw-r--r--doc/users/tobiastheviking.mdwn20
-rw-r--r--doc/walkthrough/getting_file_content.mdwn2
-rw-r--r--doc/walkthrough/syncing.mdwn10
-rw-r--r--git-annex.cabal67
-rw-r--r--git-recover-repository.hs42
-rw-r--r--standalone/android/Makefile52
-rw-r--r--standalone/android/abiversion1
-rwxr-xr-xstandalone/android/buildchroot27
-rwxr-xr-xstandalone/android/buildchroot-inchroot25
-rwxr-xr-xstandalone/android/buildchroot-inchroot-asuser38
-rwxr-xr-xstandalone/android/clean-haskell-packages6
-rw-r--r--standalone/android/evilsplicer-headers.hs7
-rw-r--r--standalone/android/haskell-patches/DAV_0.3-0001-build-without-TH.patch306
-rw-r--r--standalone/android/haskell-patches/DAV_build-without-TH.patch377
-rw-r--r--standalone/android/haskell-patches/HTTP_4000.2.8-0001-build-with-base-4.8.patch24
-rw-r--r--standalone/android/haskell-patches/MonadCatchIO-transformers_hack-to-get-to-build-with-new-ghc.patch56
-rw-r--r--standalone/android/haskell-patches/SafeSemaphore_fix-build-with-new-base.patch36
-rw-r--r--standalone/android/haskell-patches/aeson_0.6.1.0_0001-disable-TH.patch24
-rw-r--r--standalone/android/haskell-patches/async_fix-build-with-new-ghc.patch (renamed from standalone/android/haskell-patches/async_2.0.1.4_0001-allow-building-with-unreleased-ghc.patch)12
-rw-r--r--standalone/android/haskell-patches/bloomfilter_fix-build-with-newer-base.patch26
-rw-r--r--standalone/android/haskell-patches/case-insensitive_0.4.0.1_0001-allow-building-with-unreleased-ghc.patch27
-rw-r--r--standalone/android/haskell-patches/certificate_1.3.7-0001-support-Android-cert-store.patch37
-rw-r--r--standalone/android/haskell-patches/cipher-aes_0.1.7-0001-fix-cross-build.patch34
-rw-r--r--standalone/android/haskell-patches/comonad_cross-build.patch25
-rw-r--r--standalone/android/haskell-patches/crypto-numbers_build-fix.patch235
-rw-r--r--standalone/android/haskell-patches/distributive_0.3-0001-fixes-for-cross-build.patch32
-rw-r--r--standalone/android/haskell-patches/dns_0.3.6-0001-use-getprop-to-get-dns-server.patch73
-rw-r--r--standalone/android/haskell-patches/entropy_cross-build.patch25
-rw-r--r--standalone/android/haskell-patches/file-embed_0.0.4.7-0001-remove-TH-and-export-one-symbol-used-by-TH.patch193
-rw-r--r--standalone/android/haskell-patches/gnuidn_fix-build-with-new-base.patch50
-rw-r--r--standalone/android/haskell-patches/hS3_0.5.7_0001-fix-build.patch23
-rw-r--r--standalone/android/haskell-patches/hamlet_1.1.6.1_0001-remove-TH.patch294
-rw-r--r--standalone/android/haskell-patches/language-javascript_fix-build-with-new-ghc.patch25
-rw-r--r--standalone/android/haskell-patches/lens_various-hacking-to-cross-build.patch (renamed from standalone/android/haskell-patches/lens_3.8.5-0001-build-without-TH.patch)194
-rw-r--r--standalone/android/haskell-patches/libxml-sax_0.7.3-0001-static-link-with-libxml2.patch27
-rw-r--r--standalone/android/haskell-patches/lifted-base_0.2.0.2_0001-hacked-for-newer-ghc.patch163
-rw-r--r--standalone/android/haskell-patches/lifted-base_crossbuild.patch25
-rw-r--r--standalone/android/haskell-patches/monad-control_0.3.1.4_0001-build-with-newer-ghc.patch25
-rw-r--r--standalone/android/haskell-patches/monad-logger_0.2.3.2_0001-remove-TH-logging-stuff.patch124
-rw-r--r--standalone/android/haskell-patches/network-conduit_0.6.2.2_0001-NoDelay-does-not-work-on-Android.patch43
-rw-r--r--standalone/android/haskell-patches/network-protocol-xmpp_0.4.4-0001-avoid-using-gnuidn.patch60
-rw-r--r--standalone/android/haskell-patches/network_2.4.1.0_0003-configure-misdetects-accept4.patch22
-rw-r--r--standalone/android/haskell-patches/persistent-template_stub-out.patch25
-rw-r--r--standalone/android/haskell-patches/persistent_1.1.5.1_0001-disable-TH.patch73
-rw-r--r--standalone/android/haskell-patches/process_fix-build-with-new-ghc.patch24
-rw-r--r--standalone/android/haskell-patches/resourcet_0.4.4_0001-hack-to-build-with-hacked-up-lifted-base-which-is-cu.patch44
-rw-r--r--standalone/android/haskell-patches/shakespeare-css_1.0.2_0001-remove-TH.patch164
-rw-r--r--standalone/android/haskell-patches/shakespeare-i18n_1.0.0.2_0001-remove-TH.patch162
-rw-r--r--standalone/android/haskell-patches/shakespeare-js_1.1.2_0001-remove-TH.patch308
-rw-r--r--standalone/android/haskell-patches/shakespeare_1.0.3_0001-export-symbol-used-by-TH-splices.patch143
-rw-r--r--standalone/android/haskell-patches/shakespeare_1.0.3_0001-remove-TH.patch208
-rw-r--r--standalone/android/haskell-patches/skein_hardcode_little-endian.patch24
-rw-r--r--standalone/android/haskell-patches/socks_0.4.2_0001-remove-IPv6-stuff.patch158
-rw-r--r--standalone/android/haskell-patches/split_0.2.1.2_0001-modify-to-build-with-unreleased-ghc.patch25
-rw-r--r--standalone/android/haskell-patches/stm-chans_cross-build.patch25
-rw-r--r--standalone/android/haskell-patches/syb_0.3.7_0001-hack-for-cross-compiling.patch25
-rw-r--r--standalone/android/haskell-patches/unix-time_0.1.4_0001-hacks-for-android.patch81
-rw-r--r--standalone/android/haskell-patches/unix-time_hack-for-Bionic.patch56
-rw-r--r--standalone/android/haskell-patches/unix_2.6.0.1_0001-remove-stuff-not-available-on-Android.patch91
-rw-r--r--standalone/android/haskell-patches/uuid_build-without-v1-uuid-which-needs-network-info.patch79
-rw-r--r--standalone/android/haskell-patches/vector_hack-to-build-with-new-ghc.patch (renamed from standalone/android/haskell-patches/vector_0.10.0.1_0001-disable-optimisation-that-breaks-when-cross-compilin.patch)9
-rw-r--r--standalone/android/haskell-patches/wai-app-static_deal-with-TH.patch (renamed from standalone/android/haskell-patches/wai-app-static_1.3.1-remove-TH.patch)34
-rw-r--r--standalone/android/haskell-patches/wai-extra_1.3.2.1_0001-disable-CGI-module.patch26
-rw-r--r--standalone/android/haskell-patches/xml-hamlet_0.4.0.3-0001-remove-TH-code.patch108
-rw-r--r--standalone/android/haskell-patches/yesod-auth_don-t-really-build.patch34
-rw-r--r--standalone/android/haskell-patches/yesod-core_1.1.8_0001-remove-TH.patch476
-rw-r--r--standalone/android/haskell-patches/yesod-core_1.1.8_0002-replaced-TH-in-Yesod.Internal.Core.patch267
-rw-r--r--standalone/android/haskell-patches/yesod-core_1.1.8_0003-exports-for-TH-splices.patch26
-rw-r--r--standalone/android/haskell-patches/yesod-core_expand_TH.patch411
-rw-r--r--standalone/android/haskell-patches/yesod-default_1.1.3.2_0001-remove-TH.patch102
-rw-r--r--standalone/android/haskell-patches/yesod-form_1.2.1.1-0001-prepare-for-Evil-Splicer.patch83
-rw-r--r--standalone/android/haskell-patches/yesod-form_1.2.1.1-0002-expand-TH.patch1606
-rw-r--r--standalone/android/haskell-patches/yesod-form_spliced-TH.patch1783
-rw-r--r--standalone/android/haskell-patches/yesod-persistent_1.1.0.1_0001-avoid-TH.patch41
-rw-r--r--standalone/android/haskell-patches/yesod-persistent_do-not-really-build.patch26
-rw-r--r--standalone/android/haskell-patches/yesod-routes_1.1.2_0001-remove-TH-and-export-module-used-by-TH-splices.patch674
-rw-r--r--standalone/android/haskell-patches/yesod-routes_export-module-referenced-by-TH-splices.patch29
-rw-r--r--standalone/android/haskell-patches/yesod-static_1.1.2-remove-TH.patch174
-rw-r--r--standalone/android/haskell-patches/yesod_001_hacked-up-for-Android.patch74
-rw-r--r--standalone/android/haskell-patches/yesod_002_hack-around-missing-symbols.patch41
-rw-r--r--standalone/android/haskell-patches/yesod_1.1.8_0001-hacked-up-to-build-on-Android.patch157
-rw-r--r--standalone/android/haskell-patches/zlib_0.5.4.0_0001-hack-to-build-on-Android.patch13
-rwxr-xr-xstandalone/android/install-haskell-packages265
-rw-r--r--standalone/android/term.patch2
-rw-r--r--standalone/licences.gzbin60510 -> 60519 bytes
-rw-r--r--standalone/windows/build.sh7
-rw-r--r--standalone/windows/haskell-patches/MissingH_1.2.0.0-0001-hack-around-strange-build-problem-in-jenkins-autobui.patch48
1579 files changed, 40023 insertions, 10269 deletions
diff --git a/.gitignore b/.gitignore
index 717b58abc..221087847 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+tags
+Setup
+*.hi
+*.o
tmp
test
build-stamp
@@ -9,7 +13,10 @@ Build/OSXMkLibs
git-annex
git-annex.1
git-annex-shell.1
+git-union-merge
git-union-merge.1
+git-recover-repository
+git-recover-repository.1
doc/.ikiwiki
html
*.tix
@@ -22,7 +29,3 @@ cabal-dev
# OSX related
.DS_Store
.virthualenv
-tags
-Setup
-*.hi
-*.o
diff --git a/Annex.hs b/Annex.hs
index 7625fa8b6..b634041db 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -5,14 +5,13 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies, MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Annex (
Annex,
AnnexState(..),
PreferredContentMap,
new,
- newState,
run,
eval,
getState,
@@ -41,10 +40,12 @@ import Control.Concurrent
import Common
import qualified Git
import qualified Git.Config
+import Git.Types hiding (remotes)
import Git.CatFile
import Git.CheckAttr
import Git.CheckIgnore
import Git.SharedRepository
+import Git.Config
import qualified Git.Queue
import Types.Backend
import Types.GitConfig
@@ -108,12 +109,13 @@ data AnnexState = AnnexState
, fields :: M.Map String String
, cleanup :: M.Map String (Annex ())
, inodeschanged :: Maybe Bool
+ , useragent :: Maybe String
}
newState :: Git.Repo -> AnnexState
-newState gitrepo = AnnexState
- { repo = gitrepo
- , gitconfig = extractGitConfig gitrepo
+newState r = AnnexState
+ { repo = if annexDirect c then fixupDirect r else r
+ , gitconfig = c
, backends = []
, remotes = []
, output = defaultMessageState
@@ -141,7 +143,10 @@ newState gitrepo = AnnexState
, fields = M.empty
, cleanup = M.empty
, inodeschanged = Nothing
+ , useragent = Nothing
}
+ where
+ c = extractGitConfig r
{- Makes an Annex state object for the specified git repo.
- Ensures the config is read, if it was not already. -}
@@ -245,3 +250,17 @@ withCurrentState :: Annex a -> Annex (IO a)
withCurrentState a = do
s <- getState id
return $ eval s a
+
+{- Direct mode repos have core.bare=true, but are not really bare.
+ - Fix up the Repo to be a non-bare repo, and arrange for git commands
+ - run by git-annex to be passed parameters that override this setting. -}
+fixupDirect :: Git.Repo -> Git.Repo
+fixupDirect r@(Repo { location = Local { gitdir = d, worktree = Nothing } }) =
+ r
+ { location = Local { gitdir = d </> ".git", worktree = Just d }
+ , gitGlobalOpts = gitGlobalOpts r ++
+ [ Param "-c"
+ , Param $ coreBare ++ "=" ++ boolConfig False
+ ]
+ }
+fixupDirect r = r
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index bc3736a9a..5978260a1 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -1,6 +1,6 @@
{- management of the git-annex branch
-
- - Copyright 2011-2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2011-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -20,11 +20,16 @@ module Annex.Branch (
get,
change,
commit,
+ forceCommit,
files,
withIndex,
+ performTransitions,
) where
import qualified Data.ByteString.Lazy.Char8 as L
+import qualified Data.Set as S
+import qualified Data.Map as M
+import qualified Control.Exception as E
import Common.Annex
import Annex.BranchState
@@ -32,6 +37,7 @@ import Annex.Journal
import qualified Git
import qualified Git.Command
import qualified Git.Ref
+import qualified Git.Sha
import qualified Git.Branch
import qualified Git.UnionMerge
import qualified Git.UpdateIndex
@@ -42,6 +48,13 @@ import Annex.CatFile
import Annex.Perms
import qualified Annex
import Utility.Env
+import Logs
+import Logs.Transitions
+import Logs.Trust.Pure
+import Annex.ReplaceFile
+import qualified Annex.Queue
+import Annex.Branch.Transitions
+import Annex.Exception
{- Name of the branch that is used to store git-annex's information. -}
name :: Git.Ref
@@ -110,6 +123,9 @@ forceUpdate = updateTo =<< siblingBranches
- later get staged, and might overwrite changes made during the merge.
- This is only done if some of the Refs do need to be merged.
-
+ - Also handles performing any Transitions that have not yet been
+ - performed, in either the local branch, or the Refs.
+ -
- Returns True if any refs were merged in, False otherwise.
-}
updateTo :: [(Git.Ref, Git.Branch)] -> Annex Bool
@@ -117,65 +133,71 @@ updateTo pairs = do
-- ensure branch exists, and get its current ref
branchref <- getBranch
dirty <- journalDirty
- (refs, branches) <- unzip <$> filterM isnewer pairs
+ ignoredrefs <- getIgnoredRefs
+ (refs, branches) <- unzip <$> filterM (isnewer ignoredrefs) pairs
if null refs
{- Even when no refs need to be merged, the index
- may still be updated if the branch has gotten ahead
- of the index. -}
- then whenM (needUpdateIndex branchref) $ lockJournal $ do
- forceUpdateIndex branchref
+ then whenM (needUpdateIndex branchref) $ lockJournal $ \jl -> do
+ forceUpdateIndex jl branchref
{- When there are journalled changes
- as well as the branch being updated,
- a commit needs to be done. -}
when dirty $
- go branchref True [] []
+ go branchref True [] [] jl
else lockJournal $ go branchref dirty refs branches
return $ not $ null refs
where
- isnewer (r, _) = inRepo $ Git.Branch.changed fullname r
- go branchref dirty refs branches = withIndex $ do
- cleanjournal <- if dirty then stageJournal else return noop
+ isnewer ignoredrefs (r, _)
+ | S.member r ignoredrefs = return False
+ | otherwise = inRepo $ Git.Branch.changed fullname r
+ go branchref dirty refs branches jl = withIndex $ do
+ cleanjournal <- if dirty then stageJournal jl else return noop
let merge_desc = if null branches
then "update"
else "merging " ++
unwords (map Git.Ref.describe branches) ++
" into " ++ show name
+ localtransitions <- parseTransitionsStrictly "local"
+ <$> getLocal transitionsLog
unless (null branches) $ do
showSideAction merge_desc
- mergeIndex refs
- ff <- if dirty
- then return False
- else inRepo $ Git.Branch.fastForward fullname refs
- if ff
- then updateIndex branchref
- else commitBranch branchref merge_desc
- (nub $ fullname:refs)
+ mergeIndex jl refs
+ let commitrefs = nub $ fullname:refs
+ unlessM (handleTransitions jl localtransitions commitrefs) $ do
+ ff <- if dirty
+ then return False
+ else inRepo $ Git.Branch.fastForward fullname refs
+ if ff
+ then updateIndex jl branchref
+ else commitIndex jl branchref merge_desc commitrefs
liftIO cleanjournal
{- Gets the content of a file, which may be in the journal, or in the index
- (and committed to the branch).
-
- Updates the branch if necessary, to ensure the most up-to-date available
- - content is available.
+ - content is returned.
-
- Returns an empty string if the file doesn't exist yet. -}
get :: FilePath -> Annex String
get file = do
update
- get' file
+ getLocal file
{- Like get, but does not merge the branch, so the info returned may not
- reflect changes in remotes.
- (Changing the value this returns, and then merging is always the
- same as using get, and then changing its value.) -}
-getStale :: FilePath -> Annex String
-getStale = get'
-
-get' :: FilePath -> Annex String
-get' file = go =<< getJournalFile file
+getLocal :: FilePath -> Annex String
+getLocal file = go =<< getJournalFileStale file
where
go (Just journalcontent) = return journalcontent
- go Nothing = withIndex $ L.unpack <$> catFile fullname file
+ go Nothing = getRaw file
+
+getRaw :: FilePath -> Annex String
+getRaw file = withIndex $ L.unpack <$> catFile fullname file
{- Applies a function to modifiy the content of a file.
-
@@ -183,18 +205,23 @@ get' file = go =<< getJournalFile file
- modifes the current content of the file on the branch.
-}
change :: FilePath -> (String -> String) -> Annex ()
-change file a = lockJournal $ a <$> getStale file >>= set file
+change file a = lockJournal $ \jl -> a <$> getLocal file >>= set jl file
{- Records new content of a file into the journal -}
-set :: FilePath -> String -> Annex ()
+set :: JournalLocked -> FilePath -> String -> Annex ()
set = setJournalFile
{- Stages the journal, and commits staged changes to the branch. -}
commit :: String -> Annex ()
-commit message = whenM journalDirty $ lockJournal $ do
- cleanjournal <- stageJournal
+commit = whenM journalDirty . forceCommit
+
+{- Commits the current index to the branch even without any journalleda
+ - changes. -}
+forceCommit :: String -> Annex ()
+forceCommit message = lockJournal $ \jl -> do
+ cleanjournal <- stageJournal jl
ref <- getBranch
- withIndex $ commitBranch ref message [fullname]
+ withIndex $ commitIndex jl ref message [fullname]
liftIO cleanjournal
{- Commits the staged changes in the index to the branch.
@@ -215,17 +242,18 @@ commit message = whenM journalDirty $ lockJournal $ do
- previous point, though getting it a long time ago makes the race
- more likely to occur.
-}
-commitBranch :: Git.Ref -> String -> [Git.Ref] -> Annex ()
-commitBranch branchref message parents = do
+commitIndex :: JournalLocked -> Git.Ref -> String -> [Git.Ref] -> Annex ()
+commitIndex jl branchref message parents = do
showStoringStateAction
- commitBranch' branchref message parents
-commitBranch' :: Git.Ref -> String -> [Git.Ref] -> Annex ()
-commitBranch' branchref message parents = do
- updateIndex branchref
+ commitIndex' jl branchref message parents
+commitIndex' :: JournalLocked -> Git.Ref -> String -> [Git.Ref] -> Annex ()
+commitIndex' jl branchref message parents = do
+ updateIndex jl branchref
committedref <- inRepo $ Git.Branch.commit message fullname parents
setIndexSha committedref
parentrefs <- commitparents <$> catObject committedref
- when (racedetected branchref parentrefs) $
+ when (racedetected branchref parentrefs) $ do
+ liftIO $ print ("race detected", branchref, parentrefs, "committing", (branchref, parents))
fixrace committedref parentrefs
where
-- look for "parent ref" lines and return the refs
@@ -244,8 +272,8 @@ commitBranch' branchref message parents = do
{- To recover from the race, union merge the lost refs
- into the index, and recommit on top of the bad commit. -}
fixrace committedref lostrefs = do
- mergeIndex lostrefs
- commitBranch committedref racemessage [committedref]
+ mergeIndex jl lostrefs
+ commitIndex jl committedref racemessage [committedref]
racemessage = message ++ " (recovery from race)"
@@ -253,13 +281,17 @@ commitBranch' branchref message parents = do
files :: Annex [FilePath]
files = do
update
- withIndex $ do
- bfiles <- inRepo $ Git.Command.pipeNullSplitZombie
- [ Params "ls-tree --name-only -r -z"
- , Param $ show fullname
- ]
- jfiles <- getJournalledFiles
- return $ jfiles ++ bfiles
+ (++)
+ <$> branchFiles
+ <*> getJournalledFilesStale
+
+{- Files in the branch, not including any from journalled changes,
+ - and without updating the branch. -}
+branchFiles :: Annex [FilePath]
+branchFiles = withIndex $ inRepo $ Git.Command.pipeNullSplitZombie
+ [ Params "ls-tree --name-only -r -z"
+ , Param $ show fullname
+ ]
{- Populates the branch's index file with the current branch contents.
-
@@ -273,11 +305,27 @@ genIndex g = Git.UpdateIndex.streamUpdateIndex g
{- Merges the specified refs into the index.
- Any changes staged in the index will be preserved. -}
-mergeIndex :: [Git.Ref] -> Annex ()
-mergeIndex branches = do
+mergeIndex :: JournalLocked -> [Git.Ref] -> Annex ()
+mergeIndex jl branches = do
+ prepareModifyIndex jl
h <- catFileHandle
inRepo $ \g -> Git.UnionMerge.mergeIndex h g branches
+{- Removes any stale git lock file, to avoid git falling over when
+ - updating the index.
+ -
+ - Since all modifications of the index are performed inside this module,
+ - and only when the journal is locked, the fact that the journal has to be
+ - locked when this is called ensures that no other process is currently
+ - modifying the index. So any index.lock file must be stale, caused
+ - by git running when the system crashed, or the repository's disk was
+ - removed, etc.
+ -}
+prepareModifyIndex :: JournalLocked -> Annex ()
+prepareModifyIndex _jl = do
+ index <- fromRepo gitAnnexIndex
+ void $ liftIO $ tryIO $ removeFile $ index ++ ".lock"
+
{- Runs an action using the branch's index file. -}
withIndex :: Annex a -> Annex a
withIndex = withIndex' False
@@ -299,15 +347,15 @@ withIndex' bootstrapping a = do
#endif
let g' = g { gitEnv = Just $ ("GIT_INDEX_FILE", f):e }
- Annex.changeState $ \s -> s { Annex.repo = g' }
- checkIndexOnce $ unlessM (liftIO $ doesFileExist f) $ do
- unless bootstrapping create
- liftIO $ createDirectoryIfMissing True $ takeDirectory f
- unless bootstrapping $ inRepo genIndex
- r <- a
+ r <- tryAnnex $ do
+ Annex.changeState $ \s -> s { Annex.repo = g' }
+ checkIndexOnce $ unlessM (liftIO $ doesFileExist f) $ do
+ unless bootstrapping create
+ liftIO $ createDirectoryIfMissing True $ takeDirectory f
+ unless bootstrapping $ inRepo genIndex
+ a
Annex.changeState $ \s -> s { Annex.repo = (Annex.repo s) { gitEnv = gitEnv g} }
-
- return r
+ either E.throw return r
{- Updates the branch's index to reflect the current contents of the branch.
- Any changes staged in the index will be preserved.
@@ -315,40 +363,48 @@ withIndex' bootstrapping a = do
- Compares the ref stored in the lock file with the current
- ref of the branch to see if an update is needed.
-}
-updateIndex :: Git.Ref -> Annex ()
-updateIndex branchref = whenM (needUpdateIndex branchref) $
- forceUpdateIndex branchref
+updateIndex :: JournalLocked -> Git.Ref -> Annex ()
+updateIndex jl branchref = whenM (needUpdateIndex branchref) $
+ forceUpdateIndex jl branchref
-forceUpdateIndex :: Git.Ref -> Annex ()
-forceUpdateIndex branchref = do
- withIndex $ mergeIndex [fullname]
+forceUpdateIndex :: JournalLocked -> Git.Ref -> Annex ()
+forceUpdateIndex jl branchref = do
+ withIndex $ mergeIndex jl [fullname]
setIndexSha branchref
{- Checks if the index needs to be updated. -}
needUpdateIndex :: Git.Ref -> Annex Bool
needUpdateIndex branchref = do
- lock <- fromRepo gitAnnexIndexLock
- lockref <- Git.Ref . firstLine <$>
- liftIO (catchDefaultIO "" $ readFileStrict lock)
- return (lockref /= branchref)
+ f <- fromRepo gitAnnexIndexStatus
+ committedref <- Git.Ref . firstLine <$>
+ liftIO (catchDefaultIO "" $ readFileStrict f)
+ return (committedref /= branchref)
{- Record that the branch's index has been updated to correspond to a
- given ref of the branch. -}
setIndexSha :: Git.Ref -> Annex ()
setIndexSha ref = do
- lock <- fromRepo gitAnnexIndexLock
- liftIO $ writeFile lock $ show ref ++ "\n"
- setAnnexPerm lock
+ f <- fromRepo gitAnnexIndexStatus
+ liftIO $ writeFile f $ show ref ++ "\n"
+ setAnnexPerm f
{- Stages the journal into the index and returns an action that will
- clean up the staged journal files, which should only be run once
- - the index has been committed to the branch. Should be run within
- - lockJournal, to prevent others from modifying the journal. -}
-stageJournal :: Annex (IO ())
-stageJournal = withIndex $ do
+ - the index has been committed to the branch.
+ -
+ - Before staging, this removes any existing git index file lock.
+ - This is safe to do because stageJournal is the only thing that
+ - modifies this index file, and only one can run at a time, because
+ - the journal is locked. So any existing git index file lock must be
+ - stale, and the journal must contain any data that was in the process
+ - of being written to the index file when it crashed.
+ -}
+stageJournal :: JournalLocked -> Annex (IO ())
+stageJournal jl = withIndex $ do
+ prepareModifyIndex jl
g <- gitRepo
let dir = gitAnnexJournalDir g
- fs <- getJournalFiles
+ fs <- getJournalFiles jl
liftIO $ do
h <- hashObjectStart g
Git.UpdateIndex.streamUpdateIndex g
@@ -361,3 +417,117 @@ stageJournal = withIndex $ do
sha <- hashFile h path
streamer $ Git.UpdateIndex.updateIndexLine
sha FileBlob (asTopFilePath $ fileJournal file)
+
+{- This is run after the refs have been merged into the index,
+ - but before the result is committed to the branch.
+ - (Which is why it's passed the contents of the local branches's
+ - transition log before that merge took place.)
+ -
+ - When the refs contain transitions that have not yet been done locally,
+ - the transitions are performed on the index, and a new branch
+ - is created from the result.
+ -
+ - When there are transitions recorded locally that have not been done
+ - to the remote refs, the transitions are performed in the index,
+ - and committed to the existing branch. In this case, the untransitioned
+ - remote refs cannot be merged into the branch (since transitions
+ - throw away history), so they are added to the list of refs to ignore,
+ - to avoid re-merging content from them again.
+ -}
+handleTransitions :: JournalLocked -> Transitions -> [Git.Ref] -> Annex Bool
+handleTransitions jl localts refs = do
+ m <- M.fromList <$> mapM getreftransition refs
+ let remotets = M.elems m
+ if all (localts ==) remotets
+ then return False
+ else do
+ let allts = combineTransitions (localts:remotets)
+ let (transitionedrefs, untransitionedrefs) =
+ partition (\r -> M.lookup r m == Just allts) refs
+ performTransitionsLocked jl allts (localts /= allts) transitionedrefs
+ ignoreRefs untransitionedrefs
+ return True
+ where
+ getreftransition ref = do
+ ts <- parseTransitionsStrictly "remote" . L.unpack
+ <$> catFile ref transitionsLog
+ return (ref, ts)
+
+ignoreRefs :: [Git.Ref] -> Annex ()
+ignoreRefs rs = do
+ old <- getIgnoredRefs
+ let s = S.unions [old, S.fromList rs]
+ f <- fromRepo gitAnnexIgnoredRefs
+ replaceFile f $ \tmp -> liftIO $ writeFile tmp $
+ unlines $ map show $ S.elems s
+
+getIgnoredRefs :: Annex (S.Set Git.Ref)
+getIgnoredRefs = S.fromList . mapMaybe Git.Sha.extractSha . lines <$> content
+ where
+ content = do
+ f <- fromRepo gitAnnexIgnoredRefs
+ liftIO $ catchDefaultIO "" $ readFile f
+
+{- Performs the specified transitions on the contents of the index file,
+ - commits it to the branch, or creates a new branch.
+ -}
+performTransitions :: Transitions -> Bool -> [Ref] -> Annex ()
+performTransitions ts neednewlocalbranch transitionedrefs = lockJournal $ \jl ->
+ performTransitionsLocked jl ts neednewlocalbranch transitionedrefs
+performTransitionsLocked :: JournalLocked -> Transitions -> Bool -> [Ref] -> Annex ()
+performTransitionsLocked jl ts neednewlocalbranch transitionedrefs = do
+ -- For simplicity & speed, we're going to use the Annex.Queue to
+ -- update the git-annex branch, while it usually holds changes
+ -- for the head branch. Flush any such changes.
+ Annex.Queue.flush
+ withIndex $ do
+ prepareModifyIndex jl
+ run $ mapMaybe getTransitionCalculator $ transitionList ts
+ Annex.Queue.flush
+ if neednewlocalbranch
+ then do
+ committedref <- inRepo $ Git.Branch.commit message fullname transitionedrefs
+ setIndexSha committedref
+ else do
+ ref <- getBranch
+ commitIndex jl ref message (nub $ fullname:transitionedrefs)
+ where
+ message
+ | neednewlocalbranch && null transitionedrefs = "new branch for transition " ++ tdesc
+ | otherwise = "continuing transition " ++ tdesc
+ tdesc = show $ map describeTransition $ transitionList ts
+
+ {- The changes to make to the branch are calculated and applied to
+ - the branch directly, rather than going through the journal,
+ - which would be innefficient. (And the journal is not designed
+ - to hold changes to every file in the branch at once.)
+ -
+ - When a file in the branch is changed by transition code,
+ - that value is remembered and fed into the code for subsequent
+ - transitions.
+ -}
+ run [] = noop
+ run changers = do
+ trustmap <- calcTrustMap <$> getRaw trustLog
+ fs <- branchFiles
+ hasher <- inRepo hashObjectStart
+ forM_ fs $ \f -> do
+ content <- getRaw f
+ apply changers hasher f content trustmap
+ liftIO $ hashObjectStop hasher
+ apply [] _ _ _ _ = return ()
+ apply (changer:rest) hasher file content trustmap =
+ case changer file content trustmap of
+ RemoveFile -> do
+ Annex.Queue.addUpdateIndex
+ =<< inRepo (Git.UpdateIndex.unstageFile file)
+ -- File is deleted; can't run any other
+ -- transitions on it.
+ return ()
+ ChangeFile content' -> do
+ sha <- inRepo $ hashObject BlobObject content'
+ Annex.Queue.addUpdateIndex $ Git.UpdateIndex.pureStreamer $
+ Git.UpdateIndex.updateIndexLine sha FileBlob (asTopFilePath file)
+ apply rest hasher file content' trustmap
+ PreserveFile ->
+ apply rest hasher file content trustmap
diff --git a/Annex/Branch/Transitions.hs b/Annex/Branch/Transitions.hs
new file mode 100644
index 000000000..90002de62
--- /dev/null
+++ b/Annex/Branch/Transitions.hs
@@ -0,0 +1,53 @@
+{- git-annex branch transitions
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Annex.Branch.Transitions (
+ FileTransition(..),
+ getTransitionCalculator
+) where
+
+import Logs
+import Logs.Transitions
+import Logs.UUIDBased as UUIDBased
+import Logs.Presence.Pure as Presence
+import Types.TrustLevel
+import Types.UUID
+
+import qualified Data.Map as M
+
+data FileTransition
+ = ChangeFile String
+ | RemoveFile
+ | PreserveFile
+
+type TransitionCalculator = FilePath -> String -> TrustMap -> FileTransition
+
+getTransitionCalculator :: Transition -> Maybe TransitionCalculator
+getTransitionCalculator ForgetGitHistory = Nothing
+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 (PresenceLog _) ->
+ let newlog = Presence.compactLog $ dropDeadFromPresenceLog trustmap $ Presence.parseLog content
+ in if null newlog
+ then RemoveFile
+ else ChangeFile $ Presence.showLog newlog
+ Nothing -> PreserveFile
+
+dropDeadFromUUIDBasedLog :: TrustMap -> UUIDBased.Log String -> UUIDBased.Log String
+dropDeadFromUUIDBasedLog trustmap = M.filterWithKey $ notDead trustmap . const
+
+{- Presence logs can contain UUIDs or other values. Any line that matches
+ - a dead uuid is dropped; any other values are passed through. -}
+dropDeadFromPresenceLog :: TrustMap -> [Presence.LogLine] -> [Presence.LogLine]
+dropDeadFromPresenceLog trustmap = filter $ notDead trustmap (toUUID . Presence.info)
+
+notDead :: TrustMap -> (v -> UUID) -> v -> Bool
+notDead trustmap a v = M.findWithDefault SemiTrusted (a v) trustmap /= DeadTrusted
diff --git a/Annex/CatFile.hs b/Annex/CatFile.hs
index f90e74509..812d032c6 100644
--- a/Annex/CatFile.hs
+++ b/Annex/CatFile.hs
@@ -8,14 +8,17 @@
module Annex.CatFile (
catFile,
catObject,
+ catTree,
catObjectDetails,
catFileHandle,
catKey,
catKeyFile,
+ catKeyFileHEAD,
) where
import qualified Data.ByteString.Lazy as L
import qualified Data.Map as M
+import System.PosixCompat.Types
import Common.Annex
import qualified Git
@@ -23,6 +26,8 @@ import qualified Git.CatFile
import qualified Annex
import Git.Types
import Git.FilePath
+import Git.FileMode
+import qualified Git.Ref
catFile :: Git.Branch -> FilePath -> Annex L.ByteString
catFile branch file = do
@@ -34,7 +39,12 @@ catObject ref = do
h <- catFileHandle
liftIO $ Git.CatFile.catObject h ref
-catObjectDetails :: Git.Ref -> Annex (Maybe (L.ByteString, Sha))
+catTree :: Git.Ref -> Annex [(FilePath, FileMode)]
+catTree ref = do
+ h <- catFileHandle
+ liftIO $ Git.CatFile.catTree h ref
+
+catObjectDetails :: Git.Ref -> Annex (Maybe (L.ByteString, Sha, ObjectType))
catObjectDetails ref = do
h <- catFileHandle
liftIO $ Git.CatFile.catObjectDetails h ref
@@ -54,18 +64,51 @@ catFileHandle = do
Annex.changeState $ \s -> s { Annex.catfilehandles = m' }
return h
-{- From the Sha or Ref of a symlink back to the key. -}
-catKey :: Ref -> Annex (Maybe Key)
-catKey ref = do
- l <- fromInternalGitPath . encodeW8 . L.unpack <$> catObject ref
- return $ if isLinkToAnnex l
- then fileKey $ takeFileName l
- else Nothing
+{- From the Sha or Ref of a symlink back to the key.
+ -
+ - Requires a mode witness, to guarantee that the file is a symlink.
+ -}
+catKey :: Ref -> FileMode -> Annex (Maybe Key)
+catKey = catKey' True
-{- From a file in the repository back to the key.
+catKey' :: Bool -> Ref -> FileMode -> Annex (Maybe Key)
+catKey' modeguaranteed ref mode
+ | isSymLink mode = do
+ l <- fromInternalGitPath . encodeW8 . L.unpack <$> get
+ return $ if isLinkToAnnex l
+ then fileKey $ takeFileName l
+ else Nothing
+ | otherwise = return Nothing
+ where
+ -- If the mode is not guaranteed to be correct, avoid
+ -- buffering the whole file content, which might be large.
+ -- 8192 is enough if it really is a symlink.
+ get
+ | modeguaranteed = catObject ref
+ | otherwise = L.take 8192 <$> catObject ref
+
+{- Looks up the file mode corresponding to the Ref using the running
+ - cat-file.
-
- - Prefixing the file with ./ makes this work even if in a subdirectory
- - of a repo.
+ - Currently this always has to look in HEAD, because cat-file --batch
+ - does not offer a way to specify that we want to look up a tree object
+ - in the index. So if the index has a file staged not as a symlink,
+ - and it is a symlink in head, the wrong mode is gotten.
+ - Also, we have to assume the file is a symlink if it's not yet committed
+ - to HEAD. For these reasons, modeguaranteed is not set.
+ -}
+catKeyChecked :: Bool -> Ref -> Annex (Maybe Key)
+catKeyChecked needhead ref@(Ref r) =
+ catKey' False ref =<< findmode <$> catTree treeref
+ where
+ pathparts = split "/" r
+ dir = intercalate "/" $ take (length pathparts - 1) pathparts
+ file = fromMaybe "" $ lastMaybe pathparts
+ treeref = Ref $ if needhead then "HEAD" ++ dir ++ "/" else dir ++ "/"
+ findmode = fromMaybe symLinkMode . headMaybe .
+ map snd . filter (\p -> fst p == file)
+
+{- From a file in the repository back to the key.
-
- Ideally, this should reflect the key that's staged in the index,
- not the key that's committed to HEAD. Unfortunately, git cat-file
@@ -75,7 +118,8 @@ catKey ref = do
-
- For command-line git-annex use, that doesn't matter. It's perfectly
- reasonable for things staged in the index after the currently running
- - git-annex process to not be noticed by it.
+ - git-annex process to not be noticed by it. However, we do want to see
+ - what's in the index, since it may have uncommitted changes not in HEAD>
-
- For the assistant, this is much more of a problem, since it commits
- files and then needs to be able to immediately look up their keys.
@@ -87,6 +131,9 @@ catKey ref = do
-}
catKeyFile :: FilePath -> Annex (Maybe Key)
catKeyFile f = ifM (Annex.getState Annex.daemon)
- ( catKey $ Ref $ "HEAD:./" ++ f
- , catKey $ Ref $ ":./" ++ f
+ ( catKeyFileHEAD f
+ , catKeyChecked True $ Git.Ref.fileRef f
)
+
+catKeyFileHEAD :: FilePath -> Annex (Maybe Key)
+catKeyFileHEAD f = catKeyChecked False $ Git.Ref.fileFromRef Git.Ref.headRef f
diff --git a/Annex/CheckIgnore.hs b/Annex/CheckIgnore.hs
index e5626557d..d45e652bc 100644
--- a/Annex/CheckIgnore.hs
+++ b/Annex/CheckIgnore.hs
@@ -25,7 +25,7 @@ checkIgnoreHandle :: Annex (Maybe Git.CheckIgnoreHandle)
checkIgnoreHandle = maybe startup return =<< Annex.getState Annex.checkignorehandle
where
startup = do
- v <- inRepo $ Git.checkIgnoreStart
+ v <- inRepo Git.checkIgnoreStart
when (isNothing v) $
warning "The installed version of git is too old for .gitignores to be honored by git-annex."
Annex.changeState $ \s -> s { Annex.checkignorehandle = Just v }
diff --git a/Annex/Content.hs b/Annex/Content.hs
index 01ad6f96f..66ca7be18 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -30,6 +30,7 @@ module Annex.Content (
freezeContent,
thawContent,
cleanObjectLoc,
+ dirKeys,
) where
import System.IO.Unsafe (unsafeInterleaveIO)
@@ -43,7 +44,7 @@ import qualified Annex.Queue
import qualified Annex.Branch
import Utility.DiskFree
import Utility.FileMode
-import qualified Utility.Url as Url
+import qualified Annex.Url as Url
import Types.Key
import Utility.DataUnits
import Utility.CopyFile
@@ -275,10 +276,11 @@ moveAnnex key src = withObjectLoc key storeobject storedirect
thawContentDir =<< calcRepo (gitAnnexLocation key)
thawContent src
v <- isAnnexLink f
- if (Just key == v)
+ if Just key == v
then do
updateInodeCache key src
replaceFile f $ liftIO . moveFile src
+ chmodContent f
forM_ fs $
addContentWhenNotPresent key f
else ifM (goodContent key f)
@@ -457,7 +459,7 @@ downloadUrl urls file = go =<< annexWebDownloadCommand <$> Annex.getGitConfig
go Nothing = do
opts <- map Param . annexWebOptions <$> Annex.getGitConfig
headers <- getHttpHeaders
- liftIO $ anyM (\u -> Url.download u headers opts file) urls
+ anyM (\u -> Url.withUserAgent $ Url.download u headers opts file) urls
go (Just basecmd) = liftIO $ anyM (downloadcmd basecmd) urls
downloadcmd basecmd url =
boolSystem "sh" [Param "-c", Param $ gencmd url basecmd]
@@ -500,6 +502,18 @@ freezeContent file = unlessM crippledFileSystem $
removeModes writeModes .
addModes [ownerReadMode]
+{- Adjusts read mode of annexed file per core.sharedRepository setting. -}
+chmodContent :: FilePath -> Annex ()
+chmodContent file = unlessM crippledFileSystem $
+ liftIO . go =<< fromRepo getSharedRepository
+ where
+ go GroupShared = modifyFileMode file $
+ addModes [ownerReadMode, groupReadMode]
+ go AllShared = modifyFileMode file $
+ addModes readModes
+ go _ = modifyFileMode file $
+ addModes [ownerReadMode]
+
{- Allows writing to an annexed file that freezeContent was called on
- before. -}
thawContent :: FilePath -> Annex ()
@@ -509,3 +523,18 @@ thawContent file = unlessM crippledFileSystem $
go GroupShared = groupWriteRead file
go AllShared = groupWriteRead file
go _ = allowWrite file
+
+{- Finds files directly inside a directory like gitAnnexBadDir
+ - (not in subdirectories) and returns the corresponding keys. -}
+dirKeys :: (Git.Repo -> FilePath) -> Annex [Key]
+dirKeys dirspec = do
+ dir <- fromRepo dirspec
+ ifM (liftIO $ doesDirectoryExist dir)
+ ( do
+ contents <- liftIO $ getDirectoryContents dir
+ files <- liftIO $ filterM doesFileExist $
+ map (dir </>) contents
+ return $ mapMaybe (fileKey . takeFileName) files
+ , return []
+ )
+
diff --git a/Annex/Content/Direct.hs b/Annex/Content/Direct.hs
index 6da7fab52..b0b8621e9 100644
--- a/Annex/Content/Direct.hs
+++ b/Annex/Content/Direct.hs
@@ -101,7 +101,7 @@ addAssociatedFile key file = do
else file':files
{- Associated files are always stored relative to the top of the repository.
- - The input FilePath is relative to the CWD. -}
+ - The input FilePath is relative to the CWD, or is absolute. -}
normaliseAssociatedFile :: FilePath -> Annex FilePath
normaliseAssociatedFile file = do
top <- fromRepo Git.repoPath
@@ -199,7 +199,7 @@ compareInodeCachesWith = ifM inodesChanged ( return Weakly, return Strongly )
addContentWhenNotPresent :: Key -> FilePath -> FilePath -> Annex ()
addContentWhenNotPresent key contentfile associatedfile = do
v <- isAnnexLink associatedfile
- when (Just key == v) $ do
+ when (Just key == v) $
replaceFile associatedfile $
liftIO . void . copyFileExternal contentfile
updateInodeCache key associatedfile
diff --git a/Annex/Direct.hs b/Annex/Direct.hs
index d2e2cdc00..d4b73860e 100644
--- a/Annex/Direct.hs
+++ b/Annex/Direct.hs
@@ -8,14 +8,19 @@
module Annex.Direct where
import Common.Annex
+import qualified Annex
import qualified Git
import qualified Git.LsFiles
import qualified Git.Merge
import qualified Git.DiffTree as DiffTree
+import qualified Git.Config
+import qualified Git.Ref
+import qualified Git.Branch
import Git.Sha
+import Git.FilePath
import Git.Types
+import Config
import Annex.CatFile
-import Utility.FileMode
import qualified Annex.Queue
import Logs.Location
import Backend
@@ -45,8 +50,8 @@ stageDirect = do
{- Determine what kind of modified or deleted file this is, as
- efficiently as we can, by getting any key that's associated
- with it in git, as well as its stat info. -}
- go (file, Just sha) = do
- shakey <- catKey sha
+ go (file, Just sha, Just mode) = do
+ shakey <- catKey sha mode
mstat <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
filekey <- isAnnexLink file
case (shakey, filekey, mstat, toInodeCache =<< mstat) of
@@ -123,6 +128,8 @@ addDirect file cache = do
-}
mergeDirect :: FilePath -> Git.Ref -> Git.Repo -> IO Bool
mergeDirect d branch g = do
+ whenM (doesDirectoryExist d) $
+ removeDirectoryRecursive d
createDirectoryIfMissing True d
let g' = g { location = Local { gitdir = Git.localGitDir g, worktree = Just d } }
Git.Merge.mergeNonInteractive branch g'
@@ -135,23 +142,22 @@ mergeDirect d branch g = do
mergeDirectCleanup :: FilePath -> Git.Ref -> Git.Ref -> Annex ()
mergeDirectCleanup d oldsha newsha = do
(items, cleanup) <- inRepo $ DiffTree.diffTreeRecursive oldsha newsha
- forM_ items updated
+ makeabs <- flip fromTopFilePath <$> gitRepo
+ forM_ items (updated makeabs)
void $ liftIO cleanup
liftIO $ removeDirectoryRecursive d
where
- updated item = do
+ updated makeabs item = do
+ let f = makeabs (DiffTree.file item)
void $ tryAnnex $
- go DiffTree.srcsha DiffTree.srcmode moveout moveout_raw
+ go f DiffTree.srcsha DiffTree.srcmode moveout moveout_raw
void $ tryAnnex $
- go DiffTree.dstsha DiffTree.dstmode movein movein_raw
+ go f DiffTree.dstsha DiffTree.dstmode movein movein_raw
where
- go getsha getmode a araw
+ go f getsha getmode a araw
| getsha item == nullSha = noop
- | isSymLink (getmode item) =
- maybe (araw f) (\k -> void $ a k f)
- =<< catKey (getsha item)
- | otherwise = araw f
- f = DiffTree.file item
+ | otherwise = maybe (araw f) (\k -> void $ a k f)
+ =<< catKey (getsha item) (getmode item)
moveout = removeDirect
@@ -230,3 +236,66 @@ changedDirect oldk f = do
locs <- removeAssociatedFile oldk f
whenM (pure (null locs) <&&> not <$> inAnnex oldk) $
logStatus oldk InfoMissing
+
+{- Enable/disable direct mode. -}
+setDirect :: Bool -> Annex ()
+setDirect wantdirect = do
+ if wantdirect
+ then do
+ switchHEAD
+ setbare
+ else do
+ setbare
+ switchHEADBack
+ setConfig (annexConfig "direct") val
+ Annex.changeGitConfig $ \c -> c { annexDirect = wantdirect }
+ where
+ val = Git.Config.boolConfig wantdirect
+ setbare = setConfig (ConfigKey Git.Config.coreBare) val
+
+{- Since direct mode sets core.bare=true, incoming pushes could change
+ - the currently checked out branch. To avoid this problem, HEAD
+ - is changed to a internal ref that nothing is going to push to.
+ -
+ - For refs/heads/master, use refs/heads/annex/direct/master;
+ - this way things that show HEAD (eg shell prompts) will
+ - hopefully show just "master". -}
+directBranch :: Ref -> Ref
+directBranch orighead = case split "/" $ show orighead of
+ ("refs":"heads":"annex":"direct":_) -> orighead
+ ("refs":"heads":rest) ->
+ Ref $ "refs/heads/annex/direct/" ++ intercalate "/" rest
+ _ -> Ref $ "refs/heads/" ++ show (Git.Ref.base orighead)
+
+{- Converts a directBranch back to the original branch.
+ -
+ - Any other ref is left unchanged.
+ -}
+fromDirectBranch :: Ref -> Ref
+fromDirectBranch directhead = case split "/" $ show directhead of
+ ("refs":"heads":"annex":"direct":rest) ->
+ Ref $ "refs/heads/" ++ intercalate "/" rest
+ _ -> directhead
+
+switchHEAD :: Annex ()
+switchHEAD = maybe noop switch =<< inRepo Git.Branch.currentUnsafe
+ where
+ switch orighead = do
+ let newhead = directBranch orighead
+ maybe noop (inRepo . Git.Branch.update newhead)
+ =<< inRepo (Git.Ref.sha orighead)
+ inRepo $ Git.Branch.checkout newhead
+
+switchHEADBack :: Annex ()
+switchHEADBack = maybe noop switch =<< inRepo Git.Branch.currentUnsafe
+ where
+ switch currhead = do
+ let orighead = fromDirectBranch currhead
+ v <- inRepo $ Git.Ref.sha currhead
+ case v of
+ Just headsha
+ | orighead /= currhead -> do
+ inRepo $ Git.Branch.update orighead headsha
+ inRepo $ Git.Branch.checkout orighead
+ inRepo $ Git.Branch.delete currhead
+ _ -> inRepo $ Git.Branch.checkout orighead
diff --git a/Annex/Environment.hs b/Annex/Environment.hs
index ae5a5646f..f22c5f2d4 100644
--- a/Annex/Environment.hs
+++ b/Annex/Environment.hs
@@ -32,7 +32,7 @@ import Utility.Env
checkEnvironment :: Annex ()
checkEnvironment = do
gitusername <- fromRepo $ Git.Config.getMaybe "user.name"
- when (gitusername == Nothing || gitusername == Just "") $
+ when (isNothing gitusername || gitusername == Just "") $
liftIO checkEnvironmentIO
checkEnvironmentIO :: IO ()
diff --git a/Annex/Exception.hs b/Annex/Exception.hs
index 99466a851..aaa6811a5 100644
--- a/Annex/Exception.hs
+++ b/Annex/Exception.hs
@@ -13,6 +13,7 @@
module Annex.Exception (
bracketIO,
tryAnnex,
+ tryAnnexIO,
throwAnnex,
catchAnnex,
) where
@@ -24,12 +25,16 @@ import Common.Annex
{- Runs an Annex action, with setup and cleanup both in the IO monad. -}
bracketIO :: IO v -> (v -> IO b) -> (v -> Annex a) -> Annex a
-bracketIO setup cleanup go = M.bracket (liftIO setup) (liftIO . cleanup) go
+bracketIO setup cleanup = M.bracket (liftIO setup) (liftIO . cleanup)
{- try in the Annex monad -}
tryAnnex :: Annex a -> Annex (Either SomeException a)
tryAnnex = M.try
+{- try in the Annex monad, but only catching IO exceptions -}
+tryAnnexIO :: Annex a -> Annex (Either IOException a)
+tryAnnexIO = M.try
+
{- throw in the Annex monad -}
throwAnnex :: Exception e => e -> Annex a
throwAnnex = M.throw
diff --git a/Annex/FileMatcher.hs b/Annex/FileMatcher.hs
index 3abba1055..cded857a2 100644
--- a/Annex/FileMatcher.hs
+++ b/Annex/FileMatcher.hs
@@ -13,6 +13,7 @@ import Common.Annex
import Limit
import Utility.Matcher
import Types.Group
+import Types.Limit
import Logs.Group
import Logs.Remote
import Annex.UUID
diff --git a/Annex/Hook.hs b/Annex/Hook.hs
new file mode 100644
index 000000000..7301a0958
--- /dev/null
+++ b/Annex/Hook.hs
@@ -0,0 +1,42 @@
+{- git-annex git hooks
+ -
+ - Note that it's important that the scripts not change, otherwise
+ - removing old hooks using an old version of the script would fail.
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Annex.Hook where
+
+import Common.Annex
+import qualified Git.Hook as Git
+import Utility.Shell
+import Config
+
+preCommitHook :: Git.Hook
+preCommitHook = Git.Hook "pre-commit" (mkHookScript "git annex pre-commit .")
+
+mkHookScript :: String -> String
+mkHookScript s = unlines
+ [ shebang_local
+ , "# automatically configured by git-annex"
+ , s
+ ]
+
+hookWrite :: Git.Hook -> Annex ()
+hookWrite h =
+ -- cannot have git hooks in a crippled filesystem (no execute bit)
+ unlessM crippledFileSystem $
+ unlessM (inRepo $ Git.hookWrite h) $
+ hookWarning h "already exists, not configuring"
+
+hookUnWrite :: Git.Hook -> Annex ()
+hookUnWrite h = unlessM (inRepo $ Git.hookUnWrite h) $
+ hookWarning h "contents modified; not deleting. Edit it to remove call to git annex."
+
+hookWarning :: Git.Hook -> String -> Annex ()
+hookWarning h msg = do
+ r <- gitRepo
+ warning $ Git.hookName h ++ " hook (" ++ Git.hookFile h r ++ ") " ++ msg
diff --git a/Annex/Journal.hs b/Annex/Journal.hs
index fff20ccc4..8b88ab2fb 100644
--- a/Annex/Journal.hs
+++ b/Annex/Journal.hs
@@ -1,10 +1,10 @@
{- management of the git-annex journal
-
- The journal is used to queue up changes before they are committed to the
- - git-annex branch. Amoung other things, it ensures that if git-annex is
+ - git-annex branch. Among other things, it ensures that if git-annex is
- interrupted, its recorded data is not lost.
-
- - Copyright 2011 Joey Hess <joey@kitenet.net>
+ - Copyright 2011-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -23,9 +23,14 @@ import Annex.Perms
{- Records content for a file in the branch to the journal.
-
- Using the journal, rather than immediatly staging content to the index
- - avoids git needing to rewrite the index after every change. -}
-setJournalFile :: FilePath -> String -> Annex ()
-setJournalFile file content = do
+ - avoids git needing to rewrite the index after every change.
+ -
+ - The file in the journal is updated atomically, which allows
+ - getJournalFileStale to always return a consistent journal file
+ - content, although possibly not the most current one.
+ -}
+setJournalFile :: JournalLocked -> FilePath -> String -> Annex ()
+setJournalFile _jl file content = do
createAnnexDirectory =<< fromRepo gitAnnexJournalDir
createAnnexDirectory =<< fromRepo gitAnnexTmpDir
-- journal file is written atomically
@@ -37,17 +42,32 @@ setJournalFile file content = do
moveFile tmpfile jfile
{- Gets any journalled content for a file in the branch. -}
-getJournalFile :: FilePath -> Annex (Maybe String)
-getJournalFile file = inRepo $ \g -> catchMaybeIO $
+getJournalFile :: JournalLocked -> FilePath -> Annex (Maybe String)
+getJournalFile _jl = getJournalFileStale
+
+{- Without locking, this is not guaranteed to be the most recent
+ - version of the file in the journal, so should not be used as a basis for
+ - changes. -}
+getJournalFileStale :: FilePath -> Annex (Maybe String)
+getJournalFileStale file = inRepo $ \g -> catchMaybeIO $
readFileStrict $ journalFile file g
{- List of files that have updated content in the journal. -}
-getJournalledFiles :: Annex [FilePath]
-getJournalledFiles = map fileJournal <$> getJournalFiles
+getJournalledFiles :: JournalLocked -> Annex [FilePath]
+getJournalledFiles jl = map fileJournal <$> getJournalFiles jl
+
+getJournalledFilesStale :: Annex [FilePath]
+getJournalledFilesStale = map fileJournal <$> getJournalFilesStale
{- List of existing journal files. -}
-getJournalFiles :: Annex [FilePath]
-getJournalFiles = do
+getJournalFiles :: JournalLocked -> Annex [FilePath]
+getJournalFiles _jl = getJournalFilesStale
+
+{- List of existing journal files, but without locking, may miss new ones
+ - just being added, or may have false positives if the journal is staged
+ - as it is run. -}
+getJournalFilesStale :: Annex [FilePath]
+getJournalFilesStale = do
g <- gitRepo
fs <- liftIO $ catchDefaultIO [] $
getDirectoryContents $ gitAnnexJournalDir g
@@ -55,7 +75,7 @@ getJournalFiles = do
{- Checks if there are changes in the journal. -}
journalDirty :: Annex Bool
-journalDirty = not . null <$> getJournalFiles
+journalDirty = not . null <$> getJournalFilesStale
{- Produces a filename to use in the journal for a file on the branch.
-
@@ -77,14 +97,19 @@ fileJournal :: FilePath -> FilePath
fileJournal = replace [pathSeparator, pathSeparator] "_" .
replace "_" [pathSeparator]
+{- Sentinal value, only produced by lockJournal; required
+ - as a parameter by things that need to ensure the journal is
+ - locked. -}
+data JournalLocked = ProduceJournalLocked
+
{- Runs an action that modifies the journal, using locking to avoid
- contention with other git-annex processes. -}
-lockJournal :: Annex a -> Annex a
+lockJournal :: (JournalLocked -> Annex a) -> Annex a
lockJournal a = do
lockfile <- fromRepo gitAnnexJournalLock
createAnnexDirectory $ takeDirectory lockfile
mode <- annexFileMode
- bracketIO (lock lockfile mode) unlock (const a)
+ bracketIO (lock lockfile mode) unlock (const $ a ProduceJournalLocked)
where
#ifndef mingw32_HOST_OS
lock lockfile mode = do
@@ -101,4 +126,3 @@ lockJournal a = do
#else
unlock = removeFile
#endif
-
diff --git a/Annex/Link.hs b/Annex/Link.hs
index becd7e7ec..30d8c2ae8 100644
--- a/Annex/Link.hs
+++ b/Annex/Link.hs
@@ -68,9 +68,9 @@ getAnnexLinkTarget file = ifM (coreSymlinks <$> Annex.getGitConfig)
-- characters, or whitespace, we
-- certianly don't have a link to a
-- git-annex key.
- if any (`elem` s) "\0\n\r \t"
- then return ""
- else return s
+ return $ if any (`elem` s) "\0\n\r \t"
+ then ""
+ else s
{- Creates a link on disk.
-
diff --git a/Annex/Quvi.hs b/Annex/Quvi.hs
new file mode 100644
index 000000000..b0725bae7
--- /dev/null
+++ b/Annex/Quvi.hs
@@ -0,0 +1,20 @@
+{- quvi options for git-annex
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE Rank2Types #-}
+
+module Annex.Quvi where
+
+import Common.Annex
+import qualified Annex
+import Utility.Quvi
+import Utility.Url
+
+withQuviOptions :: forall a. Query a -> [CommandParam] -> URLString -> Annex a
+withQuviOptions a ps url = do
+ opts <- map Param . annexQuviOptions <$> Annex.getGitConfig
+ liftIO $ a (ps++opts) url
diff --git a/Annex/Ssh.hs b/Annex/Ssh.hs
index 6fd2c556c..8553ee797 100644
--- a/Annex/Ssh.hs
+++ b/Annex/Ssh.hs
@@ -16,6 +16,7 @@ module Annex.Ssh (
import qualified Data.Map as M
import Data.Hash.MD5
+import System.Process (cwd)
import Common.Annex
import Annex.LockPool
@@ -42,7 +43,7 @@ sshCachingOptions (host, port) opts = go =<< sshInfo (host, port)
-- If the lock pool is empty, this is the first ssh of this
-- run. There could be stale ssh connections hanging around
-- from a previous git-annex run that was interrupted.
- cleanstale = whenM (not . any isLock . M.keys <$> getPool) $
+ cleanstale = whenM (not . any isLock . M.keys <$> getPool)
sshCleanup
{- Returns a filename to use for a ssh connection caching socket, and
@@ -52,14 +53,30 @@ sshInfo (host, port) = go =<< sshCacheDir
where
go Nothing = return (Nothing, [])
go (Just dir) = do
- let socketfile = dir </> hostport2socket host port
- if valid_unix_socket_path socketfile
- then return (Just socketfile, sshConnectionCachingParams socketfile)
- else do
- socketfile' <- liftIO $ relPathCwdToFile socketfile
- if valid_unix_socket_path socketfile'
- then return (Just socketfile', sshConnectionCachingParams socketfile')
- else return (Nothing, [])
+ r <- liftIO $ bestSocketPath $ dir </> hostport2socket host port
+ return $ case r of
+ Nothing -> (Nothing, [])
+ Just socketfile -> (Just socketfile, sshConnectionCachingParams socketfile)
+
+{- Given an absolute path to use for a socket file,
+ - returns whichever is shorter of that or the relative path to the same
+ - file.
+ -
+ - If no path can be constructed that is a valid socket, returns Nothing. -}
+bestSocketPath :: FilePath -> IO (Maybe FilePath)
+bestSocketPath abssocketfile = do
+ relsocketfile <- liftIO $ relPathCwdToFile abssocketfile
+ let socketfile = if length abssocketfile <= length relsocketfile
+ then abssocketfile
+ else relsocketfile
+ return $ if valid_unix_socket_path (socketfile ++ sshgarbage)
+ then Just socketfile
+ else Nothing
+ where
+ -- ssh appends a 16 char extension to the socket when setting it
+ -- up, which needs to be taken into account when checking
+ -- that a valid socket was constructed.
+ sshgarbage = take (1+16) $ repeat 'X'
sshConnectionCachingParams :: FilePath -> [CommandParam]
sshConnectionCachingParams socketfile =
@@ -96,8 +113,8 @@ sshCleanup = go =<< sshCacheDir
where
go Nothing = noop
go (Just dir) = do
- sockets <- filter (not . isLock) <$>
- liftIO (catchDefaultIO [] $ dirContents dir)
+ sockets <- liftIO $ filter (not . isLock)
+ <$> catchDefaultIO [] (dirContents dir)
forM_ sockets cleanup
cleanup socketfile = do
#ifndef mingw32_HOST_OS
@@ -120,13 +137,15 @@ sshCleanup = go =<< sshCacheDir
stopssh socketfile
#endif
stopssh socketfile = do
- let params = sshConnectionCachingParams socketfile
+ let (dir, base) = splitFileName socketfile
+ let params = sshConnectionCachingParams base
-- "ssh -O stop" is noisy on stderr even with -q
void $ liftIO $ catchMaybeIO $
withQuietOutput createProcessSuccess $
- proc "ssh" $ toCommand $
+ (proc "ssh" $ toCommand $
[ Params "-O stop"
- ] ++ params ++ [Param "any"]
+ ] ++ params ++ [Param "any"])
+ { cwd = Just dir }
-- Cannot remove the lock file; other processes may
-- be waiting on our exclusive lock to use it.
@@ -139,8 +158,10 @@ hostport2socket host Nothing = hostport2socket' host
hostport2socket host (Just port) = hostport2socket' $ host ++ "!" ++ show port
hostport2socket' :: String -> FilePath
hostport2socket' s
- | length s > 32 = md5s (Str s)
+ | length s > lengthofmd5s = md5s (Str s)
| otherwise = s
+ where
+ lengthofmd5s = 32
socket2lock :: FilePath -> FilePath
socket2lock socket = socket ++ lockExt
diff --git a/Annex/TaggedPush.hs b/Annex/TaggedPush.hs
index 5dac345f2..039dc0e17 100644
--- a/Annex/TaggedPush.hs
+++ b/Annex/TaggedPush.hs
@@ -13,13 +13,14 @@ import qualified Annex.Branch
import qualified Git
import qualified Git.Ref
import qualified Git.Command
+import qualified Git.Branch
import Utility.Base64
{- Converts a git branch into a branch that is tagged with a UUID, typically
- the UUID of the repo that will be pushing it, and possibly with other
- information.
-
- - Pushing to branches on the remote that have out uuid in them is ugly,
+ - Pushing to branches on the remote that have our uuid in them is ugly,
- but it reserves those branches for pushing by us, and so our pushes will
- never conflict with other pushes.
-
@@ -50,7 +51,10 @@ taggedPush :: UUID -> Maybe String -> Git.Ref -> Remote -> Git.Repo -> IO Bool
taggedPush u info branch remote = Git.Command.runBool
[ Param "push"
, Param $ Remote.name remote
- , Param $ refspec Annex.Branch.name
+ {- Using forcePush here is safe because we "own" the tagged branch
+ - we're pushing; it has no other writers. Ensures it is pushed
+ - even if it has been rewritten by a transition. -}
+ , Param $ Git.Branch.forcePush $ refspec Annex.Branch.name
, Param $ refspec branch
]
where
diff --git a/Annex/UUID.hs b/Annex/UUID.hs
index c36861bbe..4e274503b 100644
--- a/Annex/UUID.hs
+++ b/Annex/UUID.hs
@@ -17,8 +17,11 @@ module Annex.UUID (
getUncachedUUID,
prepUUID,
genUUID,
+ genUUIDInNameSpace,
+ gCryptNameSpace,
removeRepoUUID,
storeUUID,
+ setUUID,
) where
import Common.Annex
@@ -27,7 +30,9 @@ import qualified Git.Config
import Config
import qualified Data.UUID as U
+import qualified Data.UUID.V5 as U5
import System.Random
+import Data.Bits.Utils
configkey :: ConfigKey
configkey = annexConfig "uuid"
@@ -36,6 +41,17 @@ configkey = annexConfig "uuid"
genUUID :: IO UUID
genUUID = UUID . show <$> (randomIO :: IO U.UUID)
+{- Generates a UUID from a given string, using a namespace.
+ - Given the same namespace, the same string will always result
+ - in the same UUID. -}
+genUUIDInNameSpace :: U.UUID -> String -> UUID
+genUUIDInNameSpace namespace = UUID . show . U5.generateNamed namespace . s2w8
+
+{- Namespace used for UUIDs derived from git-remote-gcrypt ids. -}
+gCryptNameSpace :: U.UUID
+gCryptNameSpace = U5.generateNamed U5.namespaceURL $
+ s2w8 "http://git-annex.branchable.com/design/gcrypt/"
+
{- Get current repository's UUID. -}
getUUID :: Annex UUID
getUUID = getRepoUUID =<< gitRepo
@@ -72,3 +88,9 @@ prepUUID = whenM ((==) NoUUID <$> getUUID) $
storeUUID :: ConfigKey -> UUID -> Annex ()
storeUUID configfield = setConfig configfield . fromUUID
+
+{- Only sets the configkey in the Repo; does not change .git/config -}
+setUUID :: Git.Repo -> UUID -> IO Git.Repo
+setUUID r u = do
+ let s = show configkey ++ "=" ++ fromUUID u
+ Git.Config.store s r
diff --git a/Annex/Url.hs b/Annex/Url.hs
new file mode 100644
index 000000000..0401ffe07
--- /dev/null
+++ b/Annex/Url.hs
@@ -0,0 +1,27 @@
+{- Url downloading, with git-annex user agent.
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Annex.Url (
+ module U,
+ withUserAgent,
+ getUserAgent,
+) where
+
+import Common.Annex
+import qualified Annex
+import Utility.Url as U
+import qualified Build.SysConfig as SysConfig
+
+defaultUserAgent :: U.UserAgent
+defaultUserAgent = "git-annex/" ++ SysConfig.packageversion
+
+getUserAgent :: Annex (Maybe U.UserAgent)
+getUserAgent = Annex.getState $
+ Just . fromMaybe defaultUserAgent . Annex.useragent
+
+withUserAgent :: (Maybe U.UserAgent -> IO a) -> Annex a
+withUserAgent a = liftIO . a =<< getUserAgent
diff --git a/Annex/Version.hs b/Annex/Version.hs
index 05b3f0227..2b4a49fd2 100644
--- a/Annex/Version.hs
+++ b/Annex/Version.hs
@@ -19,18 +19,21 @@ defaultVersion :: Version
defaultVersion = "3"
directModeVersion :: Version
-directModeVersion = "4"
+directModeVersion = "5"
supportedVersions :: [Version]
supportedVersions = [defaultVersion, directModeVersion]
upgradableVersions :: [Version]
#ifndef mingw32_HOST_OS
-upgradableVersions = ["0", "1", "2"]
+upgradableVersions = ["0", "1", "2", "4"]
#else
-upgradableVersions = ["2"]
+upgradableVersions = ["2", "4"]
#endif
+autoUpgradeableVersions :: [Version]
+autoUpgradeableVersions = ["4"]
+
versionField :: ConfigKey
versionField = annexConfig "version"
@@ -42,12 +45,3 @@ setVersion = setConfig versionField
removeVersion :: Annex ()
removeVersion = unsetConfig versionField
-
-checkVersion :: Version -> Annex ()
-checkVersion v
- | v `elem` supportedVersions = noop
- | v `elem` upgradableVersions = err "Upgrade this repository: git-annex upgrade"
- | otherwise = err "Upgrade git-annex."
- where
- err msg = error $ "Repository version " ++ v ++
- " is not supported. " ++ msg
diff --git a/Annex/Wanted.hs b/Annex/Wanted.hs
index b90a1af31..04dcc1c1c 100644
--- a/Annex/Wanted.hs
+++ b/Annex/Wanted.hs
@@ -1,4 +1,4 @@
-{- git-annex control over whether content is wanted
+{- git-annex checking whether content is wanted
-
- Copyright 2012 Joey Hess <joey@kitenet.net>
-
diff --git a/Assistant.hs b/Assistant.hs
index c14f1e0df..3f4c4fabd 100644
--- a/Assistant.hs
+++ b/Assistant.hs
@@ -22,6 +22,8 @@ import Assistant.Threads.Merger
import Assistant.Threads.TransferWatcher
import Assistant.Threads.Transferrer
import Assistant.Threads.SanityChecker
+import Assistant.Threads.Cronner
+import Assistant.Threads.ProblemFixer
#ifdef WITH_CLIBS
import Assistant.Threads.MountWatcher
#endif
@@ -47,6 +49,8 @@ import Assistant.Types.UrlRenderer
import qualified Utility.Daemon
import Utility.LogFile
import Utility.ThreadScheduler
+import Utility.HumanTime
+import Annex.Perms
import qualified Build.SysConfig as SysConfig
import System.Log.Logger
@@ -60,11 +64,13 @@ stopDaemon = liftIO . Utility.Daemon.stopDaemon =<< fromRepo gitAnnexPidFile
-
- startbrowser is passed the url and html shim file, as well as the original
- stdout and stderr descriptors. -}
-startDaemon :: Bool -> Bool -> Maybe HostName -> Maybe (Maybe Handle -> Maybe Handle -> String -> FilePath -> IO ()) -> Annex ()
-startDaemon assistant foreground listenhost startbrowser = do
+startDaemon :: Bool -> Bool -> Maybe Duration -> Maybe HostName -> Maybe (Maybe Handle -> Maybe Handle -> String -> FilePath -> IO ()) -> Annex ()
+startDaemon assistant foreground startdelay listenhost startbrowser = do
Annex.changeState $ \s -> s { Annex.daemon = True }
pidfile <- fromRepo gitAnnexPidFile
logfile <- fromRepo gitAnnexLogFile
+#ifndef mingw32_HOST_OS
+ createAnnexDirectory (parentDir logfile)
logfd <- liftIO $ openLog logfile
if foreground
then do
@@ -83,6 +89,13 @@ startDaemon assistant foreground listenhost startbrowser = do
Just a -> Just $ a origout origerr
else
start (Utility.Daemon.daemonize logfd (Just pidfile) False) Nothing
+#else
+ -- Windows is always foreground, and has no log file.
+ start id $
+ case startbrowser of
+ Nothing -> Nothing
+ Just a -> Just $ a Nothing Nothing
+#endif
where
desc
| assistant = "assistant"
@@ -96,7 +109,6 @@ startDaemon assistant foreground listenhost startbrowser = do
flip runAssistant (go webappwaiter)
=<< newAssistantData st dstatus
-
#ifdef WITH_WEBAPP
go webappwaiter = do
d <- getAssistant id
@@ -127,15 +139,20 @@ startDaemon assistant foreground listenhost startbrowser = do
, assist $ daemonStatusThread
, assist $ sanityCheckerDailyThread
, assist $ sanityCheckerHourlyThread
+ , assist $ problemFixerThread urlrenderer
#ifdef WITH_CLIBS
- , assist $ mountWatcherThread
+ , assist $ mountWatcherThread urlrenderer
#endif
, assist $ netWatcherThread
, assist $ netWatcherFallbackThread
, assist $ transferScannerThread urlrenderer
+ , assist $ cronnerThread urlrenderer
, assist $ configMonitorThread
, assist $ glacierThread
, watch $ watchThread
+ -- must come last so that all threads that wait
+ -- on it have already started waiting
+ , watch $ sanityCheckerStartupThread startdelay
]
liftIO waitForTermination
diff --git a/Assistant/Alert.hs b/Assistant/Alert.hs
index df5ee2910..8bdedaa3e 100644
--- a/Assistant/Alert.hs
+++ b/Assistant/Alert.hs
@@ -18,26 +18,30 @@ import Logs.Transfer
import Data.String
import qualified Data.Text as T
+import qualified Control.Exception as E
#ifdef WITH_WEBAPP
-import Assistant.Monad
import Assistant.DaemonStatus
import Assistant.WebApp.Types
-import Assistant.WebApp
+import Assistant.WebApp (renderUrl)
import Yesod
#endif
+import Assistant.Monad
+import Assistant.Types.UrlRenderer
-{- Makes a button for an alert that opens a Route. The button will
- - close the alert it's attached to when clicked. -}
+{- Makes a button for an alert that opens a Route.
+ -
+ - If autoclose is set, the button will close the alert it's
+ - attached to when clicked. -}
#ifdef WITH_WEBAPP
-mkAlertButton :: T.Text -> UrlRenderer -> Route WebApp -> Assistant AlertButton
-mkAlertButton label urlrenderer route = do
+mkAlertButton :: Bool -> T.Text -> UrlRenderer -> Route WebApp -> Assistant AlertButton
+mkAlertButton autoclose label urlrenderer route = do
close <- asIO1 removeAlert
url <- liftIO $ renderUrl urlrenderer route []
return $ AlertButton
{ buttonLabel = label
, buttonUrl = url
- , buttonAction = Just close
+ , buttonAction = if autoclose then Just close else Nothing
}
#endif
@@ -76,6 +80,22 @@ warningAlert name msg = Alert
, alertButton = Nothing
}
+errorAlert :: String -> AlertButton -> Alert
+errorAlert msg button = Alert
+ { alertClass = Error
+ , alertHeader = Nothing
+ , alertMessageRender = renderData
+ , alertData = [UnTensed $ T.pack msg]
+ , alertCounter = 0
+ , alertBlockDisplay = True
+ , alertClosable = True
+ , alertPriority = Pinned
+ , alertIcon = Just ErrorIcon
+ , alertCombiner = Nothing
+ , alertName = Nothing
+ , alertButton = Just button
+ }
+
activityAlert :: Maybe TenseText -> [TenseChunk] -> Alert
activityAlert header dat = baseActivityAlert
{ alertHeader = header
@@ -147,6 +167,63 @@ sanityCheckFixAlert msg = Alert
alerthead = "The daily sanity check found and fixed a problem:"
alertfoot = "If these problems persist, consider filing a bug report."
+fsckingAlert :: AlertButton -> Maybe Remote -> Alert
+fsckingAlert button mr = baseActivityAlert
+ { alertData = case mr of
+ Nothing -> [ UnTensed $ T.pack $ "Consistency check in progress" ]
+ Just r -> [ UnTensed $ T.pack $ "Consistency check of " ++ Remote.name r ++ " in progress"]
+ , alertButton = Just button
+ }
+
+showFscking :: UrlRenderer -> Maybe Remote -> IO (Either E.SomeException a) -> Assistant a
+showFscking urlrenderer mr a = do
+#ifdef WITH_WEBAPP
+ button <- mkAlertButton False (T.pack "Configure") urlrenderer ConfigFsckR
+ r <- alertDuring (fsckingAlert button mr) $
+ liftIO a
+#else
+ r <- liftIO a
+#endif
+ either (liftIO . E.throwIO) return r
+
+notFsckedNudge :: UrlRenderer -> Maybe Remote -> Assistant ()
+#ifdef WITH_WEBAPP
+notFsckedNudge urlrenderer mr = do
+ button <- mkAlertButton True (T.pack "Configure") urlrenderer ConfigFsckR
+ void $ addAlert (notFsckedAlert mr button)
+#else
+notFsckedNudge _ _ = noop
+#endif
+
+notFsckedAlert :: Maybe Remote -> AlertButton -> Alert
+notFsckedAlert mr button = Alert
+ { alertHeader = Just $ fromString $ concat
+ [ "You should enable consistency checking to protect your data"
+ , maybe "" (\r -> " in " ++ Remote.name r) mr
+ , "."
+ ]
+ , alertIcon = Just InfoIcon
+ , alertPriority = High
+ , alertButton = Just button
+ , alertClosable = True
+ , alertClass = Message
+ , alertMessageRender = renderData
+ , alertCounter = 0
+ , alertBlockDisplay = True
+ , alertName = Just NotFsckedAlert
+ , alertCombiner = Just $ dataCombiner $ \_old new -> new
+ , alertData = []
+ }
+
+brokenRepositoryAlert :: AlertButton -> Alert
+brokenRepositoryAlert = errorAlert "Serious problems have been detected with your repository. This needs your immediate attention!"
+
+repairingAlert :: String -> Alert
+repairingAlert repodesc = activityAlert Nothing
+ [ Tensed "Attempting to repair" "Repaired"
+ , UnTensed $ T.pack repodesc
+ ]
+
pairingAlert :: AlertButton -> Alert
pairingAlert button = baseActivityAlert
{ alertData = [ UnTensed "Pairing in progress" ]
diff --git a/Assistant/DaemonStatus.hs b/Assistant/DaemonStatus.hs
index af072d8ae..7268bbbfb 100644
--- a/Assistant/DaemonStatus.hs
+++ b/Assistant/DaemonStatus.hs
@@ -57,8 +57,7 @@ calcSyncRemotes = do
return $ \dstatus -> dstatus
{ syncRemotes = syncable
- , syncGitRemotes =
- filter (not . Remote.specialRemote) syncable
+ , syncGitRemotes = filter Remote.syncableRemote syncable
, syncDataRemotes = syncdata
, syncingToCloudRemote = any iscloud syncdata
}
@@ -77,6 +76,10 @@ updateSyncRemotes = do
M.filter $ \alert ->
alertName alert /= Just CloudRepoNeededAlert
+updateScheduleLog :: Assistant ()
+updateScheduleLog =
+ liftIO . sendNotification =<< scheduleLogNotifier <$> getDaemonStatus
+
{- Load any previous daemon status file, and store it in a MVar for this
- process to use as its DaemonStatus. Also gets current transfer status. -}
startDaemonStatus :: Annex DaemonStatusHandle
diff --git a/Assistant/DeleteRemote.hs b/Assistant/DeleteRemote.hs
index 2e06d52cd..cc05786e4 100644
--- a/Assistant/DeleteRemote.hs
+++ b/Assistant/DeleteRemote.hs
@@ -17,8 +17,7 @@ import Logs.Location
import Assistant.DaemonStatus
import qualified Remote
import Remote.List
-import qualified Git.Command
-import qualified Git.BuildVersion
+import qualified Git.Remote
import Logs.Trust
import qualified Annex
@@ -35,15 +34,7 @@ disableRemote uuid = do
remote <- fromMaybe (error "unknown remote")
<$> liftAnnex (Remote.remoteFromUUID uuid)
liftAnnex $ do
- inRepo $ Git.Command.run
- [ Param "remote"
- -- name of this subcommand changed
- , Param $
- if Git.BuildVersion.older "1.8.0"
- then "rm"
- else "remove"
- , Param (Remote.name remote)
- ]
+ inRepo $ Git.Remote.remove (Remote.name remote)
void $ remoteListRefresh
updateSyncRemotes
return remote
@@ -90,7 +81,7 @@ finishRemovingRemote :: UrlRenderer -> UUID -> Assistant ()
#ifdef WITH_WEBAPP
finishRemovingRemote urlrenderer uuid = do
desc <- liftAnnex $ Remote.prettyUUID uuid
- button <- mkAlertButton (T.pack "Finish deletion process") urlrenderer $
+ button <- mkAlertButton True (T.pack "Finish deletion process") urlrenderer $
FinishDeleteRepositoryR uuid
void $ addAlert $ remoteRemovalAlert desc button
#else
diff --git a/Assistant/MakeRemote.hs b/Assistant/MakeRemote.hs
index e26d6057a..bf316e49d 100644
--- a/Assistant/MakeRemote.hs
+++ b/Assistant/MakeRemote.hs
@@ -9,51 +9,32 @@ module Assistant.MakeRemote where
import Assistant.Common
import Assistant.Ssh
-import Assistant.Sync
import qualified Types.Remote as R
import qualified Remote
import Remote.List
import qualified Remote.Rsync as Rsync
+import qualified Remote.GCrypt as GCrypt
import qualified Git
import qualified Git.Command
import qualified Command.InitRemote
import Logs.UUID
import Logs.Remote
import Git.Remote
-import Config
-import Config.Cost
+import Git.Types (RemoteName)
import Creds
+import Assistant.Gpg
+import Utility.Gpg (KeyId)
-import qualified Data.Text as T
import qualified Data.Map as M
-type RemoteName = String
-
-{- Sets up and begins syncing with a new ssh or rsync remote. -}
-makeSshRemote :: Bool -> SshData -> Maybe Cost -> Assistant Remote
-makeSshRemote forcersync sshdata mcost = do
- r <- liftAnnex $
- addRemote $ maker (sshRepoName sshdata) sshurl
- liftAnnex $ maybe noop (setRemoteCost r) mcost
- syncRemote r
- return r
+{- Sets up a new git or rsync remote, accessed over ssh. -}
+makeSshRemote :: SshData -> Annex RemoteName
+makeSshRemote sshdata = maker (sshRepoName sshdata) (genSshUrl sshdata)
where
- rsync = forcersync || rsyncOnly sshdata
maker
- | rsync = makeRsyncRemote
+ | onlyCapability sshdata RsyncCapable = makeRsyncRemote
| otherwise = makeGitRemote
- sshurl = T.unpack $ T.concat $
- if rsync
- then [u, h, T.pack ":", sshDirectory sshdata, T.pack "/"]
- else [T.pack "ssh://", u, h, d, T.pack "/"]
- where
- u = maybe (T.pack "") (\v -> T.concat [v, T.pack "@"]) $ sshUserName sshdata
- h = sshHostName sshdata
- d
- | T.pack "/" `T.isPrefixOf` sshDirectory sshdata = sshDirectory sshdata
- | T.pack "~/" `T.isPrefixOf` sshDirectory sshdata = T.concat [T.pack "/", sshDirectory sshdata]
- | otherwise = T.concat [T.pack "/~/", sshDirectory sshdata]
-
+
{- Runs an action that returns a name of the remote, and finishes adding it. -}
addRemote :: Annex RemoteName -> Annex Remote
addRemote a = do
@@ -68,14 +49,24 @@ makeRsyncRemote name location = makeRemote name location $ const $ void $
go =<< Command.InitRemote.findExisting name
where
go Nothing = setupSpecialRemote name Rsync.remote config
- =<< Command.InitRemote.generateNew name
- go (Just v) = setupSpecialRemote name Rsync.remote config v
+ (Nothing, Command.InitRemote.newConfig name)
+ go (Just (u, c)) = setupSpecialRemote name Rsync.remote config (Just u, c)
config = M.fromList
[ ("encryption", "shared")
, ("rsyncurl", location)
, ("type", "rsync")
]
+{- Inits a gcrypt special remote, and returns its name. -}
+makeGCryptRemote :: RemoteName -> String -> KeyId -> Annex RemoteName
+makeGCryptRemote remotename location keyid =
+ initSpecialRemote remotename GCrypt.remote $ M.fromList
+ [ ("type", "gcrypt")
+ , ("gitrepo", location)
+ , configureEncryption HybridEncryption
+ , ("keyid", keyid)
+ ]
+
type SpecialRemoteMaker = RemoteName -> RemoteType -> R.RemoteConfig -> Annex RemoteName
{- Inits a new special remote. The name is used as a suggestion, but
@@ -89,7 +80,7 @@ initSpecialRemote name remotetype config = go 0
r <- Command.InitRemote.findExisting fullname
case r of
Nothing -> setupSpecialRemote fullname remotetype config
- =<< Command.InitRemote.generateNew fullname
+ (Nothing, Command.InitRemote.newConfig fullname)
Just _ -> go (n + 1)
{- Enables an existing special remote. -}
@@ -98,15 +89,15 @@ enableSpecialRemote name remotetype config = do
r <- Command.InitRemote.findExisting name
case r of
Nothing -> error $ "Cannot find a special remote named " ++ name
- Just v -> setupSpecialRemote name remotetype config v
+ Just (u, c) -> setupSpecialRemote name remotetype config (Just u, c)
-setupSpecialRemote :: RemoteName -> RemoteType -> R.RemoteConfig -> (UUID, R.RemoteConfig) -> Annex RemoteName
-setupSpecialRemote name remotetype config (u, c) = do
+setupSpecialRemote :: RemoteName -> RemoteType -> R.RemoteConfig -> (Maybe UUID, R.RemoteConfig) -> Annex RemoteName
+setupSpecialRemote name remotetype config (mu, c) = do
{- Currently, only 'weak' ciphers can be generated from the
- assistant, because otherwise GnuPG may block once the entropy
- pool is drained, and as of now there's no way to tell the user
- to perform IO actions to refill the pool. -}
- c' <- R.setup remotetype u $
+ (c', u) <- R.setup remotetype mu $
M.insert "highRandomQuality" "false" $ M.union config c
describeUUID u name
configSet u c'
@@ -128,7 +119,6 @@ makeRemote basename location a = do
g <- gitRepo
if not (any samelocation $ Git.remotes g)
then do
-
let name = uniqueRemoteName basename 0 g
a name
return name
diff --git a/Assistant/Monad.hs b/Assistant/Monad.hs
index 4b73061f9..6b843ea88 100644
--- a/Assistant/Monad.hs
+++ b/Assistant/Monad.hs
@@ -39,6 +39,7 @@ import Assistant.Types.Pushes
import Assistant.Types.BranchChange
import Assistant.Types.Commits
import Assistant.Types.Changes
+import Assistant.Types.RepoProblem
import Assistant.Types.Buddies
import Assistant.Types.NetMessager
import Assistant.Types.ThreadName
@@ -63,6 +64,7 @@ data AssistantData = AssistantData
, failedPushMap :: FailedPushMap
, commitChan :: CommitChan
, changePool :: ChangePool
+ , repoProblemChan :: RepoProblemChan
, branchChangeHandle :: BranchChangeHandle
, buddyList :: BuddyList
, netMessager :: NetMessager
@@ -80,6 +82,7 @@ newAssistantData st dstatus = AssistantData
<*> newFailedPushMap
<*> newCommitChan
<*> newChangePool
+ <*> newRepoProblemChan
<*> newBranchChangeHandle
<*> newBuddyList
<*> newNetMessager
diff --git a/Assistant/NamedThread.hs b/Assistant/NamedThread.hs
index edebe830f..2440c45bf 100644
--- a/Assistant/NamedThread.hs
+++ b/Assistant/NamedThread.hs
@@ -16,6 +16,7 @@ import Assistant.Types.DaemonStatus
import Assistant.Types.UrlRenderer
import Assistant.DaemonStatus
import Assistant.Monad
+import Utility.NotificationBroadcaster
import Control.Concurrent
import Control.Concurrent.Async
@@ -34,7 +35,7 @@ import qualified Data.Text as T
- Named threads are run by a management thread, so if they crash
- an alert is displayed, allowing the thread to be restarted. -}
startNamedThread :: UrlRenderer -> NamedThread -> Assistant ()
-startNamedThread urlrenderer namedthread@(NamedThread name a) = do
+startNamedThread urlrenderer (NamedThread afterstartupsanitycheck name a) = do
m <- startedThreads <$> getDaemonStatus
case M.lookup name m of
Nothing -> start
@@ -44,14 +45,24 @@ startNamedThread urlrenderer namedthread@(NamedThread name a) = do
Right Nothing -> noop
_ -> start
where
- start = do
+ start
+ | afterstartupsanitycheck = do
+ status <- getDaemonStatus
+ h <- liftIO $ newNotificationHandle False $
+ startupSanityCheckNotifier status
+ startwith $ runmanaged $
+ liftIO $ waitNotification h
+ | otherwise = startwith $ runmanaged noop
+ startwith runner = do
d <- getAssistant id
- aid <- liftIO $ runmanaged $ d { threadName = name }
- restart <- asIO $ startNamedThread urlrenderer namedthread
+ aid <- liftIO $ runner $ d { threadName = name }
+ restart <- asIO $ startNamedThread urlrenderer (NamedThread False name a)
modifyDaemonStatus_ $ \s -> s
{ startedThreads = M.insertWith' const name (aid, restart) (startedThreads s) }
- runmanaged d = do
- aid <- async $ runAssistant d a
+ runmanaged first d = do
+ aid <- async $ runAssistant d $ do
+ void first
+ a
void $ forkIO $ manager d aid
return aid
manager d aid = do
@@ -65,7 +76,7 @@ startNamedThread urlrenderer namedthread@(NamedThread name a) = do
]
hPutStrLn stderr msg
#ifdef WITH_WEBAPP
- button <- runAssistant d $ mkAlertButton
+ button <- runAssistant d $ mkAlertButton True
(T.pack "Restart Thread")
urlrenderer
(RestartThreadR name)
@@ -75,7 +86,7 @@ startNamedThread urlrenderer namedthread@(NamedThread name a) = do
#endif
namedThreadId :: NamedThread -> Assistant (Maybe ThreadId)
-namedThreadId (NamedThread name _) = do
+namedThreadId (NamedThread _ name _) = do
m <- startedThreads <$> getDaemonStatus
return $ asyncThreadId . fst <$> M.lookup name m
diff --git a/Assistant/NetMessager.hs b/Assistant/NetMessager.hs
index 329d808fc..acb18b648 100644
--- a/Assistant/NetMessager.hs
+++ b/Assistant/NetMessager.hs
@@ -29,6 +29,10 @@ notifyNetMessagerRestart :: Assistant ()
notifyNetMessagerRestart =
flip writeSV () <<~ (netMessagerRestart . netMessager)
+{- This can be used to get an early indication if the network has
+ - changed, to immediately restart a connection. However, that is not
+ - available on all systems, so clients also need to deal with
+ - restarting dropped connections in the usual way. -}
waitNetMessagerRestart :: Assistant ()
waitNetMessagerRestart = readSV <<~ (netMessagerRestart . netMessager)
diff --git a/Assistant/Pairing.hs b/Assistant/Pairing.hs
index 4736c4396..bb1384a15 100644
--- a/Assistant/Pairing.hs
+++ b/Assistant/Pairing.hs
@@ -28,7 +28,7 @@ data PairStage
| PairAck
{- "I saw your PairAck; you can stop sending them." -}
| PairDone
- deriving (Eq, Read, Show, Ord)
+ deriving (Eq, Read, Show, Ord, Enum)
newtype PairMsg = PairMsg (Verifiable (PairStage, PairData, SomeAddr))
deriving (Eq, Read, Show)
diff --git a/Assistant/Pairing/MakeRemote.hs b/Assistant/Pairing/MakeRemote.hs
index edd27e35a..144b236a4 100644
--- a/Assistant/Pairing/MakeRemote.hs
+++ b/Assistant/Pairing/MakeRemote.hs
@@ -12,7 +12,9 @@ import Assistant.Ssh
import Assistant.Pairing
import Assistant.Pairing.Network
import Assistant.MakeRemote
+import Assistant.Sync
import Config.Cost
+import Config
import Network.Socket
import qualified Data.Text as T
@@ -22,7 +24,7 @@ import qualified Data.Text as T
setupAuthorizedKeys :: PairMsg -> FilePath -> IO ()
setupAuthorizedKeys msg repodir = do
validateSshPubKey pubkey
- unlessM (liftIO $ addAuthorizedKeys False repodir pubkey) $
+ unlessM (liftIO $ addAuthorizedKeys True repodir pubkey) $
error "failed setting up ssh authorized keys"
where
pubkey = remoteSshPubKey $ pairMsgData msg
@@ -43,7 +45,9 @@ finishedLocalPairing msg keypair = do
, "git-annex-shell -c configlist " ++ T.unpack (sshDirectory sshdata)
]
Nothing
- void $ makeSshRemote False sshdata (Just semiExpensiveRemoteCost)
+ r <- liftAnnex $ addRemote $ makeSshRemote sshdata
+ liftAnnex $ setRemoteCost r semiExpensiveRemoteCost
+ syncRemote r
{- Mostly a straightforward conversion. Except:
- * Determine the best hostname to use to contact the host.
@@ -63,7 +67,7 @@ pairMsgToSshData msg = do
, sshRepoName = genSshRepoName hostname dir
, sshPort = 22
, needsPubKey = True
- , rsyncOnly = False
+ , sshCapabilities = [GitAnnexShellCapable, GitCapable, RsyncCapable]
}
{- Finds the best hostname to use for the host that sent the PairMsg.
diff --git a/Assistant/RepoProblem.hs b/Assistant/RepoProblem.hs
new file mode 100644
index 000000000..6913fefc6
--- /dev/null
+++ b/Assistant/RepoProblem.hs
@@ -0,0 +1,34 @@
+{- git-annex assistant remote problem handling
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Assistant.RepoProblem where
+
+import Assistant.Common
+import Assistant.Types.RepoProblem
+import Utility.TList
+
+import Control.Concurrent.STM
+
+{- Gets all repositories that have problems. Blocks until there is at
+ - least one. -}
+getRepoProblems :: Assistant [RepoProblem]
+getRepoProblems = nubBy sameRepoProblem
+ <$> (atomically . getTList) <<~ repoProblemChan
+
+{- Indicates that there was a problem with a repository, and the problem
+ - appears to not be a transient (eg network connection) problem.
+ -
+ - If the problem is able to be repaired, the passed action will be run.
+ - (However, if multiple problems are reported with a single repository,
+ - only a single action will be run.)
+ -}
+repoHasProblem :: UUID -> Assistant () -> Assistant ()
+repoHasProblem u afterrepair = do
+ rp <- RepoProblem
+ <$> pure u
+ <*> asIO afterrepair
+ (atomically . flip consTList rp) <<~ repoProblemChan
diff --git a/Assistant/Ssh.hs b/Assistant/Ssh.hs
index a62319096..1dc982ba6 100644
--- a/Assistant/Ssh.hs
+++ b/Assistant/Ssh.hs
@@ -1,6 +1,6 @@
{- git-annex assistant ssh utilities
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -11,6 +11,8 @@ import Common.Annex
import Utility.Tmp
import Utility.UserInfo
import Utility.Shell
+import Utility.Rsync
+import Utility.FileMode
import Git.Remote
import Data.Text (Text)
@@ -25,10 +27,19 @@ data SshData = SshData
, sshRepoName :: String
, sshPort :: Int
, needsPubKey :: Bool
- , rsyncOnly :: Bool
+ , sshCapabilities :: [SshServerCapability]
}
deriving (Read, Show, Eq)
+data SshServerCapability = GitAnnexShellCapable | GitCapable | RsyncCapable
+ deriving (Read, Show, Eq)
+
+hasCapability :: SshData -> SshServerCapability -> Bool
+hasCapability d c = c `elem` sshCapabilities d
+
+onlyCapability :: SshData -> SshServerCapability -> Bool
+onlyCapability d c = all (== c) (sshCapabilities d)
+
data SshKeyPair = SshKeyPair
{ sshPubKey :: String
, sshPrivKey :: String
@@ -52,6 +63,48 @@ sshDir = do
genSshHost :: Text -> Maybe Text -> String
genSshHost host user = maybe "" (\v -> T.unpack v ++ "@") user ++ T.unpack host
+{- Generates a ssh or rsync url from a SshData. -}
+genSshUrl :: SshData -> String
+genSshUrl sshdata = addtrailingslash $ T.unpack $ T.concat $
+ if (onlyCapability sshdata RsyncCapable)
+ then [u, h, T.pack ":", sshDirectory sshdata]
+ else [T.pack "ssh://", u, h, d]
+ where
+ u = maybe (T.pack "") (\v -> T.concat [v, T.pack "@"]) $ sshUserName sshdata
+ h = sshHostName sshdata
+ d
+ | T.pack "/" `T.isPrefixOf` sshDirectory sshdata = sshDirectory sshdata
+ | T.pack "~/" `T.isPrefixOf` sshDirectory sshdata = T.concat [T.pack "/", sshDirectory sshdata]
+ | otherwise = T.concat [T.pack "/~/", sshDirectory sshdata]
+ addtrailingslash s
+ | "/" `isSuffixOf` s = s
+ | otherwise = s ++ "/"
+
+{- Reverses genSshUrl -}
+parseSshUrl :: String -> Maybe SshData
+parseSshUrl u
+ | "ssh://" `isPrefixOf` u = fromssh (drop (length "ssh://") u)
+ | otherwise = fromrsync u
+ where
+ mkdata (userhost, dir) = Just $ SshData
+ { sshHostName = T.pack host
+ , sshUserName = if null user then Nothing else Just $ T.pack user
+ , sshDirectory = T.pack dir
+ , sshRepoName = genSshRepoName host dir
+ -- dummy values, cannot determine from url
+ , sshPort = 22
+ , needsPubKey = True
+ , sshCapabilities = []
+ }
+ where
+ (user, host) = if '@' `elem` userhost
+ then separate (== '@') userhost
+ else ("", userhost)
+ fromrsync s
+ | not (rsyncUrlIsShell u) = Nothing
+ | otherwise = mkdata $ separate (== ':') s
+ fromssh = mkdata . break (== '/')
+
{- Generates a git remote name, like host_dir or host -}
genSshRepoName :: String -> FilePath -> String
genSshRepoName host dir
@@ -92,12 +145,12 @@ validateSshPubKey pubkey
safeincomment c = isAlphaNum c || c == '@' || c == '-' || c == '_' || c == '.'
addAuthorizedKeys :: Bool -> FilePath -> SshPubKey -> IO Bool
-addAuthorizedKeys rsynconly dir pubkey = boolSystem "sh"
- [ Param "-c" , Param $ addAuthorizedKeysCommand rsynconly dir pubkey ]
+addAuthorizedKeys gitannexshellonly dir pubkey = boolSystem "sh"
+ [ Param "-c" , Param $ addAuthorizedKeysCommand gitannexshellonly dir pubkey ]
removeAuthorizedKeys :: Bool -> FilePath -> SshPubKey -> IO ()
-removeAuthorizedKeys rsynconly dir pubkey = do
- let keyline = authorizedKeysLine rsynconly dir pubkey
+removeAuthorizedKeys gitannexshellonly dir pubkey = do
+ let keyline = authorizedKeysLine gitannexshellonly dir pubkey
sshdir <- sshDir
let keyfile = sshdir </> "authorized_keys"
ls <- lines <$> readFileStrict keyfile
@@ -110,7 +163,7 @@ removeAuthorizedKeys rsynconly dir pubkey = do
- present.
-}
addAuthorizedKeysCommand :: Bool -> FilePath -> SshPubKey -> String
-addAuthorizedKeysCommand rsynconly dir pubkey = intercalate "&&"
+addAuthorizedKeysCommand gitannexshellonly dir pubkey = intercalate "&&"
[ "mkdir -p ~/.ssh"
, intercalate "; "
[ "if [ ! -e " ++ wrapper ++ " ]"
@@ -122,7 +175,7 @@ addAuthorizedKeysCommand rsynconly dir pubkey = intercalate "&&"
, "chmod 600 ~/.ssh/authorized_keys"
, unwords
[ "echo"
- , shellEscape $ authorizedKeysLine rsynconly dir pubkey
+ , shellEscape $ authorizedKeysLine gitannexshellonly dir pubkey
, ">>~/.ssh/authorized_keys"
]
]
@@ -141,11 +194,11 @@ addAuthorizedKeysCommand rsynconly dir pubkey = intercalate "&&"
runshell var = "exec git-annex-shell -c \"" ++ var ++ "\""
authorizedKeysLine :: Bool -> FilePath -> SshPubKey -> String
-authorizedKeysLine rsynconly dir pubkey
+authorizedKeysLine gitannexshellonly dir pubkey
+ | gitannexshellonly = limitcommand ++ pubkey
{- TODO: Locking down rsync is difficult, requiring a rather
- long perl script. -}
- | rsynconly = pubkey
- | otherwise = limitcommand ++ pubkey
+ | otherwise = pubkey
where
limitcommand = "command=\"GIT_ANNEX_SHELL_DIRECTORY="++shellEscape dir++" ~/.ssh/git-annex-shell\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding "
@@ -181,12 +234,8 @@ setupSshKeyPair sshkeypair sshdata = do
sshdir <- sshDir
createDirectoryIfMissing True $ parentDir $ sshdir </> sshprivkeyfile
- unlessM (doesFileExist $ sshdir </> sshprivkeyfile) $ do
- h <- fdToHandle =<<
- createFile (sshdir </> sshprivkeyfile)
- (unionFileModes ownerWriteMode ownerReadMode)
- hPutStr h (sshPrivKey sshkeypair)
- hClose h
+ unlessM (doesFileExist $ sshdir </> sshprivkeyfile) $
+ writeFileProtected (sshdir </> sshprivkeyfile) (sshPrivKey sshkeypair)
unlessM (doesFileExist $ sshdir </> sshpubkeyfile) $
writeFile (sshdir </> sshpubkeyfile) (sshPubKey sshkeypair)
diff --git a/Assistant/Sync.hs b/Assistant/Sync.hs
index fe578ab43..f7656f52d 100644
--- a/Assistant/Sync.hs
+++ b/Assistant/Sync.hs
@@ -23,9 +23,18 @@ import qualified Git.Command
import qualified Git.Ref
import qualified Remote
import qualified Types.Remote as Remote
+import qualified Remote.List as Remote
import qualified Annex.Branch
import Annex.UUID
import Annex.TaggedPush
+import qualified Config
+import Git.Config
+import Assistant.NamedThread
+import Assistant.Threads.Watcher (watchThread, WatcherControl(..))
+import Assistant.TransferSlots
+import Assistant.TransferQueue
+import Assistant.RepoProblem
+import Logs.Transfer
import Data.Time.Clock
import qualified Data.Map as M
@@ -44,13 +53,22 @@ import Control.Concurrent
- they push to us. Since XMPP pushes run ansynchronously, any scan of the
- XMPP remotes has to be deferred until they're done pushing to us, so
- all XMPP remotes are marked as possibly desynced.
+ -
+ - Also handles signaling any connectRemoteNotifiers, after the syncing is
+ - done.
-}
reconnectRemotes :: Bool -> [Remote] -> Assistant ()
reconnectRemotes _ [] = noop
reconnectRemotes notifypushes rs = void $ do
- modifyDaemonStatus_ $ \s -> s
- { desynced = S.union (S.fromList $ map Remote.uuid xmppremotes) (desynced s) }
- syncAction rs (const go)
+ rs' <- liftIO $ filterM (Remote.checkAvailable True) rs
+ unless (null rs') $ do
+ modifyDaemonStatus_ $ \s -> s
+ { desynced = S.union (S.fromList $ map Remote.uuid xmppremotes) (desynced s) }
+ failedrs <- syncAction rs' (const go)
+ forM_ failedrs $ \r ->
+ whenM (liftIO $ Remote.checkAvailable False r) $
+ repoHasProblem (Remote.uuid r) (syncRemote r)
+ mapM_ signal $ filter (`notElem` failedrs) rs'
where
gitremotes = filter (notspecialremote . Remote.repo) rs
(xmppremotes, nonxmppremotes) = partition isXMPPRemote rs
@@ -73,6 +91,9 @@ reconnectRemotes notifypushes rs = void $ do
filter (not . remoteAnnexIgnore . Remote.gitconfig)
nonxmppremotes
return failed
+ signal r = liftIO . mapM_ (flip tryPutMVar ())
+ =<< fromMaybe [] . M.lookup (Remote.uuid r) . connectRemoteNotifiers
+ <$> getDaemonStatus
{- Updates the local sync branch, then pushes it to all remotes, in
- parallel, along with the git-annex branch. This is the same
@@ -220,3 +241,36 @@ syncRemote remote = do
reconnectRemotes False [remote]
addScanRemotes True [remote]
void $ liftIO $ forkIO $ thread
+
+{- Use Nothing to change autocommit setting; or a remote to change
+ - its sync setting. -}
+changeSyncable :: Maybe Remote -> Bool -> Assistant ()
+changeSyncable Nothing enable = do
+ liftAnnex $ Config.setConfig key (boolConfig enable)
+ liftIO . maybe noop (`throwTo` signal)
+ =<< namedThreadId watchThread
+ where
+ key = Config.annexConfig "autocommit"
+ signal
+ | enable = ResumeWatcher
+ | otherwise = PauseWatcher
+changeSyncable (Just r) True = do
+ liftAnnex $ changeSyncFlag r True
+ syncRemote r
+changeSyncable (Just r) False = do
+ liftAnnex $ changeSyncFlag r False
+ updateSyncRemotes
+ {- Stop all transfers to or from this remote.
+ - XXX Can't stop any ongoing scan, or git syncs. -}
+ void $ dequeueTransfers tofrom
+ mapM_ (cancelTransfer False) =<<
+ filter tofrom . M.keys . currentTransfers <$> getDaemonStatus
+ where
+ tofrom t = transferUUID t == Remote.uuid r
+
+changeSyncFlag :: Remote -> Bool -> Annex ()
+changeSyncFlag r enabled = do
+ Config.setConfig key (boolConfig enabled)
+ void Remote.remoteListRefresh
+ where
+ key = Config.remoteConfig (Remote.repo r) "sync"
diff --git a/Assistant/Threads/Committer.hs b/Assistant/Threads/Committer.hs
index be3bc3c84..695703e22 100644
--- a/Assistant/Threads/Committer.hs
+++ b/Assistant/Threads/Committer.hs
@@ -112,7 +112,7 @@ waitChangeTime a = waitchanges 0
- that make up a file rename? Or some of the pairs that make up
- a directory rename?
-}
- possiblyrename cs = all renamepart cs
+ possiblyrename = all renamepart
renamepart (PendingAddChange _ _) = True
renamepart c = isRmChange c
@@ -309,7 +309,7 @@ handleAdds delayadd cs = returnWhen (null incomplete) $ do
inRepo (Git.LsFiles.notInRepo False $ map changeFile pending)
-- note: timestamp info is lost here
let ts = changeTime exemplar
- return (map (PendingAddChange ts) newfiles, void $ liftIO $ cleanup)
+ return (map (PendingAddChange ts) newfiles, void $ liftIO cleanup)
returnWhen c a
| c = return otherchanges
@@ -317,12 +317,13 @@ handleAdds delayadd cs = returnWhen (null incomplete) $ do
add :: Change -> Assistant (Maybe Change)
add change@(InProcessAddChange { keySource = ks }) =
- catchDefaultIO Nothing <~> do
- sanitycheck ks $ do
- key <- liftAnnex $ do
- showStart "add" $ keyFilename ks
- Command.Add.ingest $ Just ks
- maybe (failedingest change) (done change $ keyFilename ks) key
+ catchDefaultIO Nothing <~> doadd
+ where
+ doadd = sanitycheck ks $ do
+ (mkey, mcache) <- liftAnnex $ do
+ showStart "add" $ keyFilename ks
+ Command.Add.ingest $ Just ks
+ maybe (failedingest change) (done change mcache $ keyFilename ks) mkey
add _ = return Nothing
{- In direct mode, avoid overhead of re-injesting a renamed
@@ -349,7 +350,7 @@ handleAdds delayadd cs = returnWhen (null incomplete) $ do
fastadd change key = do
let source = keySource change
liftAnnex $ Command.Add.finishIngestDirect key source
- done change (keyFilename source) key
+ done change Nothing (keyFilename source) key
removedKeysMap :: InodeComparisonType -> [Change] -> Annex (M.Map InodeCacheKey Key)
removedKeysMap ct l = do
@@ -365,13 +366,13 @@ handleAdds delayadd cs = returnWhen (null incomplete) $ do
liftAnnex showEndFail
return Nothing
- done change file key = liftAnnex $ do
+ done change mcache file key = liftAnnex $ do
logStatus key InfoPresent
link <- ifM isDirect
( inRepo $ gitAnnexLink file key
- , Command.Add.link file key True
+ , Command.Add.link file key mcache
)
- whenM (pure DirWatcher.eventsCoalesce <||> isDirect) $ do
+ whenM (pure DirWatcher.eventsCoalesce <||> isDirect) $
stageSymlink file =<< hashSymlink link
showEndOk
return $ Just $ finishedChange change key
@@ -415,8 +416,8 @@ safeToAdd _ [] [] = return []
safeToAdd delayadd pending inprocess = do
maybe noop (liftIO . threadDelaySeconds) delayadd
liftAnnex $ do
- keysources <- mapM Command.Add.lockDown (map changeFile pending)
- let inprocess' = inprocess ++ catMaybes (map mkinprocess $ zip pending keysources)
+ keysources <- forM pending $ Command.Add.lockDown . changeFile
+ let inprocess' = inprocess ++ mapMaybe mkinprocess (zip pending keysources)
openfiles <- S.fromList . map fst3 . filter openwrite <$>
findopenfiles (map keySource inprocess')
let checked = map (check openfiles) inprocess'
@@ -434,7 +435,7 @@ safeToAdd delayadd pending inprocess = do
| S.member (contentLocation ks) openfiles = Left change
check _ change = Right change
- mkinprocess (c, Just ks) = Just $ InProcessAddChange
+ mkinprocess (c, Just ks) = Just InProcessAddChange
{ changeTime = changeTime c
, keySource = ks
}
diff --git a/Assistant/Threads/ConfigMonitor.hs b/Assistant/Threads/ConfigMonitor.hs
index 6a01ff35e..c180c4da9 100644
--- a/Assistant/Threads/ConfigMonitor.hs
+++ b/Assistant/Threads/ConfigMonitor.hs
@@ -12,13 +12,14 @@ import Assistant.BranchChange
import Assistant.DaemonStatus
import Assistant.Commits
import Utility.ThreadScheduler
+import Logs
import Logs.UUID
import Logs.Trust
-import Logs.Remote
import Logs.PreferredContent
import Logs.Group
import Remote.List (remoteListRefresh)
import qualified Git.LsTree as LsTree
+import Git.FilePath
import qualified Annex.Branch
import qualified Data.Set as S
@@ -52,12 +53,13 @@ configMonitorThread = namedThread "ConfigMonitor" $ loop =<< getConfigs
type Configs = S.Set (FilePath, String)
{- All git-annex's config files, and actions to run when they change. -}
-configFilesActions :: [(FilePath, Annex ())]
+configFilesActions :: [(FilePath, Assistant ())]
configFilesActions =
- [ (uuidLog, void $ uuidMapLoad)
- , (remoteLog, void remoteListRefresh)
- , (trustLog, void trustMapLoad)
- , (groupLog, void groupMapLoad)
+ [ (uuidLog, void $ liftAnnex uuidMapLoad)
+ , (remoteLog, void $ liftAnnex remoteListRefresh)
+ , (trustLog, void $ liftAnnex trustMapLoad)
+ , (groupLog, void $ liftAnnex groupMapLoad)
+ , (scheduleLog, void updateScheduleLog)
-- Preferred content settings depend on most of the other configs,
-- so will be reloaded whenever any configs change.
, (preferredContentLog, noop)
@@ -65,13 +67,12 @@ configFilesActions =
reloadConfigs :: Configs -> Assistant ()
reloadConfigs changedconfigs = do
- liftAnnex $ do
- sequence_ as
- void preferredContentMapLoad
+ sequence_ as
+ void $ liftAnnex preferredContentMapLoad
{- 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. -}
- when (any (`elem` fs) [remoteLog, trustLog, uuidLog]) $
+ when (any (`elem` fs) [remoteLog, trustLog, uuidLog])
updateSyncRemotes
where
(fs, as) = unzip $ filter (flip S.member changedfiles . fst)
@@ -83,4 +84,4 @@ getConfigs = S.fromList . map extract
<$> liftAnnex (inRepo $ LsTree.lsTreeFiles Annex.Branch.fullname files)
where
files = map fst configFilesActions
- extract treeitem = (LsTree.file treeitem, LsTree.sha treeitem)
+ extract treeitem = (getTopFilePath $ LsTree.file treeitem, LsTree.sha treeitem)
diff --git a/Assistant/Threads/Cronner.hs b/Assistant/Threads/Cronner.hs
new file mode 100644
index 000000000..55b3ca2f1
--- /dev/null
+++ b/Assistant/Threads/Cronner.hs
@@ -0,0 +1,225 @@
+{- git-annex assistant sceduled jobs runner
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE DeriveDataTypeable #-}
+
+module Assistant.Threads.Cronner (
+ cronnerThread
+) where
+
+import Assistant.Common
+import Assistant.DaemonStatus
+import Utility.NotificationBroadcaster
+import Annex.UUID
+import Config.Files
+import Logs.Schedule
+import Utility.Scheduled
+import Types.ScheduledActivity
+import Utility.ThreadScheduler
+import Utility.HumanTime
+import Utility.Batch
+import Assistant.TransferQueue
+import Annex.Content
+import Logs.Transfer
+import Assistant.Types.UrlRenderer
+import Assistant.Alert
+import Remote
+import qualified Types.Remote as Remote
+import qualified Git
+import qualified Git.Fsck
+import Assistant.Fsck
+import Assistant.Repair
+
+import Control.Concurrent.Async
+import Control.Concurrent.MVar
+import Data.Time.LocalTime
+import Data.Time.Clock
+import qualified Data.Map as M
+import qualified Data.Set as S
+
+{- Loads schedules for this repository, and fires off one thread for each
+ - scheduled event that runs on this repository. Each thread sleeps until
+ - its event is scheduled to run.
+ -
+ - To handle events that run on remotes, which need to only run when
+ - their remote gets connected, threads are also started, and are passed
+ - a MVar to wait on, which is stored in the DaemonStatus's
+ - connectRemoteNotifiers.
+ -
+ - In the meantime the main thread waits for any changes to the
+ - schedules. When there's a change, compare the old and new list of
+ - schedules to find deleted and added ones. Start new threads for added
+ - ones, and kill the threads for deleted ones. -}
+cronnerThread :: UrlRenderer -> NamedThread
+cronnerThread urlrenderer = namedThreadUnchecked "Cronner" $ do
+ fsckNudge urlrenderer Nothing
+ dstatus <- getDaemonStatus
+ h <- liftIO $ newNotificationHandle False (scheduleLogNotifier dstatus)
+ go h M.empty M.empty
+ where
+ go h amap nmap = do
+ activities <- liftAnnex $ scheduleGet =<< getUUID
+
+ let addedactivities = activities `S.difference` M.keysSet amap
+ let removedactivities = M.keysSet amap `S.difference` activities
+
+ forM_ (S.toList removedactivities) $ \activity ->
+ case M.lookup activity amap of
+ Just a -> do
+ debug ["stopping removed job for", fromScheduledActivity activity, show (asyncThreadId a)]
+ liftIO $ cancel a
+ Nothing -> noop
+
+ lastruntimes <- liftAnnex getLastRunTimes
+ started <- startactivities (S.toList addedactivities) lastruntimes
+ let addedamap = M.fromList $ map fst started
+ let addednmap = M.fromList $ catMaybes $ map snd started
+
+ let removefiltered = M.filterWithKey (\k _ -> S.member k removedactivities)
+ let amap' = M.difference (M.union addedamap amap) (removefiltered amap)
+ let nmap' = M.difference (M.union addednmap nmap) (removefiltered nmap)
+ modifyDaemonStatus_ $ \s -> s { connectRemoteNotifiers = M.fromListWith (++) (M.elems nmap') }
+
+ liftIO $ waitNotification h
+ debug ["reloading changed activities"]
+ go h amap' nmap'
+ startactivities as lastruntimes = forM as $ \activity ->
+ case connectActivityUUID activity of
+ Nothing -> do
+ runner <- asIO2 (sleepingActivityThread urlrenderer)
+ a <- liftIO $ async $
+ runner activity (M.lookup activity lastruntimes)
+ return ((activity, a), Nothing)
+ Just u -> do
+ mvar <- liftIO newEmptyMVar
+ runner <- asIO2 (remoteActivityThread urlrenderer mvar)
+ a <- liftIO $ async $
+ runner activity (M.lookup activity lastruntimes)
+ return ((activity, a), Just (activity, (u, [mvar])))
+
+{- Calculate the next time the activity is scheduled to run, then
+ - sleep until that time, and run it. Then call setLastRunTime, and
+ - loop.
+ -}
+sleepingActivityThread :: UrlRenderer -> ScheduledActivity -> Maybe LocalTime -> Assistant ()
+sleepingActivityThread urlrenderer activity lasttime = go lasttime =<< getnexttime lasttime
+ where
+ getnexttime = liftIO . nextTime schedule
+ go _ Nothing = debug ["no scheduled events left for", desc]
+ go l (Just (NextTimeExactly t)) = waitrun l t Nothing
+ go l (Just (NextTimeWindow windowstart windowend)) =
+ waitrun l windowstart (Just windowend)
+ desc = fromScheduledActivity activity
+ schedule = getSchedule activity
+ waitrun l t mmaxt = do
+ seconds <- liftIO $ secondsUntilLocalTime t
+ when (seconds > Seconds 0) $ do
+ debug ["waiting", show seconds, "for next scheduled", desc]
+ liftIO $ threadDelaySeconds seconds
+ now <- liftIO getCurrentTime
+ tz <- liftIO $ getTimeZone now
+ let nowt = utcToLocalTime tz now
+ if tolate nowt tz
+ then do
+ debug ["too late to run scheduled", desc]
+ go l =<< getnexttime l
+ else run nowt
+ where
+ tolate nowt tz = case mmaxt of
+ Just maxt -> nowt > maxt
+ -- allow the job to start 10 minutes late
+ Nothing ->diffUTCTime
+ (localTimeToUTC tz nowt)
+ (localTimeToUTC tz t) > 600
+ run nowt = do
+ runActivity urlrenderer activity nowt
+ go (Just nowt) =<< getnexttime (Just nowt)
+
+{- Wait for the remote to become available by waiting on the MVar.
+ - Then check if the time is within a time window when activity
+ - is scheduled to run, and if so run it.
+ - Otherwise, just wait again on the MVar.
+ -}
+remoteActivityThread :: UrlRenderer -> MVar () -> ScheduledActivity -> Maybe LocalTime -> Assistant ()
+remoteActivityThread urlrenderer mvar activity lasttime = do
+ liftIO $ takeMVar mvar
+ go =<< liftIO (nextTime (getSchedule activity) lasttime)
+ where
+ go (Just (NextTimeWindow windowstart windowend)) = do
+ now <- liftIO getCurrentTime
+ tz <- liftIO $ getTimeZone now
+ if now >= localTimeToUTC tz windowstart && now <= localTimeToUTC tz windowend
+ then do
+ let nowt = utcToLocalTime tz now
+ runActivity urlrenderer activity nowt
+ loop (Just nowt)
+ else loop lasttime
+ go _ = noop -- running at exact time not handled here
+ loop = remoteActivityThread urlrenderer mvar activity
+
+secondsUntilLocalTime :: LocalTime -> IO Seconds
+secondsUntilLocalTime t = do
+ now <- getCurrentTime
+ tz <- getTimeZone now
+ let secs = truncate $ diffUTCTime (localTimeToUTC tz t) now
+ return $ if secs > 0
+ then Seconds secs
+ else Seconds 0
+
+runActivity :: UrlRenderer -> ScheduledActivity -> LocalTime -> Assistant ()
+runActivity urlrenderer activity nowt = do
+ debug ["starting", desc]
+ runActivity' urlrenderer activity
+ debug ["finished", desc]
+ liftAnnex $ setLastRunTime activity nowt
+ where
+ desc = fromScheduledActivity activity
+
+runActivity' :: UrlRenderer -> ScheduledActivity -> Assistant ()
+runActivity' urlrenderer (ScheduledSelfFsck _ d) = do
+ program <- liftIO $ readProgramFile
+ g <- liftAnnex gitRepo
+ fsckresults <- showFscking urlrenderer Nothing $ tryNonAsync $ do
+ void $ batchCommand program (Param "fsck" : annexFsckParams d)
+ Git.Fsck.findBroken True g
+ u <- liftAnnex getUUID
+ void $ repairWhenNecessary urlrenderer u Nothing fsckresults
+ mapM_ reget =<< liftAnnex (dirKeys gitAnnexBadDir)
+ where
+ reget k = queueTransfers "fsck found bad file; redownloading" Next k Nothing Download
+runActivity' urlrenderer (ScheduledRemoteFsck u s d) = handle =<< liftAnnex (remoteFromUUID u)
+ where
+ handle Nothing = debug ["skipping remote fsck of uuid without a configured remote", fromUUID u, fromSchedule s]
+ handle (Just rmt) = void $ case Remote.remoteFsck rmt of
+ Nothing -> go rmt $ do
+ program <- readProgramFile
+ void $ batchCommand program $
+ [ Param "fsck"
+ -- avoid downloading files
+ , Param "--fast"
+ , Param "--from"
+ , Param $ Remote.name rmt
+ ] ++ annexFsckParams d
+ Just mkfscker -> do
+ {- Note that having mkfsker return an IO action
+ - avoids running a long duration fsck in the
+ - Annex monad. -}
+ go rmt =<< liftAnnex (mkfscker (annexFsckParams d))
+ go rmt annexfscker = do
+ fsckresults <- showFscking urlrenderer (Just rmt) $ tryNonAsync $ do
+ void annexfscker
+ let r = Remote.repo rmt
+ if Git.repoIsLocal r && not (Git.repoIsLocalUnknown r)
+ then Just <$> Git.Fsck.findBroken True r
+ else pure Nothing
+ maybe noop (void . repairWhenNecessary urlrenderer u (Just rmt)) fsckresults
+
+annexFsckParams :: Duration -> [CommandParam]
+annexFsckParams d =
+ [ Param "--incremental-schedule=1d"
+ , Param $ "--time-limit=" ++ fromDuration d
+ ]
diff --git a/Assistant/Threads/Glacier.hs b/Assistant/Threads/Glacier.hs
index 46f64cd56..4c4012a67 100644
--- a/Assistant/Threads/Glacier.hs
+++ b/Assistant/Threads/Glacier.hs
@@ -30,7 +30,7 @@ glacierThread = namedThread "Glacier" $ runEvery (Seconds 3600) <~> go
go = do
rs <- filter isglacier . syncDataRemotes <$> getDaemonStatus
forM_ rs $ \r ->
- check r =<< (liftAnnex $ getFailedTransfers $ Remote.uuid r)
+ check r =<< liftAnnex (getFailedTransfers $ Remote.uuid r)
check _ [] = noop
check r l = do
let keys = map getkey l
diff --git a/Assistant/Threads/Merger.hs b/Assistant/Threads/Merger.hs
index 650293e4b..3f4fcb0cc 100644
--- a/Assistant/Threads/Merger.hs
+++ b/Assistant/Threads/Merger.hs
@@ -54,7 +54,7 @@ runHandler handler file _filestatus =
{- Called when there's an error with inotify. -}
onErr :: Handler
-onErr msg = error msg
+onErr = error
{- Called when a new branch ref is written, or a branch ref is modified.
-
@@ -110,7 +110,7 @@ equivBranches x y = base x == base y
isAnnexBranch :: FilePath -> Bool
isAnnexBranch f = n `isSuffixOf` f
where
- n = "/" ++ show Annex.Branch.name
+ n = '/' : show Annex.Branch.name
fileToBranch :: FilePath -> Git.Ref
fileToBranch f = Git.Ref $ "refs" </> base
diff --git a/Assistant/Threads/MountWatcher.hs b/Assistant/Threads/MountWatcher.hs
index 143ae9cee..39ae67537 100644
--- a/Assistant/Threads/MountWatcher.hs
+++ b/Assistant/Threads/MountWatcher.hs
@@ -19,6 +19,8 @@ import Utility.ThreadScheduler
import Utility.Mounts
import Remote.List
import qualified Types.Remote as Remote
+import Assistant.Types.UrlRenderer
+import Assistant.Fsck
import qualified Data.Set as S
@@ -33,18 +35,18 @@ import qualified Control.Exception as E
#warning Building without dbus support; will use mtab polling
#endif
-mountWatcherThread :: NamedThread
-mountWatcherThread = namedThread "MountWatcher" $
+mountWatcherThread :: UrlRenderer -> NamedThread
+mountWatcherThread urlrenderer = namedThread "MountWatcher" $
#if WITH_DBUS
- dbusThread
+ dbusThread urlrenderer
#else
- pollingThread
+ pollingThread urlrenderer
#endif
#if WITH_DBUS
-dbusThread :: Assistant ()
-dbusThread = do
+dbusThread :: UrlRenderer -> Assistant ()
+dbusThread urlrenderer = do
runclient <- asIO1 go
r <- liftIO $ E.try $ runClient getSessionAddress runclient
either onerr (const noop) r
@@ -59,13 +61,13 @@ dbusThread = do
handleevent <- asIO1 $ \_event -> do
nowmounted <- liftIO $ currentMountPoints
wasmounted <- liftIO $ swapMVar mvar nowmounted
- handleMounts wasmounted nowmounted
+ handleMounts urlrenderer wasmounted nowmounted
liftIO $ forM_ mountChanged $ \matcher ->
listen client matcher handleevent
, do
liftAnnex $
warning "No known volume monitor available through dbus; falling back to mtab polling"
- pollingThread
+ pollingThread urlrenderer
)
onerr :: E.SomeException -> Assistant ()
onerr e = do
@@ -76,7 +78,7 @@ dbusThread = do
- done in this situation. -}
liftAnnex $
warning $ "dbus failed; falling back to mtab polling (" ++ show e ++ ")"
- pollingThread
+ pollingThread urlrenderer
{- Examine the list of services connected to dbus, to see if there
- are any we can use to monitor mounts. If not, will attempt to start one. -}
@@ -139,24 +141,25 @@ mountChanged = [gvfs True, gvfs False, kde, kdefallback]
#endif
-pollingThread :: Assistant ()
-pollingThread = go =<< liftIO currentMountPoints
+pollingThread :: UrlRenderer -> Assistant ()
+pollingThread urlrenderer = go =<< liftIO currentMountPoints
where
go wasmounted = do
liftIO $ threadDelaySeconds (Seconds 10)
nowmounted <- liftIO currentMountPoints
- handleMounts wasmounted nowmounted
+ handleMounts urlrenderer wasmounted nowmounted
go nowmounted
-handleMounts :: MountPoints -> MountPoints -> Assistant ()
-handleMounts wasmounted nowmounted =
- mapM_ (handleMount . mnt_dir) $
+handleMounts :: UrlRenderer -> MountPoints -> MountPoints -> Assistant ()
+handleMounts urlrenderer wasmounted nowmounted =
+ mapM_ (handleMount urlrenderer . mnt_dir) $
S.toList $ newMountPoints wasmounted nowmounted
-handleMount :: FilePath -> Assistant ()
-handleMount dir = do
+handleMount :: UrlRenderer -> FilePath -> Assistant ()
+handleMount urlrenderer dir = do
debug ["detected mount of", dir]
rs <- filter (Git.repoIsLocal . Remote.repo) <$> remotesUnder dir
+ mapM_ (fsckNudge urlrenderer . Just) rs
reconnectRemotes True rs
{- Finds remotes located underneath the mount point.
@@ -173,15 +176,15 @@ remotesUnder dir = do
rs <- liftAnnex remoteList
pairs <- liftAnnex $ mapM (checkremote repotop) rs
let (waschanged, rs') = unzip pairs
- when (any id waschanged) $ do
- liftAnnex $ Annex.changeState $ \s -> s { Annex.remotes = rs' }
+ when (or waschanged) $ do
+ liftAnnex $ Annex.changeState $ \s -> s { Annex.remotes = catMaybes rs' }
updateSyncRemotes
- return $ map snd $ filter fst pairs
+ return $ mapMaybe snd $ filter fst pairs
where
checkremote repotop r = case Remote.localpath r of
Just p | dirContains dir (absPathFrom repotop p) ->
(,) <$> pure True <*> updateRemote r
- _ -> return (False, r)
+ _ -> return (False, Just r)
type MountPoints = S.Set Mntent
diff --git a/Assistant/Threads/NetWatcher.hs b/Assistant/Threads/NetWatcher.hs
index 5974de11d..0d8442c69 100644
--- a/Assistant/Threads/NetWatcher.hs
+++ b/Assistant/Threads/NetWatcher.hs
@@ -39,7 +39,11 @@ netWatcherThread = thread noop
- network connection changes, but it also ensures that
- any networked remotes that may have not been routable for a
- while (despite the local network staying up), are synced with
- - periodically. -}
+ - periodically.
+ -
+ - Note that it does not call notifyNetMessagerRestart, because
+ - it doesn't know that the network has changed.
+ -}
netWatcherFallbackThread :: NamedThread
netWatcherFallbackThread = namedThread "NetWatcherFallback" $
runEvery (Seconds 3600) <~> handleConnection
diff --git a/Assistant/Threads/PairListener.hs b/Assistant/Threads/PairListener.hs
index 8fc015c22..cd95ab5a4 100644
--- a/Assistant/Threads/PairListener.hs
+++ b/Assistant/Threads/PairListener.hs
@@ -16,6 +16,7 @@ import Assistant.WebApp.Types
import Assistant.Alert
import Assistant.DaemonStatus
import Utility.ThreadScheduler
+import Utility.Format
import Git
import Network.Multicast
@@ -27,7 +28,7 @@ pairListenerThread :: UrlRenderer -> NamedThread
pairListenerThread urlrenderer = namedThread "PairListener" $ do
listener <- asIO1 $ go [] []
liftIO $ withSocketsDo $
- runEvery (Seconds 1) $ void $ tryIO $
+ runEvery (Seconds 60) $ void $ tryIO $
listener =<< getsock
where
{- Note this can crash if there's no network interface,
@@ -42,20 +43,32 @@ pairListenerThread urlrenderer = namedThread "PairListener" $ do
(pip, verified) <- verificationCheck m
=<< (pairingInProgress <$> getDaemonStatus)
let wrongstage = maybe False (\p -> pairMsgStage m <= inProgressPairStage p) pip
- case (wrongstage, sane, pairMsgStage m) of
- -- ignore our own messages, and
- -- out of order messages
- (True, _, _) -> go reqs cache sock
- (_, False, _) -> go reqs cache sock
- (_, _, PairReq) -> if m `elem` reqs
+ let fromus = maybe False (\p -> remoteSshPubKey (pairMsgData m) == remoteSshPubKey (inProgressPairData p)) pip
+ case (wrongstage, fromus, sane, pairMsgStage m) of
+ (_, True, _, _) -> do
+ debug ["ignoring message that looped back"]
+ go reqs cache sock
+ (_, _, False, _) -> go reqs cache sock
+ -- PairReq starts a pairing process, so a
+ -- new one is always heeded, even if
+ -- some other pairing is in process.
+ (_, _, _, PairReq) -> if m `elem` reqs
then go reqs (invalidateCache m cache) sock
else do
pairReqReceived verified urlrenderer m
go (m:take 10 reqs) (invalidateCache m cache) sock
- (_, _, PairAck) -> do
+ (True, _, _, _) -> do
+ debug
+ ["ignoring out of order message"
+ , show (pairMsgStage m)
+ , "expected"
+ , show (succ . inProgressPairStage <$> pip)
+ ]
+ go reqs cache sock
+ (_, _, _, PairAck) -> do
cache' <- pairAckReceived verified pip m cache
go reqs cache' sock
- (_, _, PairDone) -> do
+ (_,_ , _, PairDone) -> do
pairDoneReceived verified pip m
go reqs cache sock
@@ -75,11 +88,10 @@ pairListenerThread urlrenderer = namedThread "PairListener" $ do
verified = verifiedPairMsg m pip
sameuuid = pairUUID (inProgressPairData pip) == pairUUID (pairMsgData m)
- {- Various sanity checks on the content of the message. -}
- checkSane msg
+ checkSane msg
{- Control characters could be used in a
- console poisoning attack. -}
- | any isControl msg || any (`elem` "\r\n") msg = do
+ | any isControl (filter (/= '\n') (decode_c msg)) = do
liftAnnex $ warning
"illegal control characters in pairing message; ignoring"
return False
@@ -102,7 +114,7 @@ pairListenerThread urlrenderer = namedThread "PairListener" $ do
pairReqReceived :: Bool -> UrlRenderer -> PairMsg -> Assistant ()
pairReqReceived True _ _ = noop -- ignore our own PairReq
pairReqReceived False urlrenderer msg = do
- button <- mkAlertButton (T.pack "Respond") urlrenderer (FinishLocalPairR msg)
+ button <- mkAlertButton True (T.pack "Respond") urlrenderer (FinishLocalPairR msg)
void $ addAlert $ pairRequestReceivedAlert repo button
where
repo = pairRepo msg
diff --git a/Assistant/Threads/ProblemFixer.hs b/Assistant/Threads/ProblemFixer.hs
new file mode 100644
index 000000000..8095581a6
--- /dev/null
+++ b/Assistant/Threads/ProblemFixer.hs
@@ -0,0 +1,70 @@
+{- git-annex assistant thread to handle fixing problems with repositories
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Assistant.Threads.ProblemFixer (
+ problemFixerThread
+) where
+
+import Assistant.Common
+import Assistant.Types.RepoProblem
+import Assistant.RepoProblem
+import Assistant.Types.UrlRenderer
+import Assistant.Alert
+import Remote
+import qualified Types.Remote as Remote
+import qualified Git.Fsck
+import Assistant.Repair
+import qualified Git
+import Annex.UUID
+import Utility.ThreadScheduler
+
+{- Waits for problems with a repo, and tries to fsck the repo and repair
+ - the problem. -}
+problemFixerThread :: UrlRenderer -> NamedThread
+problemFixerThread urlrenderer = namedThread "ProblemFixer" $
+ go =<< getRepoProblems
+ where
+ go problems = do
+ mapM_ (handleProblem urlrenderer) problems
+ liftIO $ threadDelaySeconds (Seconds 60)
+ -- Problems may have been re-reported while they were being
+ -- fixed, so ignore those. If a new unique problem happened
+ -- 60 seconds after the last was fixed, we're unlikely
+ -- to do much good anyway.
+ go =<< filter (\p -> not (any (sameRepoProblem p) problems))
+ <$> getRepoProblems
+
+handleProblem :: UrlRenderer -> RepoProblem -> Assistant ()
+handleProblem urlrenderer repoproblem = do
+ fixed <- ifM ((==) (problemUUID repoproblem) <$> liftAnnex getUUID)
+ ( handleLocalRepoProblem urlrenderer
+ , maybe (return False) (handleRemoteProblem urlrenderer)
+ =<< liftAnnex (remoteFromUUID $ problemUUID repoproblem)
+ )
+ when fixed $
+ liftIO $ afterFix repoproblem
+
+handleRemoteProblem :: UrlRenderer -> Remote -> Assistant Bool
+handleRemoteProblem urlrenderer rmt
+ | Git.repoIsLocal r && not (Git.repoIsLocalUnknown r) =
+ ifM (liftIO $ checkAvailable True rmt)
+ ( do
+ fixedlocks <- repairStaleGitLocks r
+ fsckresults <- showFscking urlrenderer (Just rmt) $ tryNonAsync $
+ Git.Fsck.findBroken True r
+ repaired <- repairWhenNecessary urlrenderer (Remote.uuid rmt) (Just rmt) fsckresults
+ return $ fixedlocks || repaired
+ , return False
+ )
+ | otherwise = return False
+ where
+ r = Remote.repo rmt
+
+{- This is not yet used, and should probably do a fsck. -}
+handleLocalRepoProblem :: UrlRenderer -> Assistant Bool
+handleLocalRepoProblem _urlrenderer = do
+ repairStaleGitLocks =<< liftAnnex gitRepo
diff --git a/Assistant/Threads/Pusher.hs b/Assistant/Threads/Pusher.hs
index 060f26cf5..3ec922fe4 100644
--- a/Assistant/Threads/Pusher.hs
+++ b/Assistant/Threads/Pusher.hs
@@ -13,6 +13,7 @@ import Assistant.Pushes
import Assistant.DaemonStatus
import Assistant.Sync
import Utility.ThreadScheduler
+import qualified Remote
import qualified Types.Remote as Remote
{- This thread retries pushes that failed before. -}
@@ -42,7 +43,7 @@ pushThread = namedThread "Pusher" $ runEvery (Seconds 2) <~> do
- to avoid ugly messages when a removable drive is not attached.
-}
pushTargets :: Assistant [Remote]
-pushTargets = liftIO . filterM available =<< candidates <$> getDaemonStatus
+pushTargets = liftIO . filterM (Remote.checkAvailable True)
+ =<< candidates <$> getDaemonStatus
where
candidates = filter (not . Remote.readonly) . syncGitRemotes
- available = maybe (return True) doesDirectoryExist . Remote.localpath
diff --git a/Assistant/Threads/SanityChecker.hs b/Assistant/Threads/SanityChecker.hs
index 0c97a9e8f..6946e8b3a 100644
--- a/Assistant/Threads/SanityChecker.hs
+++ b/Assistant/Threads/SanityChecker.hs
@@ -1,11 +1,12 @@
{- git-annex assistant sanity checker
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012, 2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Assistant.Threads.SanityChecker (
+ sanityCheckerStartupThread,
sanityCheckerDailyThread,
sanityCheckerHourlyThread
) where
@@ -13,6 +14,7 @@ module Assistant.Threads.SanityChecker (
import Assistant.Common
import Assistant.DaemonStatus
import Assistant.Alert
+import Assistant.Repair
import qualified Git.LsFiles
import qualified Git.Command
import qualified Git.Config
@@ -20,9 +22,43 @@ import Utility.ThreadScheduler
import qualified Assistant.Threads.Watcher as Watcher
import Utility.LogFile
import Utility.Batch
+import Utility.NotificationBroadcaster
import Config
+import Utility.HumanTime
+import Git.Repair
import Data.Time.Clock.POSIX
+import qualified Data.Set as S
+
+{- This thread runs once at startup, and most other threads wait for it
+ - to finish. (However, the webapp thread does not, to prevent the UI
+ - being nonresponsive.) -}
+sanityCheckerStartupThread :: Maybe Duration -> NamedThread
+sanityCheckerStartupThread startupdelay = namedThreadUnchecked "SanityCheckerStartup" $ do
+ {- Stale git locks can prevent commits from happening, etc. -}
+ void $ repairStaleGitLocks =<< liftAnnex gitRepo
+
+ {- A corrupt index file can prevent the assistant from working at
+ - all, so detect and repair. -}
+ ifM (not <$> liftAnnex (inRepo (checkIndex S.empty)))
+ ( do
+ notice ["corrupt index file found at startup; removing and restaging"]
+ liftAnnex $ inRepo nukeIndex
+ {- Normally the startup scan avoids re-staging files,
+ - but with the index deleted, everything needs to be
+ - restaged. -}
+ modifyDaemonStatus_ $ \s -> s { forceRestage = True }
+ , whenM (liftAnnex $ inRepo missingIndex) $ do
+ debug ["no index file; restaging"]
+ modifyDaemonStatus_ $ \s -> s { forceRestage = True }
+ )
+
+ {- If there's a startup delay, it's done here. -}
+ liftIO $ maybe noop (threadDelaySeconds . Seconds . fromIntegral . durationSeconds) startupdelay
+
+ {- Notify other threads that the startup sanity check is done. -}
+ status <- getDaemonStatus
+ liftIO $ sendNotification $ startupSanityCheckNotifier status
{- This thread wakes up hourly for inxepensive frequent sanity checks. -}
sanityCheckerHourlyThread :: NamedThread
@@ -42,7 +78,7 @@ sanityCheckerDailyThread = namedThread "SanityCheckerDaily" $ forever $ do
go = do
modifyDaemonStatus_ $ \s -> s { sanityCheckRunning = True }
- now <- liftIO $ getPOSIXTime -- before check started
+ now <- liftIO getPOSIXTime -- before check started
r <- either showerr return =<< (tryIO . batch) <~> dailyCheck
modifyDaemonStatus_ $ \s -> s
@@ -78,7 +114,7 @@ dailyCheck = do
-- Find old unstaged symlinks, and add them to git.
(unstaged, cleanup) <- liftIO $ Git.LsFiles.notInRepo False ["."] g
- now <- liftIO $ getPOSIXTime
+ now <- liftIO getPOSIXTime
forM_ unstaged $ \file -> do
ms <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus file
case ms of
@@ -136,3 +172,4 @@ oneHour = 60 * 60
oneDay :: Int
oneDay = 24 * oneHour
+
diff --git a/Assistant/Threads/TransferScanner.hs b/Assistant/Threads/TransferScanner.hs
index 5a6871fdb..ba302d6bb 100644
--- a/Assistant/Threads/TransferScanner.hs
+++ b/Assistant/Threads/TransferScanner.hs
@@ -81,24 +81,23 @@ transferScannerThread urlrenderer = namedThread "TransferScanner" $ do
{- This is a cheap scan for failed transfers involving a remote. -}
failedTransferScan :: Remote -> Assistant ()
failedTransferScan r = do
- failed <- liftAnnex $ getFailedTransfers (Remote.uuid r)
- liftAnnex $ mapM_ removeFailedTransfer $ map fst failed
+ failed <- liftAnnex $ clearFailedTransfers (Remote.uuid r)
mapM_ retry failed
where
retry (t, info)
- | transferDirection t == Download = do
+ | transferDirection t == Download =
{- Check if the remote still has the key.
- If not, relies on the expensiveScan to
- get it queued from some other remote. -}
whenM (liftAnnex $ remoteHas r $ transferKey t) $
requeue t info
- | otherwise = do
+ | otherwise =
{- The Transferrer checks when uploading
- that the remote doesn't already have the
- key, so it's not redundantly checked here. -}
requeue t info
requeue t info = queueTransferWhenSmall "retrying failed transfer" (associatedFile info) t r
-
+
{- This is a expensive scan through the full git work tree, finding
- files to transfer. The scan is blocked when the transfer queue gets
- too large.
@@ -118,8 +117,12 @@ expensiveScan :: UrlRenderer -> [Remote] -> Assistant ()
expensiveScan urlrenderer rs = unless onlyweb $ batch <~> do
debug ["starting scan of", show visiblers]
+ let us = map Remote.uuid rs
+
+ mapM_ (liftAnnex . clearFailedTransfers) us
+
unwantedrs <- liftAnnex $ S.fromList
- <$> filterM inUnwantedGroup (map Remote.uuid rs)
+ <$> filterM inUnwantedGroup us
g <- liftAnnex gitRepo
(files, cleanup) <- liftIO $ LsFiles.inRepo [] g
@@ -158,7 +161,7 @@ expensiveScan urlrenderer rs = unless onlyweb $ batch <~> do
present key (Just f) Nothing
liftAnnex $ do
let slocs = S.fromList locs
- let use a = return $ catMaybes $ map (a key slocs) syncrs
+ let use a = return $ mapMaybe (a key slocs) syncrs
ts <- if present
then filterM (wantSend True (Just f) . Remote.uuid . fst)
=<< use (genTransfer Upload False)
@@ -170,7 +173,7 @@ expensiveScan urlrenderer rs = unless onlyweb $ batch <~> do
genTransfer :: Direction -> Bool -> Key -> S.Set UUID -> Remote -> Maybe (Remote, Transfer)
genTransfer direction want key slocs r
| direction == Upload && Remote.readonly r = Nothing
- | (S.member (Remote.uuid r) slocs) == want = Just
+ | S.member (Remote.uuid r) slocs == want = Just
(r, Transfer direction (Remote.uuid r) key)
| otherwise = Nothing
diff --git a/Assistant/Threads/TransferWatcher.hs b/Assistant/Threads/TransferWatcher.hs
index 7045e842d..fc09373e7 100644
--- a/Assistant/Threads/TransferWatcher.hs
+++ b/Assistant/Threads/TransferWatcher.hs
@@ -9,9 +9,7 @@ module Assistant.Threads.TransferWatcher where
import Assistant.Common
import Assistant.DaemonStatus
-import Assistant.TransferQueue
-import Assistant.Drop
-import Annex.Content
+import Assistant.TransferSlots
import Logs.Transfer
import Utility.DirWatcher
import Utility.DirWatcher.Types
@@ -51,7 +49,7 @@ runHandler handler file _filestatus =
{- Called when there's an error with inotify. -}
onErr :: Handler
-onErr msg = error msg
+onErr = error
{- Called when a new transfer information file is written. -}
onAdd :: Handler
@@ -70,10 +68,9 @@ onAdd file = case parseTransferFile file of
- The only thing that should change in the transfer info is the
- bytesComplete, so that's the only thing updated in the DaemonStatus. -}
onModify :: Handler
-onModify file = do
- case parseTransferFile file of
- Nothing -> noop
- Just t -> go t =<< liftIO (readTransferInfoFile Nothing file)
+onModify file = case parseTransferFile file of
+ Nothing -> noop
+ Just t -> go t =<< liftIO (readTransferInfoFile Nothing file)
where
go _ Nothing = noop
go t (Just newinfo) = alterTransferInfo t $
@@ -99,28 +96,3 @@ onDel file = case parseTransferFile file of
- runs. -}
threadDelay 10000000 -- 10 seconds
finished t minfo
-
-{- Queue uploads of files downloaded to us, spreading them
- - out to other reachable remotes.
- -
- - Downloading a file may have caused a remote to not want it;
- - so check for drops from remotes.
- -
- - Uploading a file may cause the local repo, or some other remote to not
- - want it; handle that too.
- -}
-finishedTransfer :: Transfer -> Maybe TransferInfo -> Assistant ()
-finishedTransfer t (Just info)
- | transferDirection t == Download =
- whenM (liftAnnex $ inAnnex $ transferKey t) $ do
- dodrops False
- queueTransfersMatching (/= transferUUID t)
- "newly received object"
- Later (transferKey t) (associatedFile info) Upload
- | otherwise = dodrops True
- where
- dodrops fromhere = handleDrops
- ("drop wanted after " ++ describeTransfer t info)
- fromhere (transferKey t) (associatedFile info) Nothing
-finishedTransfer _ _ = noop
-
diff --git a/Assistant/Threads/Transferrer.hs b/Assistant/Threads/Transferrer.hs
index 67a8c2a7b..0bc419e15 100644
--- a/Assistant/Threads/Transferrer.hs
+++ b/Assistant/Threads/Transferrer.hs
@@ -8,133 +8,18 @@
module Assistant.Threads.Transferrer where
import Assistant.Common
-import Assistant.DaemonStatus
import Assistant.TransferQueue
import Assistant.TransferSlots
-import Assistant.Alert
-import Assistant.Alert.Utility
-import Assistant.Commits
-import Assistant.Drop
-import Assistant.TransferrerPool
import Logs.Transfer
-import Logs.Location
-import Annex.Content
-import qualified Remote
-import qualified Types.Remote as Remote
-import qualified Git
import Config.Files
-import Assistant.Threads.TransferWatcher
-import Annex.Wanted
{- Dispatches transfers from the queue. -}
transfererThread :: NamedThread
transfererThread = namedThread "Transferrer" $ do
program <- liftIO readProgramFile
forever $ inTransferSlot program $
- maybe (return Nothing) (uncurry $ genTransfer)
+ maybe (return Nothing) (uncurry genTransfer)
=<< getNextTransfer notrunning
where
{- Skip transfers that are already running. -}
notrunning = isNothing . startedTime
-
-{- By the time this is called, the daemonstatus's currentTransfers map should
- - already have been updated to include the transfer. -}
-genTransfer :: Transfer -> TransferInfo -> TransferGenerator
-genTransfer t info = case (transferRemote info, associatedFile info) of
- (Just remote, Just file)
- | Git.repoIsLocalUnknown (Remote.repo remote) -> do
- -- optimisation for removable drives not plugged in
- liftAnnex $ recordFailedTransfer t info
- void $ removeTransfer t
- return Nothing
- | otherwise -> ifM (liftAnnex $ shouldTransfer t info)
- ( do
- debug [ "Transferring:" , describeTransfer t info ]
- notifyTransfer
- return $ Just (t, info, go remote file)
- , do
- debug [ "Skipping unnecessary transfer:",
- describeTransfer t info ]
- void $ removeTransfer t
- finishedTransfer t (Just info)
- return Nothing
- )
- _ -> return Nothing
- where
- direction = transferDirection t
- isdownload = direction == Download
-
- {- Alerts are only shown for successful transfers.
- - Transfers can temporarily fail for many reasons,
- - so there's no point in bothering the user about
- - those. The assistant should recover.
- -
- - After a successful upload, handle dropping it from
- - here, if desired. In this case, the remote it was
- - uploaded to is known to have it.
- -
- - Also, after a successful transfer, the location
- - log has changed. Indicate that a commit has been
- - made, in order to queue a push of the git-annex
- - branch out to remotes that did not participate
- - in the transfer.
- -
- - If the process failed, it could have crashed,
- - so remove the transfer from the list of current
- - transfers, just in case it didn't stop
- - in a way that lets the TransferWatcher do its
- - usual cleanup. However, first check if something else is
- - running the transfer, to avoid removing active transfers.
- -}
- go remote file transferrer = ifM (liftIO $ performTransfer transferrer t $ associatedFile info)
- ( do
- void $ addAlert $ makeAlertFiller True $
- transferFileAlert direction True file
- unless isdownload $
- handleDrops
- ("object uploaded to " ++ show remote)
- True (transferKey t)
- (associatedFile info)
- (Just remote)
- void $ recordCommit
- , whenM (liftAnnex $ isNothing <$> checkTransfer t) $
- void $ removeTransfer t
- )
-
-{- Called right before a transfer begins, this is a last chance to avoid
- - unnecessary transfers.
- -
- - For downloads, we obviously don't need to download if the already
- - have the object.
- -
- - Smilarly, for uploads, check if the remote is known to already have
- - the object.
- -
- - Also, uploads get queued to all remotes, in order of cost.
- - This may mean, for example, that an object is uploaded over the LAN
- - to a locally paired client, and once that upload is done, a more
- - expensive transfer remote no longer wants the object. (Since
- - all the clients have it already.) So do one last check if this is still
- - preferred content.
- -
- - We'll also do one last preferred content check for downloads. An
- - example of a case where this could be needed is if a download is queued
- - for a file that gets moved out of an archive directory -- but before
- - that download can happen, the file is put back in the archive.
- -}
-shouldTransfer :: Transfer -> TransferInfo -> Annex Bool
-shouldTransfer t info
- | transferDirection t == Download =
- (not <$> inAnnex key) <&&> wantGet True file
- | transferDirection t == Upload = case transferRemote info of
- Nothing -> return False
- Just r -> notinremote r
- <&&> wantSend True file (Remote.uuid r)
- | otherwise = return False
- where
- key = transferKey t
- file = associatedFile info
-
- {- Trust the location log to check if the remote already has
- - the key. This avoids a roundtrip to the remote. -}
- notinremote r = notElem (Remote.uuid r) <$> loggedLocations key
diff --git a/Assistant/Threads/Watcher.hs b/Assistant/Threads/Watcher.hs
index ef8bcd41f..6a56eadbb 100644
--- a/Assistant/Threads/Watcher.hs
+++ b/Assistant/Threads/Watcher.hs
@@ -5,11 +5,11 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE DeriveDataTypeable, BangPatterns, CPP #-}
+{-# LANGUAGE DeriveDataTypeable, CPP #-}
module Assistant.Threads.Watcher (
watchThread,
- WatcherException(..),
+ WatcherControl(..),
checkCanWatch,
needLsof,
onAddSymlink,
@@ -23,7 +23,7 @@ import Assistant.Types.Changes
import Assistant.Alert
import Utility.DirWatcher
import Utility.DirWatcher.Types
-import Utility.Lsof
+import qualified Utility.Lsof as Lsof
import qualified Annex
import qualified Annex.Queue
import qualified Git
@@ -50,7 +50,7 @@ import Data.Time.Clock
checkCanWatch :: Annex ()
checkCanWatch
| canWatch = do
- liftIO setupLsof
+ liftIO Lsof.setup
unlessM (liftIO (inPath "lsof") <||> Annex.getState Annex.force)
needLsof
| otherwise = error "watch mode is not available on this system"
@@ -64,10 +64,10 @@ needLsof = error $ unlines
]
{- A special exception that can be thrown to pause or resume the watcher. -}
-data WatcherException = PauseWatcher | ResumeWatcher
+data WatcherControl = PauseWatcher | ResumeWatcher
deriving (Show, Eq, Typeable)
-instance E.Exception WatcherException
+instance E.Exception WatcherControl
watchThread :: NamedThread
watchThread = namedThread "Watcher" $
@@ -79,7 +79,7 @@ watchThread = namedThread "Watcher" $
runWatcher :: Assistant ()
runWatcher = do
startup <- asIO1 startupScan
- matcher <- liftAnnex $ largeFilesMatcher
+ matcher <- liftAnnex largeFilesMatcher
direct <- liftAnnex isDirect
symlinkssupported <- liftAnnex $ coreSymlinks <$> Annex.getGitConfig
addhook <- hook $ if direct
@@ -107,9 +107,9 @@ runWatcher = do
where
hook a = Just <$> asIO2 (runHandler a)
-waitFor :: WatcherException -> Assistant () -> Assistant ()
+waitFor :: WatcherControl -> Assistant () -> Assistant ()
waitFor sig next = do
- r <- liftIO $ (E.try pause :: IO (Either E.SomeException ()))
+ r <- liftIO (E.try pause :: IO (Either E.SomeException ()))
case r of
Left e -> case E.fromException e of
Just s
@@ -124,7 +124,7 @@ startupScan :: IO a -> Assistant a
startupScan scanner = do
liftAnnex $ showAction "scanning"
alertWhile' startupScanAlert $ do
- r <- liftIO $ scanner
+ r <- liftIO scanner
-- Notice any files that were deleted before
-- watching was started.
@@ -133,7 +133,7 @@ startupScan scanner = do
forM_ fs $ \f -> do
liftAnnex $ onDel' f
maybe noop recordChange =<< madeChange f RmChange
- void $ liftIO $ cleanup
+ void $ liftIO cleanup
liftAnnex $ showAction "started"
liftIO $ putStrLn ""
@@ -176,7 +176,7 @@ runHandler handler file filestatus = void $ do
Right (Just change) -> do
-- Just in case the commit thread is not
-- flushing the queue fast enough.
- liftAnnex $ Annex.Queue.flushWhenFull
+ liftAnnex Annex.Queue.flushWhenFull
recordChange change
where
normalize f
@@ -200,6 +200,9 @@ onAdd matcher file filestatus
add matcher file
| otherwise = noChange
+shouldRestage :: DaemonStatus -> Bool
+shouldRestage ds = scanComplete ds || forceRestage ds
+
{- In direct mode, add events are received for both new files, and
- modified existing files.
-}
@@ -214,7 +217,7 @@ onAddDirect symlinkssupported matcher file fs = do
- really modified, but it might have
- just been deleted and been put back,
- so it symlink is restaged to make sure. -}
- ( ifM (scanComplete <$> getDaemonStatus)
+ ( ifM (shouldRestage <$> getDaemonStatus)
( do
link <- liftAnnex $ inRepo $ gitAnnexLink file key
addLink file link (Just key)
@@ -286,7 +289,7 @@ onAddSymlink' linktarget mk isdirect file filestatus = go mk
- links too.)
-}
ensurestaged (Just link) daemonstatus
- | scanComplete daemonstatus = addLink file link mk
+ | shouldRestage daemonstatus = addLink file link mk
| otherwise = case filestatus of
Just s
| not (afterLastDaemonRun (statusChangeTime s) daemonstatus) -> noChange
@@ -300,7 +303,7 @@ addLink file link mk = do
liftAnnex $ do
v <- catObjectDetails $ Ref $ ':':file
case v of
- Just (currlink, sha)
+ Just (currlink, sha, _type)
| s2w8 link == L.unpack currlink ->
stageSymlink file sha
_ -> stageSymlink file =<< hashSymlink link
@@ -340,8 +343,8 @@ onDelDir dir _ = do
now <- liftIO getCurrentTime
recordChanges $ map (\f -> Change now f RmChange) fs
- void $ liftIO $ clean
- liftAnnex $ Annex.Queue.flushWhenFull
+ void $ liftIO clean
+ liftAnnex Annex.Queue.flushWhenFull
noChange
{- Called when there's an error with inotify or kqueue. -}
diff --git a/Assistant/Threads/WebApp.hs b/Assistant/Threads/WebApp.hs
index 0fb038b6a..a5f4f4201 100644
--- a/Assistant/Threads/WebApp.hs
+++ b/Assistant/Threads/WebApp.hs
@@ -29,9 +29,11 @@ import Assistant.WebApp.Configurators.XMPP
import Assistant.WebApp.Configurators.Preferences
import Assistant.WebApp.Configurators.Edit
import Assistant.WebApp.Configurators.Delete
+import Assistant.WebApp.Configurators.Fsck
import Assistant.WebApp.Documentation
import Assistant.WebApp.Control
import Assistant.WebApp.OtherRepos
+import Assistant.WebApp.Repair
import Assistant.Types.ThreadedMonad
import Utility.WebApp
import Utility.Tmp
@@ -83,7 +85,10 @@ webAppThread assistantdata urlrenderer noannex listenhost postfirstrun onstartup
urlfile <- runThreadState st $ fromRepo gitAnnexUrlFile
go addr webapp htmlshim (Just urlfile)
where
- thread = namedThread "WebApp"
+ -- The webapp thread does not wait for the startupSanityCheckThread
+ -- to finish, so that the user interface remains responsive while
+ -- that's going on.
+ thread = namedThreadUnchecked "WebApp"
getreldir
| noannex = return Nothing
| otherwise = Just <$>
diff --git a/Assistant/Threads/XMPPClient.hs b/Assistant/Threads/XMPPClient.hs
index a90ffb820..8eb469939 100644
--- a/Assistant/Threads/XMPPClient.hs
+++ b/Assistant/Threads/XMPPClient.hs
@@ -103,9 +103,8 @@ xmppClient urlrenderer d creds =
- will also be killed. -}
liftIO $ pinger `concurrently` sender `concurrently` receiver
- sendnotifications selfjid = forever $ do
- a <- inAssistant $ relayNetMessage selfjid
- a
+ sendnotifications selfjid = forever $
+ join $ inAssistant $ relayNetMessage selfjid
receivenotifications selfjid lasttraffic = forever $ do
l <- decodeStanza selfjid <$> getStanza
void $ liftIO $ atomically . swapTMVar lasttraffic =<< getCurrentTime
@@ -115,7 +114,7 @@ xmppClient urlrenderer d creds =
sendpings selfjid lasttraffic = forever $ do
putStanza pingstanza
- startping <- liftIO $ getCurrentTime
+ startping <- liftIO getCurrentTime
liftIO $ threadDelaySeconds (Seconds 120)
t <- liftIO $ atomically $ readTMVar lasttraffic
when (t < startping) $ do
@@ -154,8 +153,7 @@ xmppClient urlrenderer d creds =
, logJid jid
, show $ logNetMessage msg'
]
- a <- inAssistant $ convertNetMsg msg' selfjid
- a
+ join $ inAssistant $ convertNetMsg msg' selfjid
inAssistant $ sentImportantNetMessage msg c
resendImportantMessages _ _ = noop
@@ -196,7 +194,7 @@ logClient (Client jid) = logJid jid
decodeStanza :: JID -> ReceivedStanza -> [XMPPEvent]
decodeStanza selfjid s@(ReceivedPresence p)
| presenceType p == PresenceError = [ProtocolError s]
- | presenceFrom p == Nothing = [Ignorable s]
+ | isNothing (presenceFrom p) = [Ignorable s]
| presenceFrom p == Just selfjid = [Ignorable s]
| otherwise = maybe [PresenceMessage p] decode (gitAnnexTagInfo p)
where
@@ -209,7 +207,7 @@ decodeStanza selfjid s@(ReceivedPresence p)
- along with their real meaning. -}
impliedp v = [PresenceMessage p, v]
decodeStanza selfjid s@(ReceivedMessage m)
- | messageFrom m == Nothing = [Ignorable s]
+ | isNothing (messageFrom m) = [Ignorable s]
| messageFrom m == Just selfjid = [Ignorable s]
| messageType m == MessageError = [ProtocolError s]
| otherwise = [fromMaybe (Unknown s) (GotNetMessage <$> decodeMessage m)]
@@ -241,13 +239,13 @@ relayNetMessage selfjid = do
\c -> (baseJID <$> parseJID c) == Just tojid
return $ putStanza presenceQuery
_ -> return noop
- convert (Pushing c pushstage) = withOtherClient selfjid c $ \tojid -> do
+ convert (Pushing c pushstage) = withOtherClient selfjid c $ \tojid ->
if tojid == baseJID tojid
then do
clients <- maybe [] (S.toList . buddyAssistants)
<$> getBuddy (genBuddyKey tojid) <<~ buddyList
debug ["exploded undirected message to clients", unwords $ map logClient clients]
- return $ forM_ (clients) $ \(Client jid) ->
+ return $ forM_ clients $ \(Client jid) ->
putStanza $ pushMessage pushstage jid selfjid
else do
debug ["to client:", logJid tojid]
@@ -266,7 +264,7 @@ convertNetMsg msg selfjid = convert msg
convert (Pushing c pushstage) = withOtherClient selfjid c $ \tojid ->
return $ putStanza $ pushMessage pushstage tojid selfjid
-withOtherClient :: JID -> ClientID -> (JID -> Assistant (XMPP ())) -> (Assistant (XMPP ()))
+withOtherClient :: JID -> ClientID -> (JID -> Assistant (XMPP ())) -> Assistant (XMPP ())
withOtherClient selfjid c a = case parseJID c of
Nothing -> return noop
Just tojid
@@ -323,10 +321,10 @@ pairMsgReceived :: UrlRenderer -> PairStage -> UUID -> JID -> JID -> Assistant (
pairMsgReceived urlrenderer PairReq theiruuid selfjid theirjid
| baseJID selfjid == baseJID theirjid = autoaccept
| otherwise = do
- knownjids <- catMaybes . map (parseJID . getXMPPClientID)
+ knownjids <- mapMaybe (parseJID . getXMPPClientID)
. filter isXMPPRemote . syncRemotes <$> getDaemonStatus
um <- liftAnnex uuidMap
- if any (== baseJID theirjid) knownjids && M.member theiruuid um
+ if elem (baseJID theirjid) knownjids && M.member theiruuid um
then autoaccept
else showalert
@@ -338,7 +336,7 @@ pairMsgReceived urlrenderer PairReq theiruuid selfjid theirjid
finishXMPPPairing theirjid theiruuid
-- Show an alert to let the user decide if they want to pair.
showalert = do
- button <- mkAlertButton (T.pack "Respond") urlrenderer $
+ button <- mkAlertButton True (T.pack "Respond") urlrenderer $
ConfirmXMPPPairFriendR $
PairKey theiruuid $ formatJID theirjid
void $ addAlert $ pairRequestReceivedAlert
diff --git a/Assistant/TransferSlots.hs b/Assistant/TransferSlots.hs
index 81a778a0a..cb66e845a 100644
--- a/Assistant/TransferSlots.hs
+++ b/Assistant/TransferSlots.hs
@@ -5,6 +5,8 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Assistant.TransferSlots where
import Assistant.Common
@@ -13,11 +15,29 @@ import Assistant.Types.TransferSlots
import Assistant.DaemonStatus
import Assistant.TransferrerPool
import Assistant.Types.TransferrerPool
+import Assistant.Types.TransferQueue
+import Assistant.TransferQueue
+import Assistant.Alert
+import Assistant.Alert.Utility
+import Assistant.Commits
+import Assistant.Drop
import Logs.Transfer
+import Logs.Location
+import qualified Git
+import qualified Remote
+import qualified Types.Remote as Remote
+import Annex.Content
+import Annex.Wanted
+import Config.Files
+import qualified Data.Map as M
import qualified Control.Exception as E
import Control.Concurrent
import qualified Control.Concurrent.MSemN as MSemN
+#ifndef mingw32_HOST_OS
+import System.Posix.Process (getProcessGroupIDOf)
+import System.Posix.Signals (signalProcessGroup, sigTERM, sigKILL)
+#endif
type TransferGenerator = Assistant (Maybe (Transfer, TransferInfo, Transferrer -> Assistant ()))
@@ -76,3 +96,191 @@ runTransferThread' program d run = go
_ -> done
done = runAssistant d $
flip MSemN.signal 1 <<~ transferSlots
+
+{- By the time this is called, the daemonstatus's currentTransfers map should
+ - already have been updated to include the transfer. -}
+genTransfer :: Transfer -> TransferInfo -> TransferGenerator
+genTransfer t info = case (transferRemote info, associatedFile info) of
+ (Just remote, Just file)
+ | Git.repoIsLocalUnknown (Remote.repo remote) -> do
+ -- optimisation for removable drives not plugged in
+ liftAnnex $ recordFailedTransfer t info
+ void $ removeTransfer t
+ return Nothing
+ | otherwise -> ifM (liftAnnex $ shouldTransfer t info)
+ ( do
+ debug [ "Transferring:" , describeTransfer t info ]
+ notifyTransfer
+ return $ Just (t, info, go remote file)
+ , do
+ debug [ "Skipping unnecessary transfer:",
+ describeTransfer t info ]
+ void $ removeTransfer t
+ finishedTransfer t (Just info)
+ return Nothing
+ )
+ _ -> return Nothing
+ where
+ direction = transferDirection t
+ isdownload = direction == Download
+
+ {- Alerts are only shown for successful transfers.
+ - Transfers can temporarily fail for many reasons,
+ - so there's no point in bothering the user about
+ - those. The assistant should recover.
+ -
+ - After a successful upload, handle dropping it from
+ - here, if desired. In this case, the remote it was
+ - uploaded to is known to have it.
+ -
+ - Also, after a successful transfer, the location
+ - log has changed. Indicate that a commit has been
+ - made, in order to queue a push of the git-annex
+ - branch out to remotes that did not participate
+ - in the transfer.
+ -
+ - If the process failed, it could have crashed,
+ - so remove the transfer from the list of current
+ - transfers, just in case it didn't stop
+ - in a way that lets the TransferWatcher do its
+ - usual cleanup. However, first check if something else is
+ - running the transfer, to avoid removing active transfers.
+ -}
+ go remote file transferrer = ifM (liftIO $ performTransfer transferrer t $ associatedFile info)
+ ( do
+ void $ addAlert $ makeAlertFiller True $
+ transferFileAlert direction True file
+ unless isdownload $
+ handleDrops
+ ("object uploaded to " ++ show remote)
+ True (transferKey t)
+ (associatedFile info)
+ (Just remote)
+ void recordCommit
+ , whenM (liftAnnex $ isNothing <$> checkTransfer t) $
+ void $ removeTransfer t
+ )
+
+{- Called right before a transfer begins, this is a last chance to avoid
+ - unnecessary transfers.
+ -
+ - For downloads, we obviously don't need to download if the already
+ - have the object.
+ -
+ - Smilarly, for uploads, check if the remote is known to already have
+ - the object.
+ -
+ - Also, uploads get queued to all remotes, in order of cost.
+ - This may mean, for example, that an object is uploaded over the LAN
+ - to a locally paired client, and once that upload is done, a more
+ - expensive transfer remote no longer wants the object. (Since
+ - all the clients have it already.) So do one last check if this is still
+ - preferred content.
+ -
+ - We'll also do one last preferred content check for downloads. An
+ - example of a case where this could be needed is if a download is queued
+ - for a file that gets moved out of an archive directory -- but before
+ - that download can happen, the file is put back in the archive.
+ -}
+shouldTransfer :: Transfer -> TransferInfo -> Annex Bool
+shouldTransfer t info
+ | transferDirection t == Download =
+ (not <$> inAnnex key) <&&> wantGet True file
+ | transferDirection t == Upload = case transferRemote info of
+ Nothing -> return False
+ Just r -> notinremote r
+ <&&> wantSend True file (Remote.uuid r)
+ | otherwise = return False
+ where
+ key = transferKey t
+ file = associatedFile info
+
+ {- Trust the location log to check if the remote already has
+ - the key. This avoids a roundtrip to the remote. -}
+ notinremote r = notElem (Remote.uuid r) <$> loggedLocations key
+
+{- Queue uploads of files downloaded to us, spreading them
+ - out to other reachable remotes.
+ -
+ - Downloading a file may have caused a remote to not want it;
+ - so check for drops from remotes.
+ -
+ - Uploading a file may cause the local repo, or some other remote to not
+ - want it; handle that too.
+ -}
+finishedTransfer :: Transfer -> Maybe TransferInfo -> Assistant ()
+finishedTransfer t (Just info)
+ | transferDirection t == Download =
+ whenM (liftAnnex $ inAnnex $ transferKey t) $ do
+ dodrops False
+ queueTransfersMatching (/= transferUUID t)
+ "newly received object"
+ Later (transferKey t) (associatedFile info) Upload
+ | otherwise = dodrops True
+ where
+ dodrops fromhere = handleDrops
+ ("drop wanted after " ++ describeTransfer t info)
+ fromhere (transferKey t) (associatedFile info) Nothing
+finishedTransfer _ _ = noop
+
+{- Pause a running transfer. -}
+pauseTransfer :: Transfer -> Assistant ()
+pauseTransfer = cancelTransfer True
+
+{- Cancel a running transfer. -}
+cancelTransfer :: Bool -> Transfer -> Assistant ()
+cancelTransfer pause t = do
+ m <- getCurrentTransfers
+ unless pause $
+ {- remove queued transfer -}
+ void $ dequeueTransfers $ equivilantTransfer t
+ {- stop running transfer -}
+ maybe noop stop (M.lookup t m)
+ where
+ stop info = do
+ {- When there's a thread associated with the
+ - transfer, it's signaled first, to avoid it
+ - displaying any alert about the transfer having
+ - failed when the transfer process is killed. -}
+ liftIO $ maybe noop signalthread $ transferTid info
+ liftIO $ maybe noop killproc $ transferPid info
+ if pause
+ then void $ alterTransferInfo t $
+ \i -> i { transferPaused = True }
+ else void $ removeTransfer t
+ signalthread tid
+ | pause = throwTo tid PauseTransfer
+ | otherwise = killThread tid
+ killproc pid = void $ tryIO $ do
+#ifndef mingw32_HOST_OS
+ {- In order to stop helper processes like rsync,
+ - kill the whole process group of the process
+ - running the transfer. -}
+ g <- getProcessGroupIDOf pid
+ void $ tryIO $ signalProcessGroup sigTERM g
+ threadDelay 50000 -- 0.05 second grace period
+ void $ tryIO $ signalProcessGroup sigKILL g
+#else
+ error "TODO: cancelTransfer not implemented on Windows"
+#endif
+
+{- Start or resume a transfer. -}
+startTransfer :: Transfer -> Assistant ()
+startTransfer t = do
+ m <- getCurrentTransfers
+ maybe startqueued go (M.lookup t m)
+ where
+ go info = maybe (start info) resume $ transferTid info
+ startqueued = do
+ is <- map snd <$> getMatchingTransfers (== t)
+ maybe noop start $ headMaybe is
+ resume tid = do
+ alterTransferInfo t $ \i -> i { transferPaused = False }
+ liftIO $ throwTo tid ResumeTransfer
+ start info = do
+ program <- liftIO readProgramFile
+ inImmediateTransferSlot program $
+ genTransfer t info
+
+getCurrentTransfers :: Assistant TransferMap
+getCurrentTransfers = currentTransfers <$> getDaemonStatus
diff --git a/Assistant/TransferrerPool.hs b/Assistant/TransferrerPool.hs
index d9104f74d..bb4648731 100644
--- a/Assistant/TransferrerPool.hs
+++ b/Assistant/TransferrerPool.hs
@@ -5,12 +5,17 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Assistant.TransferrerPool where
import Assistant.Common
import Assistant.Types.TransferrerPool
import Logs.Transfer
+
+#ifndef mingw32_HOST_OS
import qualified Command.TransferKeys as T
+#endif
import Control.Concurrent.STM
import System.Process (create_group)
@@ -38,13 +43,18 @@ withTransferrer program pool a = do
- finish. -}
performTransfer :: Transferrer -> Transfer -> AssociatedFile -> IO Bool
performTransfer transferrer t f = catchBoolIO $ do
+#ifndef mingw32_HOST_OS
T.sendRequest t f (transferrerWrite transferrer)
T.readResponse (transferrerRead transferrer)
+#else
+ error "TODO performTransfer not implemented on Windows"
+#endif
{- Starts a new git-annex transferkeys process, setting up a pipe
- that will be used to communicate with it. -}
mkTransferrer :: FilePath -> IO Transferrer
mkTransferrer program = do
+#ifndef mingw32_HOST_OS
(myread, twrite) <- createPipe
(tread, mywrite) <- createPipe
mapM_ (\fd -> setFdOption fd CloseOnExec True) [myread, mywrite]
@@ -68,6 +78,9 @@ mkTransferrer program = do
, transferrerWrite = mywriteh
, transferrerHandle = pid
}
+#else
+ error "TODO mkTransferrer not implemented on Windows"
+#endif
{- Checks if a Transferrer is still running. If not, makes a new one. -}
checkTransferrer :: FilePath -> Transferrer -> IO Transferrer
diff --git a/Assistant/Types/Alert.hs b/Assistant/Types/Alert.hs
index 290733b66..2e52ca7ef 100644
--- a/Assistant/Types/Alert.hs
+++ b/Assistant/Types/Alert.hs
@@ -30,6 +30,7 @@ data AlertName
| RemoteRemovalAlert String
| CloudRepoNeededAlert
| SyncAlert
+ | NotFsckedAlert
deriving (Eq)
{- The first alert is the new alert, the second is an old alert.
diff --git a/Assistant/Types/DaemonStatus.hs b/Assistant/Types/DaemonStatus.hs
index 17e535b6d..5d2f5bb37 100644
--- a/Assistant/Types/DaemonStatus.hs
+++ b/Assistant/Types/DaemonStatus.hs
@@ -5,8 +5,6 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE RankNTypes, ImpredicativeTypes #-}
-
module Assistant.Types.DaemonStatus where
import Common.Annex
@@ -18,6 +16,7 @@ import Assistant.Types.NetMessager
import Assistant.Types.Alert
import Control.Concurrent.STM
+import Control.Concurrent.MVar
import Control.Concurrent.Async
import Data.Time.Clock.POSIX
import qualified Data.Map as M
@@ -29,11 +28,13 @@ data DaemonStatus = DaemonStatus
{ startedThreads :: M.Map ThreadName (Async (), IO ())
-- False when the daemon is performing its startup scan
, scanComplete :: Bool
+ -- True when all files should be restaged.
+ , forceRestage :: Bool
-- Time when a previous process of the daemon was running ok
, lastRunning :: Maybe POSIXTime
- -- True when the sanity checker is running
+ -- True when the daily sanity checker is running
, sanityCheckRunning :: Bool
- -- Last time the sanity checker ran
+ -- Last time the daily sanity checker ran
, lastSanityCheck :: Maybe POSIXTime
-- True when a scan for file transfers is running
, transferScanRunning :: Bool
@@ -62,9 +63,15 @@ data DaemonStatus = DaemonStatus
, alertNotifier :: NotificationBroadcaster
-- Broadcasts notifications when the syncRemotes change
, syncRemotesNotifier :: NotificationBroadcaster
+ -- Broadcasts notifications when the scheduleLog changes
+ , scheduleLogNotifier :: NotificationBroadcaster
+ -- Broadcasts a notification once the startup sanity check has run.
+ , startupSanityCheckNotifier :: NotificationBroadcaster
-- When the XMPP client is connected, this will contain the XMPP
-- address.
, xmppClientID :: Maybe ClientID
+ -- MVars to signal when a remote gets connected.
+ , connectRemoteNotifiers :: M.Map UUID [MVar ()]
}
type TransferMap = M.Map Transfer TransferInfo
@@ -76,6 +83,7 @@ newDaemonStatus :: IO DaemonStatus
newDaemonStatus = DaemonStatus
<$> pure M.empty
<*> pure False
+ <*> pure False
<*> pure Nothing
<*> pure False
<*> pure Nothing
@@ -93,4 +101,7 @@ newDaemonStatus = DaemonStatus
<*> newNotificationBroadcaster
<*> newNotificationBroadcaster
<*> newNotificationBroadcaster
+ <*> newNotificationBroadcaster
+ <*> newNotificationBroadcaster
<*> pure Nothing
+ <*> pure M.empty
diff --git a/Assistant/Types/NamedThread.hs b/Assistant/Types/NamedThread.hs
index a65edc20d..5dd1364ad 100644
--- a/Assistant/Types/NamedThread.hs
+++ b/Assistant/Types/NamedThread.hs
@@ -11,7 +11,11 @@ import Assistant.Monad
import Assistant.Types.ThreadName
{- Information about a named thread that can be run. -}
-data NamedThread = NamedThread ThreadName (Assistant ())
+data NamedThread = NamedThread Bool ThreadName (Assistant ())
namedThread :: String -> Assistant () -> NamedThread
-namedThread = NamedThread . ThreadName
+namedThread = NamedThread True . ThreadName
+
+{- A named thread that can start running before the startup sanity check. -}
+namedThreadUnchecked :: String -> Assistant () -> NamedThread
+namedThreadUnchecked = NamedThread False . ThreadName
diff --git a/Assistant/Types/RepoProblem.hs b/Assistant/Types/RepoProblem.hs
new file mode 100644
index 000000000..ece5a5286
--- /dev/null
+++ b/Assistant/Types/RepoProblem.hs
@@ -0,0 +1,28 @@
+{- git-annex assistant repository problem tracking
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Assistant.Types.RepoProblem where
+
+import Types
+import Utility.TList
+
+import Control.Concurrent.STM
+import Data.Function
+
+data RepoProblem = RepoProblem
+ { problemUUID :: UUID
+ , afterFix :: IO ()
+ }
+
+{- The afterFix actions are assumed to all be equivilant. -}
+sameRepoProblem :: RepoProblem -> RepoProblem -> Bool
+sameRepoProblem = (==) `on` problemUUID
+
+type RepoProblemChan = TList RepoProblem
+
+newRepoProblemChan :: IO RepoProblemChan
+newRepoProblemChan = atomically newTList
diff --git a/Assistant/XMPP.hs b/Assistant/XMPP.hs
index 0360ce860..09b7daf4e 100644
--- a/Assistant/XMPP.hs
+++ b/Assistant/XMPP.hs
@@ -21,7 +21,7 @@ import qualified Data.Map as M
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.XML.Types
-import qualified Codec.Binary.Base64 as B64
+import qualified "dataenc" Codec.Binary.Base64 as B64
{- Name of the git-annex tag, in our own XML namespace.
- (Not using a namespace URL to avoid unnecessary bloat.) -}
diff --git a/Backend.hs b/Backend.hs
index 2ee14acc6..38314687a 100644
--- a/Backend.hs
+++ b/Backend.hs
@@ -27,12 +27,12 @@ import qualified Types.Backend as B
import Config
-- When adding a new backend, import it here and add it to the list.
-import qualified Backend.SHA
+import qualified Backend.Hash
import qualified Backend.WORM
import qualified Backend.URL
list :: [Backend]
-list = Backend.SHA.backends ++ Backend.WORM.backends ++ Backend.URL.backends
+list = Backend.Hash.backends ++ Backend.WORM.backends ++ Backend.URL.backends
{- List of backends in the order to try them when storing a new key. -}
orderedList :: Annex [Backend]
diff --git a/Backend/Hash.hs b/Backend/Hash.hs
new file mode 100644
index 000000000..96a9bab3c
--- /dev/null
+++ b/Backend/Hash.hs
@@ -0,0 +1,168 @@
+{- git-annex hashing backends
+ -
+ - Copyright 2011-2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Backend.Hash (backends) where
+
+import Common.Annex
+import qualified Annex
+import Types.Backend
+import Types.Key
+import Types.KeySource
+import Utility.Hash
+import Utility.ExternalSHA
+
+import qualified Build.SysConfig as SysConfig
+import qualified Data.ByteString.Lazy as L
+import Data.Char
+
+data Hash = SHAHash HashSize | SkeinHash HashSize
+type HashSize = Int
+
+{- Order is slightly significant; want SHA256 first, and more general
+ - sizes earlier. -}
+hashes :: [Hash]
+hashes = concat
+ [ map SHAHash [256, 1, 512, 224, 384]
+#ifdef WITH_CRYPTOHASH
+ , map SkeinHash [256, 512]
+#endif
+ ]
+
+{- The SHA256E backend is the default, so genBackendE comes first. -}
+backends :: [Backend]
+backends = catMaybes $ map genBackendE hashes ++ map genBackend hashes
+
+genBackend :: Hash -> Maybe Backend
+genBackend hash = Just Backend
+ { name = hashName hash
+ , getKey = keyValue hash
+ , fsckKey = Just $ checkKeyChecksum hash
+ , canUpgradeKey = Just needsUpgrade
+ }
+
+genBackendE :: Hash -> Maybe Backend
+genBackendE hash = do
+ b <- genBackend hash
+ return $ b
+ { name = hashNameE hash
+ , getKey = keyValueE hash
+ }
+
+hashName :: Hash -> String
+hashName (SHAHash size) = "SHA" ++ show size
+hashName (SkeinHash size) = "SKEIN" ++ show size
+
+hashNameE :: Hash -> String
+hashNameE hash = hashName hash ++ "E"
+
+{- A key is a hash of its contents. -}
+keyValue :: Hash -> KeySource -> Annex (Maybe Key)
+keyValue hash source = do
+ let file = contentLocation source
+ stat <- liftIO $ getFileStatus file
+ let filesize = fromIntegral $ fileSize stat
+ s <- hashFile hash file filesize
+ return $ Just $ stubKey
+ { keyName = s
+ , keyBackendName = hashName hash
+ , keySize = Just filesize
+ }
+
+{- Extension preserving keys. -}
+keyValueE :: Hash -> KeySource -> Annex (Maybe Key)
+keyValueE hash source = keyValue hash source >>= maybe (return Nothing) addE
+ where
+ addE k = return $ Just $ k
+ { keyName = keyName k ++ selectExtension (keyFilename source)
+ , keyBackendName = hashNameE hash
+ }
+
+selectExtension :: FilePath -> String
+selectExtension f
+ | null es = ""
+ | otherwise = intercalate "." ("":es)
+ where
+ es = filter (not . null) $ reverse $
+ take 2 $ takeWhile shortenough $
+ reverse $ split "." $ filter validExtension $ takeExtensions f
+ shortenough e = length e <= 4 -- long enough for "jpeg"
+
+{- A key's checksum is checked during fsck. -}
+checkKeyChecksum :: Hash -> Key -> FilePath -> Annex Bool
+checkKeyChecksum hash key file = do
+ fast <- Annex.getState Annex.fast
+ mstat <- liftIO $ catchMaybeIO $ getFileStatus file
+ case (mstat, fast) of
+ (Just stat, False) -> do
+ let filesize = fromIntegral $ fileSize stat
+ check <$> hashFile hash file filesize
+ _ -> return True
+ where
+ expected = keyHash key
+ check s
+ | s == expected = True
+ {- A bug caused checksums to be prefixed with \ in some
+ - cases; still accept these as legal now that the bug has been
+ - fixed. -}
+ | '\\' : s == expected = True
+ | otherwise = False
+
+keyHash :: Key -> String
+keyHash key = dropExtensions (keyName key)
+
+validExtension :: Char -> Bool
+validExtension c
+ | isAlphaNum c = True
+ | c == '.' = True
+ | otherwise = False
+
+{- Upgrade keys that have the \ prefix on their sha due to a bug, or
+ - that contain non-alphanumeric characters in their extension. -}
+needsUpgrade :: Key -> Bool
+needsUpgrade key = "\\" `isPrefixOf` keyHash key ||
+ any (not . validExtension) (takeExtensions $ keyName key)
+
+hashFile :: Hash -> FilePath -> Integer -> Annex String
+hashFile hash file filesize = do
+ showAction "checksum"
+ liftIO $ go hash
+ where
+ go (SHAHash hashsize) = case shaHasher hashsize filesize of
+ Left sha -> sha <$> L.readFile file
+ Right command ->
+ either error return
+ =<< externalSHA command hashsize file
+ go (SkeinHash hashsize) = skeinHasher hashsize <$> L.readFile file
+
+shaHasher :: HashSize -> Integer -> Either (L.ByteString -> String) String
+shaHasher hashsize filesize
+ | hashsize == 1 = use SysConfig.sha1 sha1
+ | hashsize == 256 = use SysConfig.sha256 sha256
+ | hashsize == 224 = use SysConfig.sha224 sha224
+ | hashsize == 384 = use SysConfig.sha384 sha384
+ | hashsize == 512 = use SysConfig.sha512 sha512
+ | otherwise = error $ "unsupported sha size " ++ show hashsize
+ where
+ use Nothing hasher = Left $ show . hasher
+ use (Just c) hasher
+ {- Use builtin, but slightly slower hashing for
+ - smallish files. Cryptohash benchmarks 90 to 101%
+ - faster than external hashers, depending on the hash
+ - and system. So there is no point forking an external
+ - process unless the file is large. -}
+ | filesize < 1048576 = use Nothing hasher
+ | otherwise = Right c
+
+skeinHasher :: HashSize -> (L.ByteString -> String)
+skeinHasher hashsize
+#ifdef WITH_CRYPTOHASH
+ | hashsize == 256 = show . skein256
+ | hashsize == 512 = show . skein512
+#endif
+ | otherwise = error $ "unsupported skein size " ++ show hashsize
diff --git a/Backend/SHA.hs b/Backend/SHA.hs
deleted file mode 100644
index a735ce1e5..000000000
--- a/Backend/SHA.hs
+++ /dev/null
@@ -1,146 +0,0 @@
-{- git-annex SHA backends
- -
- - Copyright 2011,2012 Joey Hess <joey@kitenet.net>
- -
- - Licensed under the GNU GPL version 3 or higher.
- -}
-
-module Backend.SHA (backends) where
-
-import Common.Annex
-import qualified Annex
-import Types.Backend
-import Types.Key
-import Types.KeySource
-import Utility.ExternalSHA
-
-import qualified Build.SysConfig as SysConfig
-import Data.Digest.Pure.SHA
-import qualified Data.ByteString.Lazy as L
-import Data.Char
-
-type SHASize = Int
-
-{- Order is slightly significant; want SHA256 first, and more general
- - sizes earlier. -}
-sizes :: [Int]
-sizes = [256, 1, 512, 224, 384]
-
-{- The SHA256E backend is the default. -}
-backends :: [Backend]
-backends = catMaybes $ map genBackendE sizes ++ map genBackend sizes
-
-genBackend :: SHASize -> Maybe Backend
-genBackend size = Just $ Backend
- { name = shaName size
- , getKey = keyValue size
- , fsckKey = Just $ checkKeyChecksum size
- , canUpgradeKey = Just $ needsUpgrade
- }
-
-genBackendE :: SHASize -> Maybe Backend
-genBackendE size = do
- b <- genBackend size
- return $ b
- { name = shaNameE size
- , getKey = keyValueE size
- }
-
-shaName :: SHASize -> String
-shaName size = "SHA" ++ show size
-
-shaNameE :: SHASize -> String
-shaNameE size = shaName size ++ "E"
-
-shaN :: SHASize -> FilePath -> Integer -> Annex String
-shaN shasize file filesize = do
- showAction "checksum"
- liftIO $ case shaCommand shasize filesize of
- Left sha -> sha <$> L.readFile file
- Right command ->
- either error return
- =<< externalSHA command shasize file
-
-shaCommand :: SHASize -> Integer -> Either (L.ByteString -> String) String
-shaCommand shasize filesize
- | shasize == 1 = use SysConfig.sha1 sha1
- | shasize == 256 = use SysConfig.sha256 sha256
- | shasize == 224 = use SysConfig.sha224 sha224
- | shasize == 384 = use SysConfig.sha384 sha384
- | shasize == 512 = use SysConfig.sha512 sha512
- | otherwise = error $ "bad sha size " ++ show shasize
- where
- use Nothing sha = Left $ showDigest . sha
- use (Just c) sha
- {- use builtin, but slower sha for small files
- - benchmarking indicates it's faster up to
- - and slightly beyond 50 kb files -}
- | filesize < 51200 = use Nothing sha
- | otherwise = Right c
-
-{- A key is a checksum of its contents. -}
-keyValue :: SHASize -> KeySource -> Annex (Maybe Key)
-keyValue shasize source = do
- let file = contentLocation source
- stat <- liftIO $ getFileStatus file
- let filesize = fromIntegral $ fileSize stat
- s <- shaN shasize file filesize
- return $ Just $ stubKey
- { keyName = s
- , keyBackendName = shaName shasize
- , keySize = Just filesize
- }
-
-{- Extension preserving keys. -}
-keyValueE :: SHASize -> KeySource -> Annex (Maybe Key)
-keyValueE size source = keyValue size source >>= maybe (return Nothing) addE
- where
- addE k = return $ Just $ k
- { keyName = keyName k ++ selectExtension (keyFilename source)
- , keyBackendName = shaNameE size
- }
-
-selectExtension :: FilePath -> String
-selectExtension f
- | null es = ""
- | otherwise = intercalate "." ("":es)
- where
- es = filter (not . null) $ reverse $
- take 2 $ takeWhile shortenough $
- reverse $ split "." $ filter validExtension $ takeExtensions f
- shortenough e = length e <= 4 -- long enough for "jpeg"
-
-{- A key's checksum is checked during fsck. -}
-checkKeyChecksum :: SHASize -> Key -> FilePath -> Annex Bool
-checkKeyChecksum size key file = do
- fast <- Annex.getState Annex.fast
- mstat <- liftIO $ catchMaybeIO $ getFileStatus file
- case (mstat, fast) of
- (Just stat, False) -> do
- let filesize = fromIntegral $ fileSize stat
- check <$> shaN size file filesize
- _ -> return True
- where
- sha = keySha key
- check s
- | s == sha = True
- {- A bug caused checksums to be prefixed with \ in some
- - cases; still accept these as legal now that the bug has been
- - fixed. -}
- | '\\' : s == sha = True
- | otherwise = False
-
-keySha :: Key -> String
-keySha key = dropExtensions (keyName key)
-
-validExtension :: Char -> Bool
-validExtension c
- | isAlphaNum c = True
- | c == '.' = True
- | otherwise = False
-
-{- Upgrade keys that have the \ prefix on their sha due to a bug, or
- - that contain non-alphanumeric characters in their extension. -}
-needsUpgrade :: Key -> Bool
-needsUpgrade key = "\\" `isPrefixOf` keySha key ||
- any (not . validExtension) (takeExtensions $ keyName key)
diff --git a/Backend/URL.hs b/Backend/URL.hs
index ace578a24..a8161c98d 100644
--- a/Backend/URL.hs
+++ b/Backend/URL.hs
@@ -10,11 +10,10 @@ module Backend.URL (
fromUrl
) where
-import Data.Hash.MD5
-
import Common.Annex
import Types.Backend
import Types.Key
+import Backend.Utilities
backends :: [Backend]
backends = [backend]
@@ -27,18 +26,12 @@ backend = Backend
, canUpgradeKey = Nothing
}
-{- When it's not too long, use the full url as the key name.
- - If the url is too long, it's truncated at half the filename length
- - limit, and the md5 of the url is prepended to ensure a unique key. -}
+{- Every unique url has a corresponding key. -}
fromUrl :: String -> Maybe Integer -> Annex Key
fromUrl url size = do
- limit <- liftIO . fileNameLengthLimit =<< fromRepo gitAnnexDir
- let truncurl = truncateFilePath (limit `div` 2) url
- let key = if url == truncurl
- then url
- else truncurl ++ "-" ++ md5s (Str url)
+ n <- genKeyName url
return $ stubKey
- { keyName = key
+ { keyName = n
, keyBackendName = "URL"
, keySize = size
- }
+ }
diff --git a/Backend/Utilities.hs b/Backend/Utilities.hs
new file mode 100644
index 000000000..24dbfd6d9
--- /dev/null
+++ b/Backend/Utilities.hs
@@ -0,0 +1,25 @@
+{- git-annex backend utilities
+ -
+ - Copyright 2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Backend.Utilities where
+
+import Data.Hash.MD5
+
+import Common.Annex
+
+{- Generates a keyName from an input string. Takes care of sanitizing it.
+ - If it's not too long, the full string is used as the keyName.
+ - Otherwise, it's truncated at half the filename length limit, and its
+ - md5 is prepended to ensure a unique key. -}
+genKeyName :: String -> Annex String
+genKeyName s = do
+ limit <- liftIO . fileNameLengthLimit =<< fromRepo gitAnnexDir
+ let s' = preSanitizeKeyName s
+ let truncs = truncateFilePath (limit `div` 2) s'
+ return $ if s' == truncs
+ then s'
+ else truncs ++ "-" ++ md5s (Str s)
diff --git a/Backend/WORM.hs b/Backend/WORM.hs
index 3471eedc1..60db42f56 100644
--- a/Backend/WORM.hs
+++ b/Backend/WORM.hs
@@ -11,6 +11,7 @@ import Common.Annex
import Types.Backend
import Types.Key
import Types.KeySource
+import Backend.Utilities
backends :: [Backend]
backends = [backend]
@@ -33,9 +34,10 @@ backend = Backend
keyValue :: KeySource -> Annex (Maybe Key)
keyValue source = do
stat <- liftIO $ getFileStatus $ contentLocation source
- return $ Just Key {
- keyName = takeFileName $ keyFilename source,
- keyBackendName = name backend,
- keySize = Just $ fromIntegral $ fileSize stat,
- keyMtime = Just $ modificationTime stat
- }
+ n <- genKeyName $ keyFilename source
+ return $ Just Key
+ { keyName = n
+ , keyBackendName = name backend
+ , keySize = Just $ fromIntegral $ fileSize stat
+ , keyMtime = Just $ modificationTime stat
+ }
diff --git a/Build/BundledPrograms.hs b/Build/BundledPrograms.hs
index 9a50778d4..87232ebec 100644
--- a/Build/BundledPrograms.hs
+++ b/Build/BundledPrograms.hs
@@ -24,9 +24,13 @@ bundledPrograms = catMaybes
, Just "git"
#endif
, Just "cp"
+#ifndef mingw32_HOST_OS
+ -- using xargs on windows led to problems, so it's not used there
, Just "xargs"
+#endif
, Just "rsync"
, Just "ssh"
+ , Just "ssh-keygen"
#ifndef mingw32_HOST_OS
, Just "sh"
#endif
@@ -35,13 +39,14 @@ bundledPrograms = catMaybes
, ifset SysConfig.wget "wget"
, ifset SysConfig.bup "bup"
, SysConfig.lsof
+ , SysConfig.gcrypt
, SysConfig.sha1
, SysConfig.sha256
, SysConfig.sha512
, SysConfig.sha224
, SysConfig.sha384
- -- ionice is not included in the bundle; we rely on the system's
- -- own version, which may better match its kernel
+ -- nice and ionice are not included in the bundle; we rely on the
+ -- system's own version, which may better match its kernel
]
where
ifset True s = Just s
diff --git a/Build/Configure.hs b/Build/Configure.hs
index 15b90ebe3..262ac2080 100644
--- a/Build/Configure.hs
+++ b/Build/Configure.hs
@@ -13,9 +13,9 @@ import Control.Monad.IfElse
import Data.Char
import Build.TestConfig
+import Build.Version
import Utility.SafeCommand
import Utility.Monad
-import Utility.Exception
import Utility.ExternalSHA
import qualified Git.Version
@@ -32,11 +32,14 @@ tests =
, TestCase "curl" $ testCmd "curl" "curl --version >/dev/null"
, TestCase "wget" $ testCmd "wget" "wget --version >/dev/null"
, TestCase "bup" $ testCmd "bup" "bup --version >/dev/null"
+ , TestCase "quvi" $ testCmd "quvi" "quvi --version >/dev/null"
+ , TestCase "nice" $ testCmd "nice" "nice true >/dev/null"
, TestCase "ionice" $ testCmd "ionice" "ionice -c3 true >/dev/null"
, TestCase "gpg" $ maybeSelectCmd "gpg"
[ ("gpg", "--version >/dev/null")
, ("gpg2", "--version >/dev/null") ]
, TestCase "lsof" $ findCmdPath "lsof" "lsof"
+ , TestCase "git-remote-gcrypt" $ findCmdPath "gcrypt" "git-remote-gcrypt"
, TestCase "ssh connection caching" getSshConnectionCaching
] ++ shaTestCases
[ (1, "da39a3ee5e6b4b0d3255bfef95601890afd80709")
@@ -87,40 +90,6 @@ testCp k option = TestCase cmd $ testCmd k cmdline
cmd = "cp " ++ option
cmdline = cmd ++ " " ++ testFile ++ " " ++ testFile ++ ".new"
-isReleaseBuild :: IO Bool
-isReleaseBuild = isJust <$> catchMaybeIO (getEnv "RELEASE_BUILD")
-
-{- Version is usually based on the major version from the changelog,
- - plus the date of the last commit, plus the git rev of that commit.
- - This works for autobuilds, ad-hoc builds, etc.
- -
- - If git or a git repo is not available, or something goes wrong,
- - or this is a release build, just use the version from the changelog. -}
-getVersion :: Test
-getVersion = do
- changelogversion <- getChangelogVersion
- version <- ifM (isReleaseBuild)
- ( return changelogversion
- , catchDefaultIO changelogversion $ do
- let major = takeWhile (/= '.') changelogversion
- autoversion <- readProcess "sh"
- [ "-c"
- , "git log -n 1 --format=format:'%ci %h'| sed -e 's/-//g' -e 's/ .* /-g/'"
- ] ""
- if null autoversion
- then return changelogversion
- else return $ concat [ major, ".", autoversion ]
- )
- return $ Config "packageversion" (StringConfig version)
-
-getChangelogVersion :: IO String
-getChangelogVersion = do
- changelog <- readFile "debian/changelog"
- let verline = takeWhile (/= '\n') changelog
- return $ middle (words verline !! 1)
- where
- middle = drop 1 . init
-
getGitVersion :: Test
getGitVersion = Config "gitversion" . StringConfig . show
<$> Git.Version.installed
@@ -129,25 +98,6 @@ getSshConnectionCaching :: Test
getSshConnectionCaching = Config "sshconnectioncaching" . BoolConfig <$>
boolSystem "sh" [Param "-c", Param "ssh -o ControlPersist=yes -V >/dev/null 2>/dev/null"]
-{- Set up cabal file with version. -}
-cabalSetup :: IO ()
-cabalSetup = do
- version <- takeWhile (\c -> isDigit c || c == '.')
- <$> getChangelogVersion
- cabal <- readFile cabalfile
- writeFile tmpcabalfile $ unlines $
- map (setfield "Version" version) $
- lines cabal
- renameFile tmpcabalfile cabalfile
- where
- cabalfile = "git-annex.cabal"
- tmpcabalfile = cabalfile++".tmp"
- setfield field value s
- | fullfield `isPrefixOf` s = fullfield ++ value
- | otherwise = s
- where
- fullfield = field ++ ": "
-
setup :: IO ()
setup = do
createDirectoryIfMissing True tmpDir
@@ -165,8 +115,8 @@ run ts = do
then writeSysConfig $ androidConfig config
else writeSysConfig config
cleanup
- whenM (isReleaseBuild) $
- cabalSetup
+ whenM isReleaseBuild $
+ cabalSetup "git-annex.cabal"
{- Hard codes some settings to cross-compile for Android. -}
androidConfig :: [Config] -> [Config]
diff --git a/Build/EvilSplicer.hs b/Build/EvilSplicer.hs
index 8f203437a..35dba4968 100644
--- a/Build/EvilSplicer.hs
+++ b/Build/EvilSplicer.hs
@@ -294,6 +294,8 @@ expandExpressionSplice s lls = concat [before, spliced:padding, end]
{- Tweaks code output by GHC in splices to actually build. Yipes. -}
mangleCode :: String -> String
mangleCode = flip_colon
+ . remove_unnecessary_type_signatures
+ . lambdaparenhack
. lambdaparens
. declaration_parens
. case_layout
@@ -331,6 +333,12 @@ mangleCode = flip_colon
preindent <- many1 $ oneOf " \n"
string "\\ "
lambdaparams <- restofline
+ continuedlambdaparams <- many $ try $ do
+ indent <- many1 $ char ' '
+ p <- satisfy isLetter
+ aram <- many $ satisfy isAlphaNum <|> oneOf "_"
+ newline
+ return $ indent ++ p:aram ++ "\n"
indent <- many1 $ char ' '
string "-> "
firstline <- restofline
@@ -342,10 +350,46 @@ mangleCode = flip_colon
return $ concat
[ prefix:preindent
, "(\\ " ++ lambdaparams ++ "\n"
+ , concat continuedlambdaparams
, indent ++ "-> "
, lambdaparens $ intercalate "\n" (firstline:lambdalines)
, ")\n"
]
+
+ {- Hack to add missing parens in a specific case in yesod
+ - static route code.
+ -
+ - StaticR
+ - yesod_dispatch_env_a4iDV
+ - (\ p_a4iE2 r_a4iE3
+ - -> r_a4iE3 {Network.Wai.pathInfo = p_a4iE2}
+ - xrest_a4iDT req_a4iDW)) }
+ -
+ - Need to add another paren around the lambda, and close it
+ - before its parameters. lambdaparens misses this one because
+ - there is already one paren present.
+ -
+ - FIXME: This is a hack. lambdaparens could just always add a
+ - layer of parens even when a lambda seems to be in parent.
+ -}
+ lambdaparenhack = parsecAndReplace $ do
+ indent <- many1 $ char ' '
+ staticr <- string "StaticR"
+ newline
+ string indent
+ yesod_dispatch_env <- restofline
+ string indent
+ lambdaprefix <- string "(\\ "
+ l1 <- restofline
+ string indent
+ lambdaarrow <- string " ->"
+ l2 <- restofline
+ return $ unlines
+ [ indent ++ staticr
+ , indent ++ yesod_dispatch_env
+ , indent ++ "(" ++ lambdaprefix ++ l1
+ , indent ++ lambdaarrow ++ l2 ++ ")"
+ ]
restofline = manyTill (noneOf "\n") newline
@@ -439,6 +483,19 @@ mangleCode = flip_colon
- declarations. -}
declaration_parens = replace "StaticR Route Static" "StaticR (Route Static)"
+ {- A type signature is sometimes given for an entire lambda,
+ - which is not properly parenthesized or laid out. This is a
+ - hack to remove one specific case where this happens and the
+ - signature is easily inferred, so is just removed.
+ -}
+ remove_unnecessary_type_signatures = parsecAndReplace $ do
+ string " ::"
+ newline
+ many1 $ char ' '
+ string "Text.Css.Block Text.Css.Resolved"
+ newline
+ return ""
+
{- GHC may add full package and version qualifications for
- symbols from unimported modules. We don't want these.
-
@@ -527,7 +584,7 @@ text_builder_hack = replace "Data.Text.Lazy.Builder.Internal.fromText" "Data.Tex
parsecAndReplace :: Parser String -> String -> String
parsecAndReplace p s = case parse find "" s of
Left e -> s
- Right l -> concatMap (either (\c -> [c]) id) l
+ Right l -> concatMap (either return id) l
where
find :: Parser [Either Char String]
find = many $ try (Right <$> p) <|> (Left <$> anyChar)
diff --git a/Build/OSXMkLibs.hs b/Build/OSXMkLibs.hs
index ed12a945f..dae9bc0ae 100644
--- a/Build/OSXMkLibs.hs
+++ b/Build/OSXMkLibs.hs
@@ -144,7 +144,7 @@ getLibName lib libmap = case M.lookup lib libmap of
Just n -> (n, libmap)
Nothing -> (nextfreename, M.insert lib nextfreename libmap)
where
- names = map (\c -> [c]) ['A' .. 'Z'] ++
+ names = map pure ['A' .. 'Z'] ++
[[n, l] | n <- ['0' .. '9'], l <- ['A' .. 'Z']]
used = S.fromList $ M.elems libmap
nextfreename = fromMaybe (error "ran out of short library names!") $
diff --git a/Build/Version.hs b/Build/Version.hs
new file mode 100644
index 000000000..7ff2fe662
--- /dev/null
+++ b/Build/Version.hs
@@ -0,0 +1,69 @@
+{- Package version determination, for configure script. -}
+
+module Build.Version where
+
+import Data.Maybe
+import Control.Applicative
+import Data.List
+import System.Environment
+import System.Directory
+import Data.Char
+import System.Process
+
+import Build.TestConfig
+import Utility.Monad
+import Utility.Exception
+
+{- Set when making an official release. (Distribution vendors should set
+ - this too.) -}
+isReleaseBuild :: IO Bool
+isReleaseBuild = isJust <$> catchMaybeIO (getEnv "RELEASE_BUILD")
+
+{- Version is usually based on the major version from the changelog,
+ - plus the date of the last commit, plus the git rev of that commit.
+ - This works for autobuilds, ad-hoc builds, etc.
+ -
+ - If git or a git repo is not available, or something goes wrong,
+ - or this is a release build, just use the version from the changelog. -}
+getVersion :: Test
+getVersion = do
+ changelogversion <- getChangelogVersion
+ version <- ifM (isReleaseBuild)
+ ( return changelogversion
+ , catchDefaultIO changelogversion $ do
+ let major = takeWhile (/= '.') changelogversion
+ autoversion <- takeWhile (\c -> isAlphaNum c || c == '-') <$> readProcess "sh"
+ [ "-c"
+ , "git log -n 1 --format=format:'%ci %h'| sed -e 's/-//g' -e 's/ .* /-g/'"
+ ] ""
+ if null autoversion
+ then return changelogversion
+ else return $ concat [ major, ".", autoversion ]
+ )
+ return $ Config "packageversion" (StringConfig version)
+
+getChangelogVersion :: IO String
+getChangelogVersion = do
+ changelog <- readFile "debian/changelog"
+ let verline = takeWhile (/= '\n') changelog
+ return $ middle (words verline !! 1)
+ where
+ middle = drop 1 . init
+
+{- Set up cabal file with version. -}
+cabalSetup :: FilePath -> IO ()
+cabalSetup cabalfile = do
+ version <- takeWhile (\c -> isDigit c || c == '.')
+ <$> getChangelogVersion
+ cabal <- readFile cabalfile
+ writeFile tmpcabalfile $ unlines $
+ map (setfield "Version" version) $
+ lines cabal
+ renameFile tmpcabalfile cabalfile
+ where
+ tmpcabalfile = cabalfile++".tmp"
+ setfield field value s
+ | fullfield `isPrefixOf` s = fullfield ++ value
+ | otherwise = s
+ where
+ fullfield = field ++ ": "
diff --git a/Build/mdwn2man b/Build/mdwn2man
index ba5919b38..aadb13cdf 100755
--- a/Build/mdwn2man
+++ b/Build/mdwn2man
@@ -8,6 +8,7 @@ print ".TH $prog $section\n";
while (<>) {
s{(\\?)\[\[([^\s\|\]]+)(\|[^\s\]]+)?\]\]}{$1 ? "[[$2]]" : $2}eg;
+ s/\`([^\`]*)\`/\\fB$1\\fP/g;
s/\`//g;
s/^\s*\./\\&./g;
if (/^#\s/) {
@@ -25,7 +26,7 @@ while (<>) {
$inlist=1;
$spippara=0;
}
- elsif (/.SH/) {
+ elsif (/^.SH/) {
$skippara=0;
$inlist=0;
}
diff --git a/BuildFlags.hs b/BuildFlags.hs
index f37782c97..1dba47eaf 100644
--- a/BuildFlags.hs
+++ b/BuildFlags.hs
@@ -48,4 +48,19 @@ buildFlags = filter (not . null)
#ifdef WITH_DNS
, "DNS"
#endif
+#ifdef WITH_FEED
+ , "Feeds"
+#endif
+#ifdef WITH_QUVI
+ , "Quvi"
+#endif
+#ifdef WITH_TDFA
+ , "TDFA"
+#endif
+#ifdef WITH_CRYPTOHASH
+ , "CryptoHash"
+#endif
+#ifdef WITH_EKG
+ , "EKG"
+#endif
]
diff --git a/Command.hs b/Command.hs
index fec733f72..2c157304f 100644
--- a/Command.hs
+++ b/Command.hs
@@ -111,7 +111,7 @@ numCopies file = do
Just n -> return $ Just n
Nothing -> readish <$> checkAttr "annex.numcopies" file
-numCopiesCheck :: FilePath -> Key -> (Int -> Int -> Bool) -> Annex Bool
+numCopiesCheck :: FilePath -> Key -> (Int -> Int -> v) -> Annex v
numCopiesCheck file key vs = do
numcopiesattr <- numCopies file
needed <- getNumCopies numcopiesattr
diff --git a/Command/Add.hs b/Command/Add.hs
index 245ca2bd6..9f1beb28a 100644
--- a/Command/Add.hs
+++ b/Command/Add.hs
@@ -23,10 +23,11 @@ import Annex.Perms
import Annex.Link
import qualified Annex
import qualified Annex.Queue
+#ifdef WITH_CLIBS
#ifndef __ANDROID__
import Utility.Touch
#endif
-import Utility.FileMode
+#endif
import Config
import Utility.InodeCache
import Annex.FileMatcher
@@ -77,7 +78,7 @@ start file = ifAnnexed file addpresent add
-- is present but not yet added to git
showStart "add" file
liftIO $ removeFile file
- next $ next $ cleanup file key =<< inAnnex key
+ next $ next $ cleanup file key Nothing =<< inAnnex key
{- The file that's being added is locked down before a key is generated,
- to prevent it from being modified in between. This lock down is not
@@ -86,11 +87,6 @@ start file = ifAnnexed file addpresent add
- So a KeySource is returned. Its inodeCache can be used to detect any
- changes that might be made to the file after it was locked down.
-
- - In indirect mode, the write bit is removed from the file as part of lock
- - down to guard against further writes, and because objects in the annex
- - have their write bit disabled anyway. This is not done in direct mode,
- - because files there need to remain writable at all times.
- -
- When possible, the file is hard linked to a temp directory. This guards
- against some changes, like deletion or overwrite of the file, and
- allows lsof checks to be done more efficiently when adding a lot of files.
@@ -98,24 +94,36 @@ 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)
+lockDown file = ifM crippledFileSystem
( liftIO $ catchMaybeIO nohardlink
, do
tmp <- fromRepo gitAnnexTmpDir
createAnnexDirectory tmp
- unlessM (isDirect) $ liftIO $
- void $ tryIO $ preventWrite file
- liftIO $ catchMaybeIO $ do
+ eitherToMaybe <$> tryAnnexIO (go tmp)
+ )
+ where
+ {- In indirect mode, the write bit is removed from the file as part
+ - of lock down to guard against further writes, and because objects
+ - in the annex have their write bit disabled anyway.
+ -
+ - Freezing the content early also lets us fail early when
+ - someone else owns the file.
+ -
+ - This is not done in direct mode, because files there need to
+ - remain writable at all times.
+ -}
+ go tmp = do
+ unlessM isDirect $
+ freezeContent file
+ liftIO $ do
(tmpfile, h) <- openTempFile tmp $
relatedTemplate $ takeFileName file
hClose h
nukeFile tmpfile
withhardlink tmpfile `catchIO` const nohardlink
- )
- where
nohardlink = do
cache <- genInodeCache file
- return $ KeySource
+ return KeySource
{ keyFilename = file
, contentLocation = file
, inodeCache = cache
@@ -123,7 +131,7 @@ lockDown file = ifM (crippledFileSystem)
withhardlink tmpfile = do
createLink file tmpfile
cache <- genInodeCache tmpfile
- return $ KeySource
+ return KeySource
{ keyFilename = file
, contentLocation = tmpfile
, inodeCache = cache
@@ -134,8 +142,8 @@ lockDown file = ifM (crippledFileSystem)
- In direct mode, leaves the file alone, and just updates bookkeeping
- information.
-}
-ingest :: (Maybe KeySource) -> Annex (Maybe Key)
-ingest Nothing = return Nothing
+ingest :: Maybe KeySource -> Annex (Maybe Key, Maybe InodeCache)
+ingest Nothing = return (Nothing, Nothing)
ingest (Just source) = do
backend <- chooseBackend $ keyFilename source
k <- genKey source backend
@@ -147,24 +155,24 @@ ingest (Just source) = do
where
go k cache = ifM isDirect ( godirect k cache , goindirect k cache )
- goindirect (Just (key, _)) _ = do
+ goindirect (Just (key, _)) mcache = do
catchAnnex (moveAnnex key $ contentLocation source)
(undo (keyFilename source) key)
liftIO $ nukeFile $ keyFilename source
- return $ Just key
+ return $ (Just key, mcache)
goindirect Nothing _ = failure "failed to generate a key"
godirect (Just (key, _)) (Just cache) = do
addInodeCache key cache
finishIngestDirect key source
- return $ Just key
+ return $ (Just key, Just cache)
godirect _ _ = failure "failed to generate a key"
failure msg = do
warning $ keyFilename source ++ " " ++ msg
when (contentLocation source /= keyFilename source) $
liftIO $ nukeFile $ contentLocation source
- return Nothing
+ return (Nothing, Nothing)
finishIngestDirect :: Key -> KeySource -> Annex ()
finishIngestDirect key source = do
@@ -178,9 +186,10 @@ finishIngestDirect key source = do
addContentWhenNotPresent key (keyFilename source)
perform :: FilePath -> CommandPerform
-perform file =
- maybe stop (\key -> next $ cleanup file key True)
- =<< ingest =<< lockDown file
+perform file = lockDown file >>= ingest >>= go
+ where
+ go (Just key, cache) = next $ cleanup file key cache True
+ go (Nothing, _) = stop
{- On error, put the file back so it doesn't seem to have vanished.
- This can be called before or after the symlink is in place. -}
@@ -199,18 +208,19 @@ undo file key e = do
liftIO $ moveFile src file
{- Creates the symlink to the annexed content, returns the link target. -}
-link :: FilePath -> Key -> Bool -> Annex String
-link file key hascontent = flip catchAnnex (undo file key) $ do
+link :: FilePath -> Key -> Maybe InodeCache -> Annex String
+link file key mcache = flip catchAnnex (undo file key) $ do
l <- inRepo $ gitAnnexLink file key
replaceFile file $ makeAnnexLink l
+#ifdef WITH_CLIBS
#ifndef __ANDROID__
- when hascontent $ do
- -- touch the symlink to have the same mtime as the
- -- file it points to
- liftIO $ do
- mtime <- modificationTime <$> getFileStatus file
- touch file (TimeSpec mtime) False
+ -- touch symlink to have same time as the original file,
+ -- as provided in the InodeCache
+ case mcache of
+ Just c -> liftIO $ touch file (TimeSpec $ inodeCacheToMtime c) False
+ Nothing -> noop
+#endif
#endif
return l
@@ -224,28 +234,28 @@ link file key hascontent = flip catchAnnex (undo file key) $ do
- Also, using git add allows it to skip gitignored files, unless forced
- to include them.
-}
-addLink :: FilePath -> Key -> Bool -> Annex ()
-addLink file key hascontent = ifM (coreSymlinks <$> Annex.getGitConfig)
+addLink :: FilePath -> Key -> Maybe InodeCache -> Annex ()
+addLink file key mcache = ifM (coreSymlinks <$> Annex.getGitConfig)
( do
- _ <- link file key hascontent
+ _ <- link file key mcache
params <- ifM (Annex.getState Annex.force)
( return [Param "-f"]
, return []
)
Annex.Queue.addCommand "add" (params++[Param "--"]) [file]
, do
- l <- link file key hascontent
+ l <- link file key mcache
addAnnexLink l file
)
-cleanup :: FilePath -> Key -> Bool -> CommandCleanup
-cleanup file key hascontent = do
+cleanup :: FilePath -> Key -> Maybe InodeCache -> Bool -> CommandCleanup
+cleanup file key mcache hascontent = do
when hascontent $
logStatus key InfoPresent
ifM (isDirect <&&> pure hascontent)
( do
l <- inRepo $ gitAnnexLink file key
stageSymlink file =<< hashSymlink l
- , addLink file key hascontent
+ , addLink file key mcache
)
return True
diff --git a/Command/AddUnused.hs b/Command/AddUnused.hs
index 21a75137f..1a178e8d4 100644
--- a/Command/AddUnused.hs
+++ b/Command/AddUnused.hs
@@ -29,7 +29,7 @@ start = startUnused "addunused" perform
perform :: Key -> CommandPerform
perform key = next $ do
logStatus key InfoPresent
- Command.Add.addLink file key False
+ Command.Add.addLink file key Nothing
return True
where
file = "unused." ++ key2file key
diff --git a/Command/AddUrl.hs b/Command/AddUrl.hs
index d172a6869..27ca72d1a 100644
--- a/Command/AddUrl.hs
+++ b/Command/AddUrl.hs
@@ -5,6 +5,8 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Command.AddUrl where
import Network.URI
@@ -15,8 +17,8 @@ import Backend
import qualified Command.Add
import qualified Annex
import qualified Annex.Queue
+import qualified Annex.Url as Url
import qualified Backend.URL
-import qualified Utility.Url as Url
import Annex.Content
import Logs.Web
import qualified Option
@@ -27,6 +29,10 @@ import Annex.Content.Direct
import Logs.Location
import qualified Logs.Transfer as Transfer
import Utility.Daemon (checkDaemon)
+#ifdef WITH_QUVI
+import Annex.Quvi
+import qualified Utility.Quvi as Quvi
+#endif
def :: [Command]
def = [notBareRepo $ withOptions [fileOption, pathdepthOption, relaxedOption] $
@@ -51,15 +57,64 @@ seek = [withField fileOption return $ \f ->
start :: Bool -> Maybe FilePath -> Maybe Int -> String -> CommandStart
start relaxed optfile pathdepth s = go $ fromMaybe bad $ parseURI s
where
- bad = fromMaybe (error $ "bad url " ++ s) $
- parseURI $ escapeURIString isUnescapedInURI s
- go url = do
+ (s', downloader) = getDownloader s
+ bad = fromMaybe (error $ "bad url " ++ s') $
+ parseURI $ escapeURIString isUnescapedInURI s'
+ choosefile = flip fromMaybe optfile
+ go url = case downloader of
+ QuviDownloader -> usequvi
+ DefaultDownloader ->
+#ifdef WITH_QUVI
+ ifM (liftIO $ Quvi.supported s')
+ ( usequvi
+ , regulardownload url
+ )
+#else
+ regulardownload url
+#endif
+ regulardownload url = do
+ pathmax <- liftIO $ fileNameLengthLimit "."
+ let file = choosefile $ url2file url pathdepth pathmax
+ showStart "addurl" file
+ next $ perform relaxed s' file
+#ifdef WITH_QUVI
+ badquvi = error $ "quvi does not know how to download url " ++ s'
+ usequvi = do
+ page <- fromMaybe badquvi
+ <$> withQuviOptions Quvi.forceQuery [Quvi.quiet, Quvi.httponly] s'
+ let link = fromMaybe badquvi $ headMaybe $ Quvi.pageLinks page
pathmax <- liftIO $ fileNameLengthLimit "."
- let file = fromMaybe (url2file url pathdepth pathmax) optfile
+ let file = choosefile $ truncateFilePath pathmax $ sanitizeFilePath $
+ Quvi.pageTitle page ++ "." ++ Quvi.linkSuffix link
showStart "addurl" file
- next $ perform relaxed s file
+ next $ performQuvi relaxed s' (Quvi.linkUrl link) file
+#else
+ usequvi = error "not built with quvi support"
+#endif
-perform :: Bool -> String -> FilePath -> CommandPerform
+#ifdef WITH_QUVI
+performQuvi :: Bool -> URLString -> URLString -> FilePath -> CommandPerform
+performQuvi relaxed pageurl videourl file = ifAnnexed file addurl geturl
+ where
+ quviurl = setDownloader pageurl QuviDownloader
+ addurl (key, _backend) = next $ cleanup quviurl file key Nothing
+ geturl = do
+ key <- Backend.URL.fromUrl quviurl Nothing
+ ifM (pure relaxed <||> Annex.getState Annex.fast)
+ ( next $ cleanup quviurl file key Nothing
+ , do
+ tmp <- fromRepo $ gitAnnexTmpLocation key
+ showOutput
+ ok <- Transfer.download webUUID key (Just file) Transfer.forwardRetry $ const $ do
+ liftIO $ createDirectoryIfMissing True (parentDir tmp)
+ downloadUrl [videourl] tmp
+ if ok
+ then next $ cleanup quviurl file key (Just tmp)
+ else stop
+ )
+#endif
+
+perform :: Bool -> URLString -> FilePath -> CommandPerform
perform relaxed url file = ifAnnexed file addurl geturl
where
geturl = next $ addUrlFile relaxed url file
@@ -69,16 +124,18 @@ perform relaxed url file = ifAnnexed file addurl geturl
next $ return True
| otherwise = do
headers <- getHttpHeaders
- ifM (liftIO $ Url.check url headers $ keySize key)
- ( do
+ (exists, samesize) <- Url.withUserAgent $ Url.check url headers $ keySize key
+ if exists && samesize
+ then do
setUrlPresent key url
next $ return True
- , do
- warning $ "failed to verify url exists: " ++ url
+ 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
- )
-addUrlFile :: Bool -> String -> FilePath -> Annex Bool
+addUrlFile :: Bool -> URLString -> FilePath -> Annex Bool
addUrlFile relaxed url file = do
liftIO $ createDirectoryIfMissing True (parentDir file)
ifM (Annex.getState Annex.fast <||> pure relaxed)
@@ -88,7 +145,7 @@ addUrlFile relaxed url file = do
download url file
)
-download :: String -> FilePath -> Annex Bool
+download :: URLString -> FilePath -> Annex Bool
download url file = do
dummykey <- genkey
tmp <- fromRepo $ gitAnnexTmpLocation dummykey
@@ -120,7 +177,7 @@ download url file = do
size <- ifM (liftIO $ isJust <$> checkDaemon pidfile)
( do
headers <- getHttpHeaders
- liftIO $ snd <$> Url.exists url headers
+ snd <$> Url.withUserAgent (Url.exists url headers)
, return Nothing
)
Backend.URL.fromUrl url size
@@ -130,12 +187,12 @@ download url file = do
downloadUrl [url] tmp
-cleanup :: String -> FilePath -> Key -> Maybe FilePath -> Annex Bool
+cleanup :: URLString -> FilePath -> Key -> Maybe FilePath -> Annex Bool
cleanup url file key mtmp = do
when (isJust mtmp) $
logStatus key InfoPresent
setUrlPresent key url
- Command.Add.addLink file key False
+ Command.Add.addLink file key Nothing
whenM isDirect $ do
void $ addAssociatedFile key file
{- For moveAnnex to work in direct mode, the symlink
@@ -144,12 +201,12 @@ cleanup url file key mtmp = do
maybe noop (moveAnnex key) mtmp
return True
-nodownload :: Bool -> String -> FilePath -> Annex Bool
+nodownload :: Bool -> URLString -> FilePath -> Annex Bool
nodownload relaxed url file = do
headers <- getHttpHeaders
(exists, size) <- if relaxed
then pure (True, Nothing)
- else liftIO $ Url.exists url headers
+ else Url.withUserAgent $ Url.exists url headers
if exists
then do
key <- Backend.URL.fromUrl url size
@@ -160,7 +217,7 @@ nodownload relaxed url file = do
url2file :: URI -> Maybe Int -> Int -> FilePath
url2file url pathdepth pathmax = case pathdepth of
- Nothing -> truncateFilePath pathmax $ escape fullurl
+ Nothing -> truncateFilePath pathmax $ sanitizeFilePath fullurl
Just depth
| depth >= length urlbits -> frombits id
| depth > 0 -> frombits $ drop depth
@@ -169,6 +226,6 @@ url2file url pathdepth pathmax = case pathdepth of
where
fullurl = uriRegName auth ++ uriPath url ++ uriQuery url
frombits a = intercalate "/" $ a urlbits
- urlbits = map (truncateFilePath pathmax . escape) $ filter (not . null) $ split "/" fullurl
+ urlbits = map (truncateFilePath pathmax . sanitizeFilePath) $
+ filter (not . null) $ split "/" fullurl
auth = fromMaybe (error $ "bad url " ++ show url) $ uriAuthority url
- escape = replace "/" "_" . replace "?" "_"
diff --git a/Command/Assistant.hs b/Command/Assistant.hs
index f65bed736..521a88571 100644
--- a/Command/Assistant.hs
+++ b/Command/Assistant.hs
@@ -14,43 +14,55 @@ import qualified Command.Watch
import Init
import Config.Files
import qualified Build.SysConfig
+import Utility.HumanTime
import System.Environment
def :: [Command]
-def = [noRepo checkAutoStart $ dontCheck repoExists $
- withOptions [Command.Watch.foregroundOption, Command.Watch.stopOption, autoStartOption] $
+def = [noRepo checkAutoStart $ dontCheck repoExists $ withOptions options $
command "assistant" paramNothing seek SectionCommon
"automatically handle changes"]
+options :: [Option]
+options =
+ [ Command.Watch.foregroundOption
+ , Command.Watch.stopOption
+ , autoStartOption
+ , startDelayOption
+ ]
+
autoStartOption :: Option
autoStartOption = Option.flag [] "autostart" "start in known repositories"
+startDelayOption :: Option
+startDelayOption = Option.field [] "startdelay" paramNumber "delay before running startup scan"
+
seek :: [CommandSeek]
seek = [withFlag Command.Watch.stopOption $ \stopdaemon ->
withFlag Command.Watch.foregroundOption $ \foreground ->
withFlag autoStartOption $ \autostart ->
- withNothing $ start foreground stopdaemon autostart]
+ withField startDelayOption (pure . maybe Nothing parseDuration) $ \startdelay ->
+ withNothing $ start foreground stopdaemon autostart startdelay]
-start :: Bool -> Bool -> Bool -> CommandStart
-start foreground stopdaemon autostart
+start :: Bool -> Bool -> Bool -> Maybe Duration -> CommandStart
+start foreground stopdaemon autostart startdelay
| autostart = do
- liftIO autoStart
+ liftIO $ autoStart startdelay
stop
| otherwise = do
ensureInitialized
- Command.Watch.start True foreground stopdaemon
+ Command.Watch.start True foreground stopdaemon startdelay
{- Run outside a git repository. Check to see if any parameter is
- --autostart and enter autostart mode. -}
checkAutoStart :: IO ()
checkAutoStart = ifM (elem "--autostart" <$> getArgs)
- ( autoStart
+ ( autoStart Nothing
, error "Not in a git repository."
)
-autoStart :: IO ()
-autoStart = do
+autoStart :: Maybe Duration -> IO ()
+autoStart startdelay = do
dirs <- liftIO readAutoStartFile
when (null dirs) $ do
f <- autoStartFile
@@ -67,5 +79,10 @@ autoStart = do
go haveionice program dir = do
setCurrentDirectory dir
if haveionice
- then boolSystem "ionice" [Param "-c3", Param program, Param "assistant"]
- else boolSystem program [Param "assistant"]
+ then boolSystem "ionice" (Param "-c3" : Param program : baseparams)
+ else boolSystem program baseparams
+ where
+ baseparams =
+ [ Param "assistant"
+ , Param $ "--startdelay=" ++ fromDuration (fromMaybe (Duration 5) startdelay)
+ ]
diff --git a/Command/ConfigList.hs b/Command/ConfigList.hs
index 703d6882d..c42480200 100644
--- a/Command/ConfigList.hs
+++ b/Command/ConfigList.hs
@@ -10,6 +10,8 @@ module Command.ConfigList where
import Common.Annex
import Command
import Annex.UUID
+import qualified Git.Config
+import Remote.GCrypt (coreGCryptId)
def :: [Command]
def = [noCommit $ command "configlist" paramNothing seek
@@ -21,5 +23,8 @@ seek = [withNothing start]
start :: CommandStart
start = do
u <- getUUID
- liftIO $ putStrLn $ "annex.uuid=" ++ fromUUID u
+ showConfig "annex.uuid" $ fromUUID u
+ showConfig coreGCryptId =<< fromRepo (Git.Config.get coreGCryptId "")
stop
+ where
+ showConfig k v = liftIO $ putStrLn $ k ++ "=" ++ v
diff --git a/Command/Copy.hs b/Command/Copy.hs
index 4e1646ad1..9fd97334a 100644
--- a/Command/Copy.hs
+++ b/Command/Copy.hs
@@ -9,6 +9,7 @@ module Command.Copy where
import Common.Annex
import Command
+import GitAnnex.Options
import qualified Command.Move
import qualified Remote
import Annex.Wanted
@@ -19,8 +20,8 @@ def = [withOptions Command.Move.moveOptions $ command "copy" paramPaths seek
seek :: [CommandSeek]
seek =
- [ withField Command.Move.toOption Remote.byNameWithUUID $ \to ->
- withField Command.Move.fromOption Remote.byNameWithUUID $ \from ->
+ [ withField toOption Remote.byNameWithUUID $ \to ->
+ withField fromOption Remote.byNameWithUUID $ \from ->
withKeyOptions (Command.Move.startKey to from False) $
withFilesInGit $ whenAnnexed $ start to from
]
diff --git a/Command/Direct.hs b/Command/Direct.hs
index 7835988b4..1f262bd9f 100644
--- a/Command/Direct.hs
+++ b/Command/Direct.hs
@@ -7,6 +7,8 @@
module Command.Direct where
+import Control.Exception.Extensible
+
import Common.Annex
import Command
import qualified Git
@@ -15,6 +17,7 @@ import qualified Git.LsFiles
import Config
import Annex.Direct
import Annex.Version
+import Annex.Exception
def :: [Command]
def = [notBareRepo $ noDaemonRunning $
@@ -51,10 +54,17 @@ perform = do
Nothing -> noop
Just a -> do
showStart "direct" f
- a
- showEndOk
+ r' <- tryAnnex a
+ case r' of
+ Left e -> warnlocked e
+ Right _ -> showEndOk
return Nothing
+ warnlocked :: SomeException -> Annex ()
+ warnlocked e = do
+ warning $ show e
+ warning "leaving this file as-is; correct this problem and run git annex fsck on it"
+
cleanup :: CommandCleanup
cleanup = do
showStart "direct" ""
diff --git a/Command/Drop.hs b/Command/Drop.hs
index b3f7d7574..5d642ed3a 100644
--- a/Command/Drop.hs
+++ b/Command/Drop.hs
@@ -139,7 +139,7 @@ notEnoughCopies key need have skip bad = do
unsafe = showNote "unsafe"
hint = showLongNote "(Use --force to override this check, or adjust annex.numcopies.)"
-{- In auto mode, only runs the action if there are enough copies
+{- In auto mode, only runs the action if there are enough
- copies on other semitrusted repositories.
-
- Passes any numcopies attribute of the file on to the action as an
diff --git a/Command/EnableRemote.hs b/Command/EnableRemote.hs
index ea606c284..f6a1b819c 100644
--- a/Command/EnableRemote.hs
+++ b/Command/EnableRemote.hs
@@ -43,12 +43,12 @@ unknownNameError prefix = do
error $ prefix ++
if null names
then ""
- else " Known special remotes: " ++ intercalate " " names
+ else " Known special remotes: " ++ unwords names
perform :: RemoteType -> UUID -> R.RemoteConfig -> CommandPerform
perform t u c = do
- c' <- R.setup t u c
- next $ cleanup u c'
+ (c', u') <- R.setup t (Just u) c
+ next $ cleanup u' c'
cleanup :: UUID -> R.RemoteConfig -> CommandCleanup
cleanup u c = do
diff --git a/Command/Fix.hs b/Command/Fix.hs
index da2627619..a63a10f8f 100644
--- a/Command/Fix.hs
+++ b/Command/Fix.hs
@@ -14,9 +14,11 @@ import System.PosixCompat.Files
import Common.Annex
import Command
import qualified Annex.Queue
+#ifdef WITH_CLIBS
#ifndef __ANDROID__
import Utility.Touch
#endif
+#endif
def :: [Command]
def = [notDirect $ noCommit $ command "fix" paramPaths seek
@@ -36,17 +38,21 @@ start file (key, _) = do
perform :: FilePath -> FilePath -> CommandPerform
perform file link = do
liftIO $ do
+#ifdef WITH_CLIBS
#ifndef __ANDROID__
-- preserve mtime of symlink
mtime <- catchMaybeIO $ TimeSpec . modificationTime
<$> getSymbolicLinkStatus file
#endif
+#endif
createDirectoryIfMissing True (parentDir file)
removeFile file
createSymbolicLink link file
+#ifdef WITH_CLIBS
#ifndef __ANDROID__
maybe noop (\t -> touch file t False) mtime
#endif
+#endif
next $ cleanup file
cleanup :: FilePath -> CommandCleanup
diff --git a/Command/Forget.hs b/Command/Forget.hs
new file mode 100644
index 000000000..74bd68ad1
--- /dev/null
+++ b/Command/Forget.hs
@@ -0,0 +1,52 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Forget where
+
+import Common.Annex
+import Command
+import qualified Annex.Branch as Branch
+import Logs.Transitions
+import qualified Annex
+import qualified Option
+
+import Data.Time.Clock.POSIX
+
+def :: [Command]
+def = [withOptions forgetOptions $ command "forget" paramNothing seek
+ SectionMaintenance "prune git-annex branch history"]
+
+forgetOptions :: [Option]
+forgetOptions = [dropDeadOption]
+
+dropDeadOption :: Option
+dropDeadOption = Option.flag [] "drop-dead" "drop references to dead repositories"
+
+seek :: [CommandSeek]
+seek = [withFlag dropDeadOption $ \dropdead ->
+ withNothing $ start dropdead]
+
+start :: Bool -> CommandStart
+start dropdead = do
+ showStart "forget" "git-annex"
+ now <- liftIO getPOSIXTime
+ let basets = addTransition now ForgetGitHistory noTransitions
+ let ts = if dropdead
+ then addTransition now ForgetDeadRemotes basets
+ else basets
+ next $ perform ts =<< Annex.getState Annex.force
+
+perform :: Transitions -> Bool -> CommandPerform
+perform ts True = do
+ recordTransitions Branch.change ts
+ -- get branch committed before contining with the transition
+ Branch.update
+ void $ Branch.performTransitions ts True []
+ next $ return True
+perform _ False = do
+ showLongNote "To forget git-annex branch history, you must specify --force. This deletes metadata!"
+ stop
diff --git a/Command/Fsck.hs b/Command/Fsck.hs
index 6464fc002..3b89c550c 100644
--- a/Command/Fsck.hs
+++ b/Command/Fsck.hs
@@ -33,7 +33,7 @@ import qualified Option
import Types.Key
import Utility.HumanTime
import Git.FilePath
-import GitAnnex.Options
+import GitAnnex.Options hiding (fromOption)
#ifndef mingw32_HOST_OS
import System.Posix.Process (getProcessID)
@@ -104,7 +104,7 @@ withIncremental = withValue $ do
Nothing -> noop
Just started -> do
now <- liftIO getPOSIXTime
- when (now - realToFrac started >= delta) $
+ when (now - realToFrac started >= durationToPOSIXTime delta)
resetStartTime
return True
@@ -187,7 +187,7 @@ performAll key backend = check
]
check :: [Annex Bool] -> Annex Bool
-check cs = all id <$> sequence cs
+check cs = and <$> sequence cs
{- Checks that the file's link points correctly to the content.
-
@@ -225,7 +225,7 @@ verifyLocationLog key desc = do
{- In direct mode, modified files will show up as not present,
- but that is expected and not something to do anything about. -}
- if (direct && not present)
+ if direct && not present
then return True
else verifyLocationLog' key desc present u (logChange key u)
@@ -271,7 +271,7 @@ verifyDirectMapping key file = do
{- Ensures that files whose content is available are in direct mode. -}
verifyDirectMode :: Key -> FilePath -> Annex Bool
verifyDirectMode key file = do
- whenM (isDirect <&&> islink) $ do
+ whenM (isDirect <&&> isJust <$> isAnnexLink file) $ do
v <- toDirectGen key file
case v of
Nothing -> noop
@@ -279,8 +279,6 @@ verifyDirectMode key file = do
showNote "fixing direct mode"
a
return True
- where
- islink = liftIO $ isSymbolicLink <$> getSymbolicLinkStatus file
{- The size of the data for a key is checked against the size encoded in
- the key's metadata, if available.
@@ -347,7 +345,7 @@ checkBackend backend key mfile = go =<< isDirect
checkBackendRemote :: Backend -> Key -> Remote -> Maybe FilePath -> Annex Bool
checkBackendRemote backend key remote = maybe (return True) go
where
- go file = checkBackendOr (badContentRemote remote) backend key file
+ go = checkBackendOr (badContentRemote remote) backend key
checkBackendOr :: (Key -> Annex String) -> Backend -> Key -> FilePath -> Annex Bool
checkBackendOr bad backend key file =
@@ -408,7 +406,7 @@ badContentDirect :: FilePath -> Key -> Annex String
badContentDirect file key = do
void $ liftIO $ catchMaybeIO $ touchFile file
logStatus key InfoMissing
- return $ "left in place for you to examine"
+ return "left in place for you to examine"
badContentRemote :: Remote -> Key -> Annex String
badContentRemote remote key = do
diff --git a/Command/GCryptSetup.hs b/Command/GCryptSetup.hs
new file mode 100644
index 000000000..bdd770f15
--- /dev/null
+++ b/Command/GCryptSetup.hs
@@ -0,0 +1,39 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.GCryptSetup where
+
+import Common.Annex
+import Command
+import Annex.UUID
+import qualified Remote.GCrypt
+import qualified Git
+
+def :: [Command]
+def = [dontCheck repoExists $ noCommit $
+ command "gcryptsetup" paramValue seek
+ SectionPlumbing "sets up gcrypt repository"]
+
+seek :: [CommandSeek]
+seek = [withStrings start]
+
+start :: String -> CommandStart
+start gcryptid = next $ next $ do
+ u <- getUUID
+ when (u /= NoUUID) $
+ error "gcryptsetup refusing to run; this repository already has a git-annex uuid!"
+
+ g <- gitRepo
+ gu <- Remote.GCrypt.getGCryptUUID True g
+ let newgu = genUUIDInNameSpace gCryptNameSpace gcryptid
+ if gu == Nothing || gu == Just newgu
+ then if Git.repoIsLocalBare g
+ then do
+ void $ Remote.GCrypt.setupRepo gcryptid g
+ return True
+ else error "cannot use gcrypt in a non-bare repository"
+ else error "gcryptsetup uuid mismatch"
diff --git a/Command/Get.hs b/Command/Get.hs
index 31a75c3e1..9adf79393 100644
--- a/Command/Get.hs
+++ b/Command/Get.hs
@@ -11,10 +11,10 @@ import Common.Annex
import Command
import qualified Remote
import Annex.Content
-import qualified Command.Move
import Logs.Transfer
import Annex.Wanted
import GitAnnex.Options
+import qualified Command.Move
import Types.Key
def :: [Command]
@@ -22,11 +22,11 @@ def = [withOptions getOptions $ command "get" paramPaths seek
SectionCommon "make content of annexed files available"]
getOptions :: [Option]
-getOptions = [Command.Move.fromOption] ++ keyOptions
+getOptions = fromOption : keyOptions
seek :: [CommandSeek]
seek =
- [ withField Command.Move.fromOption Remote.byNameWithUUID $ \from ->
+ [ withField fromOption Remote.byNameWithUUID $ \from ->
withKeyOptions (startKeys from) $
withFilesInGit $ whenAnnexed $ start from
]
@@ -75,7 +75,7 @@ getKeyFile key afile dest = dispatch =<< Remote.keyPossibilities key
( docopy r (trycopy full rs)
, trycopy full rs
)
- showlocs = Remote.showLocations key [] $
+ showlocs = Remote.showLocations key []
"No other repository is known to contain the file."
-- This check is to avoid an ugly message if a remote is a
-- drive that is not mounted.
diff --git a/Command/Import.hs b/Command/Import.hs
index 518666af9..dcadd96ce 100644
--- a/Command/Import.hs
+++ b/Command/Import.hs
@@ -1,6 +1,6 @@
{- git-annex command
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -13,30 +13,92 @@ import Common.Annex
import Command
import qualified Annex
import qualified Command.Add
+import qualified Option
+import Utility.CopyFile
+import Backend
+import Remote
+import Types.KeySource
def :: [Command]
-def = [notBareRepo $ command "import" paramPaths seek
+def = [withOptions opts $ notBareRepo $ command "import" paramPaths seek
SectionCommon "move and add files from outside git working copy"]
+opts :: [Option]
+opts =
+ [ duplicateOption
+ , deduplicateOption
+ , cleanDuplicatesOption
+ ]
+
+duplicateOption :: Option
+duplicateOption = Option.flag [] "duplicate" "do not delete outside files"
+
+deduplicateOption :: Option
+deduplicateOption = Option.flag [] "deduplicate" "do not add files whose content has been seen"
+
+cleanDuplicatesOption :: Option
+cleanDuplicatesOption = Option.flag [] "clean-duplicates" "delete outside duplicate files (import nothing)"
+
+data DuplicateMode = Default | Duplicate | DeDuplicate | CleanDuplicates
+ deriving (Eq)
+
+getDuplicateMode :: Annex DuplicateMode
+getDuplicateMode = gen
+ <$> getflag duplicateOption
+ <*> getflag deduplicateOption
+ <*> getflag cleanDuplicatesOption
+ where
+ getflag = Annex.getFlag . Option.name
+ gen False False False = Default
+ gen True False False = Duplicate
+ gen False True False = DeDuplicate
+ gen False False True = CleanDuplicates
+ gen _ _ _ = error "bad combination of --duplicate, --deduplicate, --clean-duplicates"
+
seek :: [CommandSeek]
-seek = [withPathContents start]
+seek = [withValue getDuplicateMode $ \mode -> withPathContents $ start mode]
-start :: (FilePath, FilePath) -> CommandStart
-start (srcfile, destfile) =
+start :: DuplicateMode -> (FilePath, FilePath) -> CommandStart
+start mode (srcfile, destfile) =
ifM (liftIO $ isRegularFile <$> getSymbolicLinkStatus srcfile)
( do
showStart "import" destfile
- next $ perform srcfile destfile
+ next $ perform mode srcfile destfile
, stop
)
-perform :: FilePath -> FilePath -> CommandPerform
-perform srcfile destfile = do
- whenM (liftIO $ doesFileExist destfile) $
- unlessM (Annex.getState Annex.force) $
- error $ "not overwriting existing " ++ destfile ++
- " (use --force to override)"
-
- liftIO $ createDirectoryIfMissing True (parentDir destfile)
- liftIO $ moveFile srcfile destfile
- Command.Add.perform destfile
+perform :: DuplicateMode -> FilePath -> FilePath -> CommandPerform
+perform mode srcfile destfile =
+ case mode of
+ DeDuplicate -> ifM isdup
+ ( deletedup
+ , go
+ )
+ CleanDuplicates -> ifM isdup
+ ( deletedup
+ , next $ return True
+ )
+ _ -> go
+ where
+ isdup = do
+ backend <- chooseBackend destfile
+ let ks = KeySource srcfile srcfile Nothing
+ v <- genKey ks backend
+ case v of
+ Just (k, _) -> not . null <$> keyLocations k
+ _ -> return False
+ deletedup = do
+ showNote "duplicate"
+ liftIO $ removeFile srcfile
+ next $ return True
+ go = do
+ whenM (liftIO $ doesFileExist destfile) $
+ unlessM (Annex.getState Annex.force) $
+ error $ "not overwriting existing " ++ destfile ++
+ " (use --force to override)"
+
+ liftIO $ createDirectoryIfMissing True (parentDir destfile)
+ liftIO $ if mode == Duplicate
+ then void $ copyFileExternal srcfile destfile
+ else moveFile srcfile destfile
+ Command.Add.perform destfile
diff --git a/Command/ImportFeed.hs b/Command/ImportFeed.hs
index 5ad568647..7f54643c9 100644
--- a/Command/ImportFeed.hs
+++ b/Command/ImportFeed.hs
@@ -12,13 +12,12 @@ import Text.Feed.Query
import Text.Feed.Types
import qualified Data.Set as S
import qualified Data.Map as M
-import Data.Char
import Data.Time.Clock
import Common.Annex
import qualified Annex
import Command
-import qualified Utility.Url as Url
+import qualified Annex.Url as Url
import Logs.Web
import qualified Option
import qualified Utility.Format
@@ -51,9 +50,10 @@ perform relaxed cache url = do
v <- findEnclosures url
case v of
Just l | not (null l) -> do
- ok <- all id
- <$> mapM (downloadEnclosure relaxed cache) l
- next $ cleanup url ok
+ ok <- and <$> mapM (downloadEnclosure relaxed cache) l
+ unless ok $
+ feedProblem url "problem downloading item"
+ next $ cleanup url True
_ -> do
feedProblem url "bad feed content"
next $ return True
@@ -102,9 +102,10 @@ findEnclosures url = extract <$> downloadFeed url
downloadFeed :: URLString -> Annex (Maybe Feed)
downloadFeed url = do
showOutput
+ ua <- Url.getUserAgent
liftIO $ withTmpFile "feed" $ \f h -> do
fileEncoding h
- ifM (Url.download url [] [] f)
+ ifM (Url.download url [] [] f ua)
( liftIO $ parseFeedString <$> hGetContentsStrict h
, return Nothing
)
@@ -172,20 +173,15 @@ feedFile tmpl i = Utility.Format.format tmpl $ M.fromList
, fieldMaybe "itemdescription" $ getItemDescription $ item i
, fieldMaybe "itemrights" $ getItemRights $ item i
, fieldMaybe "itemid" $ snd <$> getItemId (item i)
- , ("extension", map sanitize $ takeExtension $ location i)
+ , ("extension", sanitizeFilePath $ takeExtension $ location i)
]
where
field k v =
- let s = map sanitize v in
+ let s = sanitizeFilePath v in
if null s then (k, "none") else (k, s)
fieldMaybe k Nothing = (k, "none")
fieldMaybe k (Just v) = field k v
- sanitize c
- | c == '.' = c
- | isSpace c || isPunctuation c || c == '/' = '_'
- | otherwise = c
-
{- Called when there is a problem with a feed.
- Throws an error if the feed is broken, otherwise shows a warning. -}
feedProblem :: URLString -> String -> Annex ()
diff --git a/Command/Indirect.hs b/Command/Indirect.hs
index e63c4cb8a..a2512ea96 100644
--- a/Command/Indirect.hs
+++ b/Command/Indirect.hs
@@ -8,12 +8,14 @@
module Command.Indirect where
import System.PosixCompat.Files
+import Control.Exception.Extensible
import Common.Annex
import Command
import qualified Git
import qualified Git.Command
import qualified Git.LsFiles
+import Git.FileMode
import Config
import qualified Annex
import Annex.Direct
@@ -21,7 +23,9 @@ import Annex.Content
import Annex.CatFile
import Annex.Version
import Annex.Perms
+import Annex.Exception
import Init
+import qualified Command.Add
def :: [Command]
def = [notBareRepo $ noDaemonRunning $
@@ -45,7 +49,7 @@ start = ifM isDirect
perform :: CommandPerform
perform = do
showStart "commit" ""
- whenM (stageDirect) $ do
+ whenM stageDirect $ do
showOutput
void $ inRepo $ Git.Command.runBool
[ Param "commit"
@@ -67,8 +71,7 @@ perform = do
{- Walk tree from top and move all present direct mode files into
- the annex, replacing with symlinks. Also delete direct mode
- caches and mappings. -}
- go (_, Nothing) = noop
- go (f, Just sha) = do
+ go (f, Just sha, Just mode) | isSymLink mode = do
r <- liftIO $ catchMaybeIO $ getSymbolicLinkStatus f
case r of
Just s
@@ -78,23 +81,33 @@ perform = do
return Nothing
| otherwise ->
maybe noop (fromdirect f)
- =<< catKey sha
+ =<< catKey sha mode
_ -> noop
+ go _ = noop
fromdirect f k = do
showStart "indirect" f
thawContentDir =<< calcRepo (gitAnnexLocation k)
cleandirect k -- clean before content directory gets frozen
whenM (liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f) $ do
- moveAnnex k f
- l <- inRepo $ gitAnnexLink f k
- liftIO $ createSymbolicLink l f
+ v <-tryAnnexIO (moveAnnex k f)
+ case v of
+ Right _ -> do
+ l <- inRepo $ gitAnnexLink f k
+ liftIO $ createSymbolicLink l f
+ Left e -> catchAnnex (Command.Add.undo f k e)
+ warnlocked
showEndOk
+ warnlocked :: SomeException -> Annex ()
+ warnlocked e = do
+ warning $ show e
+ warning "leaving this file as-is; correct this problem and run git annex add on it"
+
cleandirect k = do
liftIO . nukeFile =<< calcRepo (gitAnnexInodeCache k)
liftIO . nukeFile =<< calcRepo (gitAnnexMapping k)
-
+
cleanup :: CommandCleanup
cleanup = do
setVersion defaultVersion
diff --git a/Command/Info.hs b/Command/Info.hs
new file mode 100644
index 000000000..d465f2d84
--- /dev/null
+++ b/Command/Info.hs
@@ -0,0 +1,384 @@
+{- git-annex command
+ -
+ - Copyright 2011 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE BangPatterns #-}
+
+module Command.Info where
+
+import "mtl" Control.Monad.State.Strict
+import qualified Data.Map as M
+import Text.JSON
+import Data.Tuple
+import Data.Ord
+import System.PosixCompat.Files
+
+import Common.Annex
+import qualified Remote
+import qualified Command.Unused
+import qualified Git
+import qualified Annex
+import Command
+import Utility.DataUnits
+import Utility.DiskFree
+import Annex.Content
+import Types.Key
+import Logs.UUID
+import Logs.Trust
+import Remote
+import Config
+import Utility.Percentage
+import Logs.Transfer
+import Types.TrustLevel
+import Types.FileMatcher
+import qualified Limit
+
+-- a named computation that produces a statistic
+type Stat = StatState (Maybe (String, StatState String))
+
+-- data about a set of keys
+data KeyData = KeyData
+ { countKeys :: Integer
+ , sizeKeys :: Integer
+ , unknownSizeKeys :: Integer
+ , backendsKeys :: M.Map String Integer
+ }
+
+data NumCopiesStats = NumCopiesStats
+ { numCopiesVarianceMap :: M.Map Variance Integer
+ }
+
+newtype Variance = Variance Int
+ deriving (Eq, Ord)
+
+instance Show Variance where
+ show (Variance n)
+ | n >= 0 = "numcopies +" ++ show n
+ | otherwise = "numcopies " ++ show n
+
+-- cached info that multiple Stats use
+data StatInfo = StatInfo
+ { presentData :: Maybe KeyData
+ , referencedData :: Maybe KeyData
+ , numCopiesStats :: Maybe NumCopiesStats
+ }
+
+-- a state monad for running Stats in
+type StatState = StateT StatInfo Annex
+
+def :: [Command]
+def = [noCommit $ command "info" paramPaths seek
+ SectionQuery "shows general information about the annex"]
+
+seek :: [CommandSeek]
+seek = [withWords start]
+
+start :: [FilePath] -> CommandStart
+start [] = do
+ globalInfo
+ stop
+start ps = do
+ mapM_ localInfo =<< filterM isdir ps
+ stop
+ where
+ isdir = liftIO . catchBoolIO . (isDirectory <$$> getFileStatus)
+
+globalInfo :: Annex ()
+globalInfo = do
+ stats <- selStats global_fast_stats global_slow_stats
+ showCustom "info" $ do
+ evalStateT (mapM_ showStat stats) (StatInfo Nothing Nothing Nothing)
+ return True
+
+localInfo :: FilePath -> Annex ()
+localInfo dir = showCustom (unwords ["info", dir]) $ do
+ stats <- selStats (tostats local_fast_stats) (tostats local_slow_stats)
+ evalStateT (mapM_ showStat stats) =<< getLocalStatInfo dir
+ return True
+ where
+ tostats = map (\s -> s dir)
+
+selStats :: [Stat] -> [Stat] -> Annex [Stat]
+selStats fast_stats slow_stats = do
+ fast <- Annex.getState Annex.fast
+ return $ if fast
+ then fast_stats
+ else fast_stats ++ slow_stats
+
+{- Order is significant. Less expensive operations, and operations
+ - that share data go together.
+ -}
+global_fast_stats :: [Stat]
+global_fast_stats =
+ [ repository_mode
+ , remote_list Trusted
+ , remote_list SemiTrusted
+ , remote_list UnTrusted
+ , transfer_list
+ , disk_size
+ ]
+global_slow_stats :: [Stat]
+global_slow_stats =
+ [ tmp_size
+ , bad_data_size
+ , local_annex_keys
+ , local_annex_size
+ , known_annex_files
+ , known_annex_size
+ , bloom_info
+ , backend_usage
+ ]
+local_fast_stats :: [FilePath -> Stat]
+local_fast_stats =
+ [ local_dir
+ , const local_annex_keys
+ , const local_annex_size
+ , const known_annex_files
+ , const known_annex_size
+ ]
+local_slow_stats :: [FilePath -> Stat]
+local_slow_stats =
+ [ const numcopies_stats
+ ]
+
+stat :: String -> (String -> StatState String) -> Stat
+stat desc a = return $ Just (desc, a desc)
+
+nostat :: Stat
+nostat = return Nothing
+
+json :: JSON j => (j -> String) -> StatState j -> String -> StatState String
+json serialize a desc = do
+ j <- a
+ lift $ maybeShowJSON [(desc, j)]
+ return $ serialize j
+
+nojson :: StatState String -> String -> StatState String
+nojson a _ = a
+
+showStat :: Stat -> StatState ()
+showStat s = maybe noop calc =<< s
+ where
+ calc (desc, a) = do
+ (lift . showHeader) desc
+ lift . showRaw =<< a
+
+repository_mode :: Stat
+repository_mode = stat "repository mode" $ json id $ lift $
+ ifM isDirect
+ ( return "direct", return "indirect" )
+
+remote_list :: TrustLevel -> Stat
+remote_list level = stat n $ nojson $ lift $ do
+ us <- M.keys <$> (M.union <$> uuidMap <*> remoteMap Remote.name)
+ rs <- fst <$> trustPartition level us
+ s <- prettyPrintUUIDs n rs
+ return $ if null s then "0" else show (length rs) ++ "\n" ++ beginning s
+ where
+ n = showTrustLevel level ++ " repositories"
+
+local_dir :: FilePath -> Stat
+local_dir dir = stat "directory" $ json id $ return dir
+
+local_annex_keys :: Stat
+local_annex_keys = stat "local annex keys" $ json show $
+ countKeys <$> cachedPresentData
+
+local_annex_size :: Stat
+local_annex_size = stat "local annex size" $ json id $
+ showSizeKeys <$> cachedPresentData
+
+known_annex_files :: Stat
+known_annex_files = stat "annexed files in working tree" $ json show $
+ countKeys <$> cachedReferencedData
+
+known_annex_size :: Stat
+known_annex_size = stat "size of annexed files in working tree" $ json id $
+ showSizeKeys <$> cachedReferencedData
+
+tmp_size :: Stat
+tmp_size = staleSize "temporary directory size" gitAnnexTmpDir
+
+bad_data_size :: Stat
+bad_data_size = staleSize "bad keys size" gitAnnexBadDir
+
+bloom_info :: Stat
+bloom_info = stat "bloom filter size" $ json id $ do
+ localkeys <- countKeys <$> cachedPresentData
+ capacity <- fromIntegral <$> lift Command.Unused.bloomCapacity
+ let note = aside $
+ if localkeys >= capacity
+ then "appears too small for this repository; adjust annex.bloomcapacity"
+ else showPercentage 1 (percentage capacity localkeys) ++ " full"
+
+ -- Two bloom filters are used at the same time, so double the size
+ -- of one.
+ size <- roughSize memoryUnits False . (* 2) . fromIntegral . fst <$>
+ lift Command.Unused.bloomBitsHashes
+
+ return $ size ++ note
+
+transfer_list :: Stat
+transfer_list = stat "transfers in progress" $ nojson $ lift $ do
+ uuidmap <- Remote.remoteMap id
+ ts <- getTransfers
+ return $ if null ts
+ then "none"
+ else multiLine $
+ map (uncurry $ line uuidmap) $ sort ts
+ where
+ line uuidmap t i = unwords
+ [ showLcDirection (transferDirection t) ++ "ing"
+ , fromMaybe (key2file $ transferKey t) (associatedFile i)
+ , if transferDirection t == Upload then "to" else "from"
+ , maybe (fromUUID $ transferUUID t) Remote.name $
+ M.lookup (transferUUID t) uuidmap
+ ]
+
+disk_size :: Stat
+disk_size = stat "available local disk space" $ json id $ lift $
+ calcfree
+ <$> (annexDiskReserve <$> Annex.getGitConfig)
+ <*> inRepo (getDiskFree . gitAnnexDir)
+ where
+ calcfree reserve (Just have) = unwords
+ [ roughSize storageUnits False $ nonneg $ have - reserve
+ , "(+" ++ roughSize storageUnits False reserve
+ , "reserved)"
+ ]
+ calcfree _ _ = "unknown"
+
+ nonneg x
+ | x >= 0 = x
+ | otherwise = 0
+
+backend_usage :: Stat
+backend_usage = stat "backend usage" $ nojson $
+ calc
+ <$> (backendsKeys <$> cachedReferencedData)
+ <*> (backendsKeys <$> cachedPresentData)
+ where
+ calc x y = multiLine $
+ map (\(n, b) -> b ++ ": " ++ show n) $
+ reverse $ sort $ map swap $ M.toList $
+ M.unionWith (+) x y
+
+numcopies_stats :: Stat
+numcopies_stats = stat "numcopies stats" $ nojson $
+ calc <$> (maybe M.empty numCopiesVarianceMap <$> cachedNumCopiesStats)
+ where
+ calc = multiLine
+ . map (\(variance, count) -> show variance ++ ": " ++ show count)
+ . reverse . sortBy (comparing snd) . M.toList
+
+cachedPresentData :: StatState KeyData
+cachedPresentData = do
+ s <- get
+ case presentData s of
+ Just v -> return v
+ Nothing -> do
+ v <- foldKeys <$> lift getKeysPresent
+ put s { presentData = Just v }
+ return v
+
+cachedReferencedData :: StatState KeyData
+cachedReferencedData = do
+ s <- get
+ case referencedData s of
+ Just v -> return v
+ Nothing -> do
+ !v <- lift $ Command.Unused.withKeysReferenced
+ emptyKeyData addKey
+ put s { referencedData = Just v }
+ return v
+
+-- currently only available for local info
+cachedNumCopiesStats :: StatState (Maybe NumCopiesStats)
+cachedNumCopiesStats = numCopiesStats <$> get
+
+getLocalStatInfo :: FilePath -> Annex StatInfo
+getLocalStatInfo dir = do
+ fast <- Annex.getState Annex.fast
+ matcher <- Limit.getMatcher
+ (presentdata, referenceddata, numcopiesstats) <-
+ Command.Unused.withKeysFilesReferencedIn dir initial
+ (update matcher fast)
+ return $ StatInfo (Just presentdata) (Just referenceddata) (Just numcopiesstats)
+ where
+ initial = (emptyKeyData, emptyKeyData, emptyNumCopiesStats)
+ update matcher fast key file vs@(presentdata, referenceddata, numcopiesstats) =
+ ifM (matcher $ FileInfo file file)
+ ( do
+ !presentdata' <- ifM (inAnnex key)
+ ( return $ addKey key presentdata
+ , return presentdata
+ )
+ let !referenceddata' = addKey key referenceddata
+ !numcopiesstats' <- if fast
+ then return numcopiesstats
+ else updateNumCopiesStats key file numcopiesstats
+ return $! (presentdata', referenceddata', numcopiesstats')
+ , return vs
+ )
+
+emptyKeyData :: KeyData
+emptyKeyData = KeyData 0 0 0 M.empty
+
+emptyNumCopiesStats :: NumCopiesStats
+emptyNumCopiesStats = NumCopiesStats M.empty
+
+foldKeys :: [Key] -> KeyData
+foldKeys = foldl' (flip addKey) emptyKeyData
+
+addKey :: Key -> KeyData -> KeyData
+addKey key (KeyData count size unknownsize backends) =
+ KeyData count' size' unknownsize' backends'
+ where
+ {- All calculations strict to avoid thunks when repeatedly
+ - applied to many keys. -}
+ !count' = count + 1
+ !backends' = M.insertWith' (+) (keyBackendName key) 1 backends
+ !size' = maybe size (+ size) ks
+ !unknownsize' = maybe (unknownsize + 1) (const unknownsize) ks
+ ks = keySize key
+
+updateNumCopiesStats :: Key -> FilePath -> NumCopiesStats -> Annex NumCopiesStats
+updateNumCopiesStats key file (NumCopiesStats m) = do
+ !variance <- Variance <$> numCopiesCheck file key (-)
+ let !m' = M.insertWith' (+) variance 1 m
+ let !ret = NumCopiesStats m'
+ return ret
+
+showSizeKeys :: KeyData -> String
+showSizeKeys d = total ++ missingnote
+ where
+ total = roughSize storageUnits False $ sizeKeys d
+ missingnote
+ | unknownSizeKeys d == 0 = ""
+ | otherwise = aside $
+ "+ " ++ show (unknownSizeKeys d) ++
+ " unknown size"
+
+staleSize :: String -> (Git.Repo -> FilePath) -> Stat
+staleSize label dirspec = go =<< lift (dirKeys dirspec)
+ where
+ go [] = nostat
+ go keys = onsize =<< sum <$> keysizes keys
+ onsize 0 = nostat
+ onsize size = stat label $
+ json (++ aside "clean up with git-annex unused") $
+ return $ roughSize storageUnits False size
+ keysizes keys = do
+ dir <- lift $ fromRepo dirspec
+ liftIO $ forM keys $ \k -> catchDefaultIO 0 $
+ fromIntegral . fileSize
+ <$> getFileStatus (dir </> keyFile k)
+
+aside :: String -> String
+aside s = " (" ++ s ++ ")"
+
+multiLine :: [String] -> String
+multiLine = concatMap (\l -> "\n\t" ++ l)
diff --git a/Command/InitRemote.hs b/Command/InitRemote.hs
index 684a2cc91..5a240f800 100644
--- a/Command/InitRemote.hs
+++ b/Command/InitRemote.hs
@@ -14,7 +14,6 @@ import Command
import qualified Remote
import qualified Logs.Remote
import qualified Types.Remote as R
-import Annex.UUID
import Logs.UUID
import Logs.Trust
@@ -34,18 +33,18 @@ start (name:ws) = ifM (isJust <$> findExisting name)
( error $ "There is already a special remote named \"" ++ name ++
"\". (Use enableremote to enable an existing special remote.)"
, do
- (u, c) <- generateNew name
+ let c = newConfig name
t <- findType config
showStart "initremote" name
- next $ perform t u name $ M.union config c
+ next $ perform t name $ M.union config c
)
where
config = Logs.Remote.keyValToConfig ws
-perform :: RemoteType -> UUID -> String -> R.RemoteConfig -> CommandPerform
-perform t u name c = do
- c' <- R.setup t u c
+perform :: RemoteType -> String -> R.RemoteConfig -> CommandPerform
+perform t name c = do
+ (c', u) <- R.setup t Nothing c
next $ cleanup u name c'
cleanup :: UUID -> String -> R.RemoteConfig -> CommandCleanup
@@ -63,10 +62,8 @@ findExisting name = do
<$> Logs.Remote.readRemoteLog
return $ headMaybe matches
-generateNew :: String -> Annex (UUID, R.RemoteConfig)
-generateNew name = do
- uuid <- liftIO genUUID
- return (uuid, M.singleton nameKey name)
+newConfig :: String -> R.RemoteConfig
+newConfig name = M.singleton nameKey name
findByName :: String -> M.Map UUID R.RemoteConfig -> [(UUID, R.RemoteConfig)]
findByName n = filter (matching . snd) . M.toList
diff --git a/Command/List.hs b/Command/List.hs
new file mode 100644
index 000000000..12c27c022
--- /dev/null
+++ b/Command/List.hs
@@ -0,0 +1,88 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ - Copyright 2013 Antoine Beaupré
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.List where
+
+import qualified Data.Set as S
+import qualified Data.Map as M
+import Data.Function
+import Data.Tuple.Utils
+import Data.Ord
+
+import Common.Annex
+import Command
+import Remote
+import Logs.Trust
+import Logs.UUID
+import Annex.UUID
+import qualified Option
+import qualified Annex
+import Git.Types (RemoteName)
+
+def :: [Command]
+def = [noCommit $ withOptions [allrepos] $ command "list" paramPaths seek
+ SectionQuery "show which remotes contain files"]
+
+allrepos :: Option
+allrepos = Option.flag [] "allrepos" "show all repositories, not only remotes"
+
+seek :: [CommandSeek]
+seek =
+ [ withValue getList $ withNothing . startHeader
+ , withValue getList $ withFilesInGit . whenAnnexed . start
+ ]
+
+getList :: Annex [(UUID, RemoteName, TrustLevel)]
+getList = ifM (Annex.getFlag $ Option.name allrepos)
+ ( nubBy ((==) `on` fst3) <$> ((++) <$> getRemotes <*> getAll)
+ , getRemotes
+ )
+ where
+ getRemotes = do
+ rs <- remoteList
+ ts <- mapM (lookupTrust . uuid) rs
+ hereu <- getUUID
+ heretrust <- lookupTrust hereu
+ return $ (hereu, "here", heretrust) : zip3 (map uuid rs) (map name rs) ts
+ getAll = do
+ rs <- M.toList <$> uuidMap
+ rs3 <- forM rs $ \(u, n) -> (,,)
+ <$> pure u
+ <*> pure n
+ <*> lookupTrust u
+ return $ sortBy (comparing snd3) $
+ filter (\t -> thd3 t /= DeadTrusted) rs3
+
+startHeader :: [(UUID, RemoteName, TrustLevel)] -> CommandStart
+startHeader l = do
+ liftIO $ putStrLn $ header $ map (\(_, n, t) -> (n, t)) l
+ stop
+
+start :: [(UUID, RemoteName, TrustLevel)] -> FilePath -> (Key, Backend) -> CommandStart
+start l file (key, _) = do
+ ls <- S.fromList <$> keyLocations key
+ liftIO $ putStrLn $ format (map (\(u, _, t) -> (t, S.member u ls)) l) file
+ stop
+
+type Present = Bool
+
+header :: [(RemoteName, TrustLevel)] -> String
+header remotes = unlines (zipWith formatheader [0..] remotes) ++ pipes (length remotes)
+ where
+ formatheader n (remotename, trustlevel) = pipes n ++ remotename ++ trust trustlevel
+ pipes = flip replicate '|'
+ trust UnTrusted = " (untrusted)"
+ trust _ = ""
+
+format :: [(TrustLevel, Present)] -> FilePath -> String
+format remotes file = thereMap ++ " " ++ file
+ where
+ thereMap = concatMap there remotes
+ there (UnTrusted, True) = "x"
+ there (_, True) = "X"
+ there (_, False) = "_"
diff --git a/Command/Log.hs b/Command/Log.hs
index 2d4819f7f..f3a5becb8 100644
--- a/Command/Log.hs
+++ b/Command/Log.hs
@@ -17,7 +17,7 @@ import Data.Char
import Common.Annex
import Command
-import qualified Logs.Location
+import Logs
import qualified Logs.Presence
import Annex.CatFile
import qualified Annex.Branch
@@ -135,7 +135,7 @@ getLog :: Key -> [CommandParam] -> Annex [String]
getLog key os = do
top <- fromRepo Git.repoPath
p <- liftIO $ relPathCwdToFile top
- let logfile = p </> Logs.Location.logFile key
+ let logfile = p </> locationLogFile key
inRepo $ pipeNullSplitZombie $
[ Params "log -z --pretty=format:%ct --raw --abbrev=40"
, Param "--remove-empty"
diff --git a/Command/Map.hs b/Command/Map.hs
index c88520b07..91f4a0251 100644
--- a/Command/Map.hs
+++ b/Command/Map.hs
@@ -20,7 +20,7 @@ import qualified Annex
import Annex.UUID
import Logs.UUID
import Logs.Trust
-import Remote.Helper.Ssh
+import qualified Remote.Helper.Ssh as Ssh
import qualified Utility.Dot as Dot
-- a link from the first repository to the second (its remote)
@@ -74,7 +74,7 @@ drawMap rs umap ts = Dot.graph $ repos ++ trusted ++ others
hostname :: Git.Repo -> String
hostname r
- | Git.repoIsUrl r = Git.Url.host r
+ | Git.repoIsUrl r = fromMaybe (Git.repoLocation r) (Git.Url.host r)
| otherwise = "localhost"
basehostname :: Git.Repo -> String
@@ -203,9 +203,9 @@ tryScan r
where
p = proc cmd $ toCommand params
- configlist = onRemote r (pipedconfig, Nothing) "configlist" [] []
+ configlist = Ssh.onRemote r (pipedconfig, Nothing) "configlist" [] []
manualconfiglist = do
- sshparams <- sshToRepo r [Param sshcmd]
+ sshparams <- Ssh.toRepo r [Param sshcmd]
liftIO $ pipedconfig "ssh" sshparams
where
sshcmd = cddir ++ " && " ++
diff --git a/Command/Merge.hs b/Command/Merge.hs
index 659f14080..31db7a99f 100644
--- a/Command/Merge.hs
+++ b/Command/Merge.hs
@@ -11,7 +11,7 @@ import Common.Annex
import Command
import qualified Annex.Branch
import qualified Git.Branch
-import Command.Sync (mergeLocal)
+import Command.Sync (prepMerge, mergeLocal)
def :: [Command]
def = [command "merge" paramNothing seek SectionMaintenance
@@ -34,5 +34,5 @@ mergeBranch = do
mergeSynced :: CommandStart
mergeSynced = do
- branch <- inRepo Git.Branch.current
- maybe stop mergeLocal branch
+ prepMerge
+ mergeLocal =<< inRepo Git.Branch.current
diff --git a/Command/Mirror.hs b/Command/Mirror.hs
new file mode 100644
index 000000000..c0dd8a51f
--- /dev/null
+++ b/Command/Mirror.hs
@@ -0,0 +1,58 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Mirror where
+
+import Common.Annex
+import Command
+import GitAnnex.Options
+import qualified Command.Move
+import qualified Command.Drop
+import qualified Command.Get
+import qualified Remote
+import Annex.Content
+import qualified Annex
+
+def :: [Command]
+def = [withOptions fromToOptions $ command "mirror" paramPaths seek
+ SectionCommon "mirror content of files to/from another repository"]
+
+seek :: [CommandSeek]
+seek =
+ [ withField toOption Remote.byNameWithUUID $ \to ->
+ withField fromOption Remote.byNameWithUUID $ \from ->
+ withFilesInGit $ whenAnnexed $ start to from
+ ]
+
+start :: Maybe Remote -> Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart
+start to from file (key, _backend) = do
+ noAuto
+ case (from, to) of
+ (Nothing, Nothing) -> error "specify either --from or --to"
+ (Nothing, Just r) -> mirrorto r
+ (Just r, Nothing) -> mirrorfrom r
+ _ -> error "only one of --from or --to can be specified"
+ where
+ noAuto = whenM (Annex.getState Annex.auto) $
+ error "--auto is not supported for mirror"
+ mirrorto r = ifM (inAnnex key)
+ ( Command.Move.toStart r False (Just file) key
+ , do
+ numcopies <- numCopies file
+ Command.Drop.startRemote file numcopies key r
+ )
+ mirrorfrom r = do
+ haskey <- Remote.hasKey r key
+ case haskey of
+ Left _ -> stop
+ Right True -> Command.Get.start' (return True) Nothing key (Just file)
+ Right False -> ifM (inAnnex key)
+ ( do
+ numcopies <- numCopies file
+ Command.Drop.startLocal file numcopies key Nothing
+ , stop
+ )
diff --git a/Command/Move.hs b/Command/Move.hs
index 357ccc21e..dc501ae0f 100644
--- a/Command/Move.hs
+++ b/Command/Move.hs
@@ -14,7 +14,6 @@ import qualified Annex
import Annex.Content
import qualified Remote
import Annex.UUID
-import qualified Option
import Logs.Presence
import Logs.Transfer
import GitAnnex.Options
@@ -24,14 +23,8 @@ def :: [Command]
def = [withOptions moveOptions $ command "move" paramPaths seek
SectionCommon "move content of files to/from another repository"]
-fromOption :: Option
-fromOption = Option.field ['f'] "from" paramRemote "source remote"
-
-toOption :: Option
-toOption = Option.field ['t'] "to" paramRemote "destination remote"
-
moveOptions :: [Option]
-moveOptions = [fromOption, toOption] ++ keyOptions
+moveOptions = fromToOptions ++ keyOptions
seek :: [CommandSeek]
seek =
@@ -45,7 +38,7 @@ start :: Maybe Remote -> Maybe Remote -> Bool -> FilePath -> (Key, Backend) -> C
start to from move file (key, _) = start' to from move (Just file) key
startKey :: Maybe Remote -> Maybe Remote -> Bool -> Key -> CommandStart
-startKey to from move key = start' to from move Nothing key
+startKey to from move = start' to from move Nothing
start' :: Maybe Remote -> Maybe Remote -> Bool -> AssociatedFile -> Key -> CommandStart
start' to from move afile key = do
@@ -54,7 +47,7 @@ start' to from move afile key = do
(Nothing, Nothing) -> error "specify either --from or --to"
(Nothing, Just dest) -> toStart dest move afile key
(Just src, Nothing) -> fromStart src move afile key
- (_ , _) -> error "only one of --from or --to can be specified"
+ _ -> error "only one of --from or --to can be specified"
where
noAuto = when move $ whenM (Annex.getState Annex.auto) $ error
"--auto is not supported for move"
diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs
index 565344d25..f10ac628e 100644
--- a/Command/PreCommit.hs
+++ b/Command/PreCommit.hs
@@ -12,9 +12,11 @@ import Command
import qualified Command.Add
import qualified Command.Fix
import qualified Git.DiffTree
+import qualified Git.Ref
import Annex.CatFile
import Annex.Content.Direct
import Git.Sha
+import Git.FilePath
def :: [Command]
def = [command "pre-commit" paramPaths seek SectionPlumbing
@@ -23,7 +25,7 @@ def = [command "pre-commit" paramPaths seek SectionPlumbing
seek :: [CommandSeek]
seek =
-- fix symlinks to files being committed
- [ whenNotDirect $ withFilesToBeCommitted $ whenAnnexed $ Command.Fix.start
+ [ whenNotDirect $ withFilesToBeCommitted $ whenAnnexed Command.Fix.start
-- inject unlocked files into the annex
, whenNotDirect $ withFilesUnlockedToBeCommitted startIndirect
-- update direct mode mappings for committed files
@@ -38,16 +40,18 @@ startIndirect file = next $ do
startDirect :: [String] -> CommandStart
startDirect _ = next $ do
- (diffs, clean) <- inRepo $ Git.DiffTree.diffIndex
- forM_ diffs go
+ (diffs, clean) <- inRepo $ Git.DiffTree.diffIndex Git.Ref.headRef
+ makeabs <- flip fromTopFilePath <$> gitRepo
+ forM_ diffs (go makeabs)
next $ liftIO clean
where
- go diff = do
- withkey (Git.DiffTree.srcsha diff) removeAssociatedFile
- withkey (Git.DiffTree.dstsha diff) addAssociatedFile
+ go makeabs diff = do
+ withkey (Git.DiffTree.srcsha diff) (Git.DiffTree.srcmode diff) removeAssociatedFile
+ withkey (Git.DiffTree.dstsha diff) (Git.DiffTree.dstmode diff) addAssociatedFile
where
- withkey sha a = when (sha /= nullSha) $ do
- k <- catKey sha
+ withkey sha mode a = when (sha /= nullSha) $ do
+ k <- catKey sha mode
case k of
Nothing -> noop
- Just key -> void $ a key (Git.DiffTree.file diff)
+ Just key -> void $ a key $
+ makeabs $ Git.DiffTree.file diff
diff --git a/Command/ReKey.hs b/Command/ReKey.hs
index d7b277fa6..7448ba97e 100644
--- a/Command/ReKey.hs
+++ b/Command/ReKey.hs
@@ -66,6 +66,6 @@ cleanup file oldkey newkey = do
-- Update symlink to use the new key.
liftIO $ removeFile file
- Command.Add.addLink file newkey True
+ Command.Add.addLink file newkey Nothing
logStatus newkey InfoPresent
return True
diff --git a/Command/RecvKey.hs b/Command/RecvKey.hs
index c316e2ca5..3b2a8c496 100644
--- a/Command/RecvKey.hs
+++ b/Command/RecvKey.hs
@@ -32,7 +32,7 @@ seek = [withKeys start]
start :: Key -> CommandStart
start key = ifM (inAnnex key)
( error "key is already present in annex"
- , fieldTransfer Download key $ \_p -> do
+ , fieldTransfer Download key $ \_p ->
ifM (getViaTmp key go)
( do
-- forcibly quit after receiving one key,
@@ -72,7 +72,18 @@ start key = ifM (inAnnex key)
return $ size == size'
if oksize
then case Backend.maybeLookupBackendName (Types.Key.keyBackendName key) of
- Nothing -> return False
- Just backend -> maybe (return True) (\a -> a key tmp)
+ Nothing -> do
+ warning "recvkey: received key from direct mode repository using unknown backend; cannot check; discarding"
+ return False
+ Just backend -> maybe (return True) runfsck
(Types.Backend.fsckKey backend)
- else return False
+ else do
+ warning "recvkey: received key with wrong size; discarding"
+ return False
+ where
+ runfsck check = ifM (check key tmp)
+ ( return True
+ , do
+ warning "recvkey: received key from direct mode repository seems to have changed as it was transferred; discarding"
+ return False
+ )
diff --git a/Command/Reinject.hs b/Command/Reinject.hs
index 642f38947..e4abeef3c 100644
--- a/Command/Reinject.hs
+++ b/Command/Reinject.hs
@@ -34,7 +34,7 @@ start (src:dest:[])
start _ = error "specify a src file and a dest file"
perform :: FilePath -> FilePath -> (Key, Backend) -> CommandPerform
-perform src _dest (key, backend) = do
+perform src _dest (key, backend) =
{- Check the content before accepting it. -}
ifM (Command.Fsck.checkKeySizeOr reject key src
<&&> Command.Fsck.checkBackendOr reject backend key src)
diff --git a/Command/Repair.hs b/Command/Repair.hs
new file mode 100644
index 000000000..517e14afc
--- /dev/null
+++ b/Command/Repair.hs
@@ -0,0 +1,71 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Repair where
+
+import Common.Annex
+import Command
+import qualified Annex
+import qualified Git.Repair
+import qualified Annex.Branch
+import Git.Fsck (MissingObjects)
+import Git.Types
+import Annex.Version
+
+def :: [Command]
+def = [noCommit $ dontCheck repoExists $
+ command "repair" paramNothing seek SectionMaintenance "recover broken git repository"]
+
+seek :: [CommandSeek]
+seek = [withNothing start]
+
+start :: CommandStart
+start = next $ next $ runRepair =<< Annex.getState Annex.force
+
+runRepair :: Bool -> Annex Bool
+runRepair forced = do
+ (ok, stillmissing, modifiedbranches) <- inRepo $
+ Git.Repair.runRepair forced
+ -- This command can be run in git repos not using git-annex,
+ -- so avoid git annex branch stuff in that case.
+ whenM (isJust <$> getVersion) $
+ repairAnnexBranch stillmissing modifiedbranches
+ return ok
+
+{- After git repository repair, the .git/annex/index file could
+ - still be broken, by pointing to bad objects, or might just be corrupt on
+ - its own. Since this index file is not used to stage things
+ - for long durations of time, it can safely be deleted if it is broken.
+ -
+ - Otherwise, if the git-annex branch was modified by the repair,
+ - commit the index file to the git-annex branch.
+ - This way, if the git-annex branch got rewound to an old version by
+ - the repository repair, or was completely deleted, this will get it back
+ - to a good state. Note that in the unlikely case where the git-annex
+ - branch was rewound to a state that, had new changes from elsewhere not
+ - yet reflected in the index, this does properly merge those into the
+ - index before committing.
+ -}
+repairAnnexBranch :: MissingObjects -> [Branch] -> Annex ()
+repairAnnexBranch missing modifiedbranches
+ | Annex.Branch.fullname `elem` modifiedbranches = ifM okindex
+ ( commitindex
+ , do
+ nukeindex
+ liftIO $ putStrLn "Had to delete the .git/annex/index file as it was corrupt. Since the git-annex branch is not up-to-date anymore. It would be a very good idea to run: git annex fsck --fast"
+ )
+ | otherwise = ifM okindex
+ ( noop
+ , nukeindex
+ )
+ where
+ okindex = Annex.Branch.withIndex $
+ inRepo $ Git.Repair.checkIndex missing
+ commitindex = do
+ Annex.Branch.forceCommit "committing index after git repository repair"
+ liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index"
+ nukeindex = inRepo $ nukeFile . gitAnnexIndex
diff --git a/Command/Schedule.hs b/Command/Schedule.hs
new file mode 100644
index 000000000..35f144c75
--- /dev/null
+++ b/Command/Schedule.hs
@@ -0,0 +1,50 @@
+{- git-annex command
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Command.Schedule where
+
+import Common.Annex
+import Command
+import qualified Remote
+import Logs.Schedule
+import Types.ScheduledActivity
+
+import qualified Data.Set as S
+
+def :: [Command]
+def = [command "schedule" (paramPair paramRemote (paramOptional paramExpression)) seek
+ SectionSetup "get or set scheduled jobs"]
+
+seek :: [CommandSeek]
+seek = [withWords start]
+
+start :: [String] -> CommandStart
+start = parse
+ where
+ parse (name:[]) = go name performGet
+ parse (name:expr:[]) = go name $ \uuid -> do
+ showStart "schedile" name
+ performSet expr uuid
+ parse _ = error "Specify a repository."
+
+ go name a = do
+ u <- Remote.nameToUUID name
+ next $ a u
+
+performGet :: UUID -> CommandPerform
+performGet uuid = do
+ s <- scheduleGet uuid
+ liftIO $ putStrLn $ intercalate "; " $
+ map fromScheduledActivity $ S.toList s
+ next $ return True
+
+performSet :: String -> UUID -> CommandPerform
+performSet expr uuid = case parseScheduledActivities expr of
+ Left e -> error $ "Parse error: " ++ e
+ Right l -> do
+ scheduleSet uuid l
+ next $ return True
diff --git a/Command/SendKey.hs b/Command/SendKey.hs
index afd1ac1e0..039a3d7ca 100644
--- a/Command/SendKey.hs
+++ b/Command/SendKey.hs
@@ -46,6 +46,6 @@ fieldTransfer direction key a = do
ok <- maybe (a $ const noop)
(\u -> runTransfer (Transfer direction (toUUID u) key) afile noRetry a)
=<< Fields.getField Fields.remoteUUID
- if ok
- then liftIO exitSuccess
- else liftIO exitFailure
+ liftIO $ if ok
+ then exitSuccess
+ else exitFailure
diff --git a/Command/Status.hs b/Command/Status.hs
index af85fcc2a..5dc625994 100644
--- a/Command/Status.hs
+++ b/Command/Status.hs
@@ -1,345 +1,89 @@
{- git-annex command
-
- - Copyright 2011 Joey Hess <joey@kitenet.net>
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE BangPatterns #-}
-
module Command.Status where
-import "mtl" Control.Monad.State.Strict
-import qualified Data.Map as M
-import Text.JSON
-import Data.Tuple
-import System.PosixCompat.Files
-
import Common.Annex
-import qualified Types.Backend as B
-import qualified Types.Remote as R
-import qualified Remote
-import qualified Command.Unused
-import qualified Git
-import qualified Annex
import Command
-import Utility.DataUnits
-import Utility.DiskFree
-import Annex.Content
-import Types.Key
-import Backend
-import Logs.UUID
-import Logs.Trust
-import Remote
+import Annex.CatFile
+import Annex.Content.Direct
import Config
-import Utility.Percentage
-import Logs.Transfer
-import Types.TrustLevel
-import Types.FileMatcher
-import qualified Limit
-
--- a named computation that produces a statistic
-type Stat = StatState (Maybe (String, StatState String))
-
--- data about a set of keys
-data KeyData = KeyData
- { countKeys :: Integer
- , sizeKeys :: Integer
- , unknownSizeKeys :: Integer
- , backendsKeys :: M.Map String Integer
- }
-
--- cached info that multiple Stats use
-data StatInfo = StatInfo
- { presentData :: Maybe KeyData
- , referencedData :: Maybe KeyData
- }
-
--- a state monad for running Stats in
-type StatState = StateT StatInfo Annex
+import qualified Git.LsFiles as LsFiles
+import qualified Git.Ref
+import qualified Git
def :: [Command]
-def = [command "status" paramPaths seek
- SectionQuery "shows status information about the annex"]
+def = [notBareRepo $ noCommit $ noMessages $
+ command "status" paramPaths seek SectionCommon
+ "show the working tree status"]
seek :: [CommandSeek]
-seek = [withWords start]
+seek =
+ [ withWords start
+ ]
start :: [FilePath] -> CommandStart
start [] = do
- globalStatus
- stop
-start ps = do
- mapM_ localStatus =<< filterM isdir ps
- stop
- where
- isdir = liftIO . catchBoolIO . (isDirectory <$$> getFileStatus)
-
-globalStatus :: Annex ()
-globalStatus = do
- fast <- Annex.getState Annex.fast
- let stats = if fast
- then global_fast_stats
- else global_fast_stats ++ global_slow_stats
- showCustom "status" $ do
- evalStateT (mapM_ showStat stats) (StatInfo Nothing Nothing)
- return True
-
-localStatus :: FilePath -> Annex ()
-localStatus dir = showCustom (unwords ["status", dir]) $ do
- let stats = map (\s -> s dir) local_stats
- evalStateT (mapM_ showStat stats) =<< getLocalStatInfo dir
- return True
-
-{- Order is significant. Less expensive operations, and operations
- - that share data go together.
- -}
-global_fast_stats :: [Stat]
-global_fast_stats =
- [ supported_backends
- , supported_remote_types
- , repository_mode
- , remote_list Trusted
- , remote_list SemiTrusted
- , remote_list UnTrusted
- , transfer_list
- , disk_size
- ]
-global_slow_stats :: [Stat]
-global_slow_stats =
- [ tmp_size
- , bad_data_size
- , local_annex_keys
- , local_annex_size
- , known_annex_keys
- , known_annex_size
- , bloom_info
- , backend_usage
- ]
-local_stats :: [FilePath -> Stat]
-local_stats =
- [ local_dir
- , const local_annex_keys
- , const local_annex_size
- , const known_annex_keys
- , const known_annex_size
- ]
-
-stat :: String -> (String -> StatState String) -> Stat
-stat desc a = return $ Just (desc, a desc)
-
-nostat :: Stat
-nostat = return Nothing
-
-json :: JSON j => (j -> String) -> StatState j -> String -> StatState String
-json serialize a desc = do
- j <- a
- lift $ maybeShowJSON [(desc, j)]
- return $ serialize j
-
-nojson :: StatState String -> String -> StatState String
-nojson a _ = a
-
-showStat :: Stat -> StatState ()
-showStat s = maybe noop calc =<< s
- where
- calc (desc, a) = do
- (lift . showHeader) desc
- lift . showRaw =<< a
-
-supported_backends :: Stat
-supported_backends = stat "supported backends" $ json unwords $
- return $ map B.name Backend.list
-
-supported_remote_types :: Stat
-supported_remote_types = stat "supported remote types" $ json unwords $
- return $ map R.typename Remote.remoteTypes
-
-repository_mode :: Stat
-repository_mode = stat "repository mode" $ json id $ lift $
- ifM isDirect
- ( return "direct", return "indirect" )
-
-remote_list :: TrustLevel -> Stat
-remote_list level = stat n $ nojson $ lift $ do
- us <- M.keys <$> (M.union <$> uuidMap <*> remoteMap Remote.name)
- rs <- fst <$> trustPartition level us
- s <- prettyPrintUUIDs n rs
- return $ if null s then "0" else show (length rs) ++ "\n" ++ beginning s
- where
- n = showTrustLevel level ++ " repositories"
+ -- Like git status, when run without a directory, behave as if
+ -- given the path to the top of the repository.
+ cwd <- liftIO getCurrentDirectory
+ top <- fromRepo Git.repoPath
+ next $ perform [relPathDirToFile cwd top]
+start locs = next $ perform locs
-local_dir :: FilePath -> Stat
-local_dir dir = stat "directory" $ json id $ return dir
-
-local_annex_size :: Stat
-local_annex_size = stat "local annex size" $ json id $
- showSizeKeys <$> cachedPresentData
-
-local_annex_keys :: Stat
-local_annex_keys = stat "local annex keys" $ json show $
- countKeys <$> cachedPresentData
-
-known_annex_size :: Stat
-known_annex_size = stat "known annex size" $ json id $
- showSizeKeys <$> cachedReferencedData
-
-known_annex_keys :: Stat
-known_annex_keys = stat "known annex keys" $ json show $
- countKeys <$> cachedReferencedData
-
-tmp_size :: Stat
-tmp_size = staleSize "temporary directory size" gitAnnexTmpDir
-
-bad_data_size :: Stat
-bad_data_size = staleSize "bad keys size" gitAnnexBadDir
-
-bloom_info :: Stat
-bloom_info = stat "bloom filter size" $ json id $ do
- localkeys <- countKeys <$> cachedPresentData
- capacity <- fromIntegral <$> lift Command.Unused.bloomCapacity
- let note = aside $
- if localkeys >= capacity
- then "appears too small for this repository; adjust annex.bloomcapacity"
- else showPercentage 1 (percentage capacity localkeys) ++ " full"
-
- -- Two bloom filters are used at the same time, so double the size
- -- of one.
- size <- roughSize memoryUnits False . (* 2) . fromIntegral . fst <$>
- lift Command.Unused.bloomBitsHashes
-
- return $ size ++ note
-
-transfer_list :: Stat
-transfer_list = stat "transfers in progress" $ nojson $ lift $ do
- uuidmap <- Remote.remoteMap id
- ts <- getTransfers
- if null ts
- then return "none"
- else return $ multiLine $
- map (\(t, i) -> line uuidmap t i) $ sort ts
- where
- line uuidmap t i = unwords
- [ showLcDirection (transferDirection t) ++ "ing"
- , fromMaybe (key2file $ transferKey t) (associatedFile i)
- , if transferDirection t == Upload then "to" else "from"
- , maybe (fromUUID $ transferUUID t) Remote.name $
- M.lookup (transferUUID t) uuidmap
- ]
-
-disk_size :: Stat
-disk_size = stat "available local disk space" $ json id $ lift $
- calcfree
- <$> (annexDiskReserve <$> Annex.getGitConfig)
- <*> inRepo (getDiskFree . gitAnnexDir)
- where
- calcfree reserve (Just have) = unwords
- [ roughSize storageUnits False $ nonneg $ have - reserve
- , "(+" ++ roughSize storageUnits False reserve
- , "reserved)"
- ]
- calcfree _ _ = "unknown"
-
- nonneg x
- | x >= 0 = x
- | otherwise = 0
-
-backend_usage :: Stat
-backend_usage = stat "backend usage" $ nojson $
- calc
- <$> (backendsKeys <$> cachedReferencedData)
- <*> (backendsKeys <$> cachedPresentData)
- where
- calc x y = multiLine $
- map (\(n, b) -> b ++ ": " ++ show n) $
- reverse $ sort $ map swap $ M.toList $
- M.unionWith (+) x y
-
-cachedPresentData :: StatState KeyData
-cachedPresentData = do
- s <- get
- case presentData s of
- Just v -> return v
- Nothing -> do
- v <- foldKeys <$> lift getKeysPresent
- put s { presentData = Just v }
- return v
-
-cachedReferencedData :: StatState KeyData
-cachedReferencedData = do
- s <- get
- case referencedData s of
- Just v -> return v
- Nothing -> do
- !v <- lift $ Command.Unused.withKeysReferenced
- emptyKeyData addKey
- put s { referencedData = Just v }
- return v
-
-getLocalStatInfo :: FilePath -> Annex StatInfo
-getLocalStatInfo dir = do
- matcher <- Limit.getMatcher
- (presentdata, referenceddata) <-
- Command.Unused.withKeysFilesReferencedIn dir initial
- (update matcher)
- return $ StatInfo (Just presentdata) (Just referenceddata)
- where
- initial = (emptyKeyData, emptyKeyData)
- update matcher key file vs@(presentdata, referenceddata) =
- ifM (matcher $ FileInfo file file)
- ( (,)
- <$> ifM (inAnnex key)
- ( return $ addKey key presentdata
- , return presentdata
- )
- <*> pure (addKey key referenceddata)
- , return vs
- )
-
-emptyKeyData :: KeyData
-emptyKeyData = KeyData 0 0 0 M.empty
-
-foldKeys :: [Key] -> KeyData
-foldKeys = foldl' (flip addKey) emptyKeyData
-
-addKey :: Key -> KeyData -> KeyData
-addKey key (KeyData count size unknownsize backends) =
- KeyData count' size' unknownsize' backends'
- where
- {- All calculations strict to avoid thunks when repeatedly
- - applied to many keys. -}
- !count' = count + 1
- !backends' = M.insertWith' (+) (keyBackendName key) 1 backends
- !size' = maybe size (+ size) ks
- !unknownsize' = maybe (unknownsize + 1) (const unknownsize) ks
- ks = keySize key
-
-showSizeKeys :: KeyData -> String
-showSizeKeys d = total ++ missingnote
+perform :: [FilePath] -> CommandPerform
+perform locs = do
+ (l, cleanup) <- inRepo $ LsFiles.modifiedOthers locs
+ getstatus <- ifM isDirect
+ ( return statusDirect
+ , return $ Just <$$> statusIndirect
+ )
+ forM_ l $ \f -> maybe noop (showFileStatus f) =<< getstatus f
+ void $ liftIO cleanup
+ next $ return True
+
+data Status
+ = NewFile
+ | DeletedFile
+ | ModifiedFile
+
+showStatus :: Status -> String
+showStatus NewFile = "?"
+showStatus DeletedFile = "D"
+showStatus ModifiedFile = "M"
+
+showFileStatus :: FilePath -> Status -> Annex ()
+showFileStatus f s = liftIO $ putStrLn $ showStatus s ++ " " ++ f
+
+statusDirect :: FilePath -> Annex (Maybe Status)
+statusDirect f = checkstatus =<< liftIO (catchMaybeIO $ getFileStatus f)
where
- total = roughSize storageUnits False $ sizeKeys d
- missingnote
- | unknownSizeKeys d == 0 = ""
- | otherwise = aside $
- "+ " ++ show (unknownSizeKeys d) ++
- " keys of unknown size"
-
-staleSize :: String -> (Git.Repo -> FilePath) -> Stat
-staleSize label dirspec = go =<< lift (Command.Unused.staleKeys dirspec)
+ checkstatus Nothing = return $ Just DeletedFile
+ checkstatus (Just s)
+ -- Git thinks that present direct mode files modifed,
+ -- so have to check.
+ | not (isSymbolicLink s) = checkkey s =<< catKeyFile f
+ | otherwise = Just <$> checkNew f
+
+ checkkey s (Just k) = ifM (sameFileStatus k s)
+ ( return Nothing
+ , return $ Just ModifiedFile
+ )
+ checkkey _ Nothing = Just <$> checkNew f
+
+statusIndirect :: FilePath -> Annex Status
+statusIndirect f = ifM (liftIO $ isJust <$> catchMaybeIO (getFileStatus f))
+ ( checkNew f
+ , return DeletedFile
+ )
where
- go [] = nostat
- go keys = onsize =<< sum <$> keysizes keys
- onsize 0 = nostat
- onsize size = stat label $
- json (++ aside "clean up with git-annex unused") $
- return $ roughSize storageUnits False size
- keysizes keys = map (fromIntegral . fileSize) <$> stats keys
- stats keys = do
- dir <- lift $ fromRepo dirspec
- liftIO $ forM keys $ \k -> getFileStatus (dir </> keyFile k)
-
-aside :: String -> String
-aside s = " (" ++ s ++ ")"
-multiLine :: [String] -> String
-multiLine = concatMap (\l -> "\n\t" ++ l)
+checkNew :: FilePath -> Annex Status
+checkNew f = ifM (isJust <$> catObjectDetails (Git.Ref.fileRef f))
+ ( return ModifiedFile
+ , return NewFile
+ )
diff --git a/Command/Sync.hs b/Command/Sync.hs
index a6ae610f8..c41f46f8a 100644
--- a/Command/Sync.hs
+++ b/Command/Sync.hs
@@ -29,8 +29,11 @@ import qualified Remote.Git
import Types.Key
import Config
import Annex.ReplaceFile
+import Git.FileMode
+import qualified Data.Set as S
import Data.Hash.MD5
+import Control.Concurrent.MVar
def :: [Command]
def = [command "sync" (paramOptional (paramRepeating paramRemote))
@@ -39,24 +42,43 @@ def = [command "sync" (paramOptional (paramRepeating paramRemote))
-- syncing involves several operations, any of which can independently fail
seek :: CommandSeek
seek rs = do
- branch <- fromMaybe nobranch <$> inRepo Git.Branch.current
+ prepMerge
+
+ -- There may not be a branch checked out until after the commit,
+ -- or perhaps after it gets merged from the remote.
+ -- So only look it up once it's needed, and if once there is a
+ -- branch, cache it.
+ mvar <- liftIO newEmptyMVar
+ let getbranch = ifM (liftIO $ isEmptyMVar mvar)
+ ( do
+ branch <- inRepo Git.Branch.current
+ when (isJust branch) $
+ liftIO $ putMVar mvar branch
+ return branch
+ , liftIO $ readMVar mvar
+ )
+ let withbranch a = a =<< getbranch
+
remotes <- syncRemotes rs
return $ concat
[ [ commit ]
- , [ mergeLocal branch ]
- , [ pullRemote remote branch | remote <- remotes ]
+ , [ withbranch mergeLocal ]
+ , [ withbranch (pullRemote remote) | remote <- remotes ]
, [ mergeAnnex ]
- , [ pushLocal branch ]
- , [ pushRemote remote branch | remote <- remotes ]
+ , [ withbranch pushLocal ]
+ , [ withbranch (pushRemote remote) | remote <- remotes ]
]
- where
- nobranch = error "no branch is checked out"
+
+{- Merging may delete the current directory, so go to the top
+ - of the repo. -}
+prepMerge :: Annex ()
+prepMerge = liftIO . setCurrentDirectory =<< fromRepo Git.repoPath
syncBranch :: Git.Ref -> Git.Ref
-syncBranch = Git.Ref.under "refs/heads/synced/"
+syncBranch = Git.Ref.under "refs/heads/synced" . fromDirectBranch
remoteBranch :: Remote -> Git.Ref -> Git.Ref
-remoteBranch remote = Git.Ref.under $ "refs/remotes/" ++ Remote.name remote
+remoteBranch remote = Git.Ref.underBase $ "refs/remotes/" ++ Remote.name remote
syncRemotes :: [String] -> Annex [Remote]
syncRemotes rs = ifM (Annex.getState Annex.fast) ( nub <$> pickfast , wanted )
@@ -67,52 +89,62 @@ syncRemotes rs = ifM (Annex.getState Annex.fast) ( nub <$> pickfast , wanted )
| otherwise = listed
listed = do
l <- catMaybes <$> mapM (Remote.byName . Just) rs
- let s = filter Remote.specialRemote l
+ let s = filter (not . Remote.syncableRemote) l
unless (null s) $
error $ "cannot sync special remotes: " ++
unwords (map Types.Remote.name s)
return l
- available = filter (not . Remote.specialRemote)
+ available = filter Remote.syncableRemote
. filter (remoteAnnexSync . Types.Remote.gitconfig)
<$> Remote.remoteList
good = filterM $ Remote.Git.repoAvail . Types.Remote.repo
fastest = fromMaybe [] . headMaybe . Remote.byCost
commit :: CommandStart
-commit = next $ next $ do
- ifM isDirect
- ( do
- void $ stageDirect
- runcommit []
- , runcommit [Param "-a"]
- )
+commit = next $ next $ ifM isDirect
+ ( do
+ void stageDirect
+ runcommit []
+ , runcommit [Param "-a"]
+ )
where
runcommit ps = do
showStart "commit" ""
showOutput
Annex.Branch.commit "update"
-- Commit will fail when the tree is clean, so ignore failure.
- let params = (Param "commit") : ps ++
+ let params = Param "commit" : ps ++
[Param "-m", Param "git-annex automatic sync"]
_ <- inRepo $ tryIO . Git.Command.runQuiet params
return True
-mergeLocal :: Git.Ref -> CommandStart
-mergeLocal branch = go =<< needmerge
+mergeLocal :: Maybe Git.Ref -> CommandStart
+mergeLocal Nothing = stop
+mergeLocal (Just branch) = go =<< needmerge
where
syncbranch = syncBranch branch
- needmerge = do
- unlessM (inRepo $ Git.Ref.exists syncbranch) $
- inRepo $ updateBranch syncbranch
- inRepo $ Git.Branch.changed branch syncbranch
+ needmerge = ifM isBareRepo
+ ( return False
+ , do
+ unlessM (inRepo $ Git.Ref.exists syncbranch) $
+ inRepo $ updateBranch syncbranch
+ inRepo $ Git.Branch.changed branch syncbranch
+ )
go False = stop
go True = do
showStart "merge" $ Git.Ref.describe syncbranch
next $ next $ mergeFrom syncbranch
-pushLocal :: Git.Ref -> CommandStart
-pushLocal branch = do
+pushLocal :: Maybe Git.Ref -> CommandStart
+pushLocal Nothing = stop
+pushLocal (Just branch) = do
+ -- Update the sync branch to match the new state of the branch
inRepo $ updateBranch $ syncBranch branch
+ -- In direct mode, we're operating on some special direct mode
+ -- branch, rather than the intended branch, so update the indended
+ -- branch.
+ whenM isDirect $
+ inRepo $ updateBranch $ fromDirectBranch branch
stop
updateBranch :: Git.Ref -> Git.Repo -> IO ()
@@ -125,13 +157,13 @@ updateBranch syncbranch g =
, Param $ show $ Git.Ref.base syncbranch
] g
-pullRemote :: Remote -> Git.Ref -> CommandStart
+pullRemote :: Remote -> Maybe Git.Ref -> CommandStart
pullRemote remote branch = do
showStart "pull" (Remote.name remote)
next $ do
showOutput
stopUnless fetch $
- next $ mergeRemote remote (Just branch)
+ next $ mergeRemote remote branch
where
fetch = inRepo $ Git.Command.runBool
[Param "fetch", Param $ Remote.name remote]
@@ -141,20 +173,21 @@ pullRemote remote branch = do
- were committed (or pushed changes, if this is a bare remote),
- while the synced/master may have changes that some
- other remote synced to this remote. So, merge them both. -}
-mergeRemote :: Remote -> (Maybe Git.Ref) -> CommandCleanup
+mergeRemote :: Remote -> Maybe Git.Ref -> CommandCleanup
mergeRemote remote b = case b of
Nothing -> do
branch <- inRepo Git.Branch.currentUnsafe
- all id <$> (mapM merge $ branchlist branch)
- Just _ -> all id <$> (mapM merge =<< tomerge (branchlist b))
+ and <$> mapM merge (branchlist branch)
+ Just _ -> and <$> (mapM merge =<< tomerge (branchlist b))
where
merge = mergeFrom . remoteBranch remote
tomerge branches = filterM (changed remote) branches
branchlist Nothing = []
branchlist (Just branch) = [branch, syncBranch branch]
-pushRemote :: Remote -> Git.Ref -> CommandStart
-pushRemote remote branch = go =<< needpush
+pushRemote :: Remote -> Maybe Git.Ref -> CommandStart
+pushRemote _remote Nothing = stop
+pushRemote remote (Just branch) = go =<< needpush
where
needpush = anyM (newer remote) [syncBranch branch, Annex.Branch.name]
go False = stop
@@ -162,31 +195,54 @@ pushRemote remote branch = go =<< needpush
showStart "push" (Remote.name remote)
next $ next $ do
showOutput
- inRepo $ pushBranch remote branch
+ ok <- inRepo $ pushBranch remote branch
+ unless ok $ do
+ warning $ unwords [ "Pushing to " ++ Remote.name remote ++ " failed." ]
+ showLongNote "(non-fast-forward problems can be solved by setting receive.denyNonFastforwards to false in the remote's git config)"
+ return ok
-{- If the remote is a bare git repository, it's best to push the branch
- - directly to it. On the other hand, if it's not bare, pushing to the
- - checked out branch will fail, and this is why we use the syncBranch.
+{- Pushes a regular branch like master to a remote. Also pushes the git-annex
+ - branch.
+ -
+ - If the remote is a bare git repository, it's best to push the regular
+ - branch directly to it, so that cloning/pulling will get it.
+ - On the other hand, if it's not bare, pushing to the checked out branch
+ - will fail, and this is why we push to its syncBranch.
-
- Git offers no way to tell if a remote is bare or not, so both methods
- are tried.
-
- The direct push is likely to spew an ugly error message, so stderr is
- - elided. Since progress is output to stderr too, the sync push is done
- - first, and actually sends the data. Then the direct push is tried,
- - with stderr discarded, to update the branch ref on the remote.
+ - elided. Since git progress display goes to stderr too, the sync push
+ - is done first, and actually sends the data. Then the direct push is
+ - tried, with stderr discarded, to update the branch ref on the remote.
+ -
+ - The sync push forces the update of the remote synced/git-annex branch.
+ - This is necessary if a transition has rewritten the git-annex branch.
+ - Normally any changes to the git-annex branch get pulled and merged before
+ - this push, so this forcing is unlikely to overwrite new data pushed
+ - in from another repository that is also syncing.
+ -
+ - But overwriting of data on synced/git-annex can happen, in a race.
+ - The only difference caused by using a forced push in that case is that
+ - the last repository to push wins the race, rather than the first to push.
+ -
+ - The sync push will fail to overwrite if receive.denyNonFastforwards is
+ - set on the remote.
-}
pushBranch :: Remote -> Git.Ref -> Git.Repo -> IO Bool
-pushBranch remote branch g = tryIO directpush `after` syncpush
+pushBranch remote branch g = tryIO (directpush g) `after` syncpush g
where
- syncpush = Git.Command.runBool (pushparams (refspec branch)) g
- directpush = Git.Command.runQuiet (pushparams (show $ Git.Ref.base branch)) g
- pushparams b =
+ syncpush = Git.Command.runBool $ pushparams
+ [ Git.Branch.forcePush $ refspec Annex.Branch.name
+ , refspec branch
+ ]
+ directpush = Git.Command.runQuiet $ pushparams
+ [show $ Git.Ref.base $ fromDirectBranch branch]
+ pushparams branches =
[ Param "push"
, Param $ Remote.name remote
- , Param $ refspec Annex.Branch.name
- , Param b
- ]
+ ] ++ map Param branches
refspec b = concat
[ show $ Git.Ref.base b
, ":"
@@ -195,7 +251,7 @@ pushBranch remote branch g = tryIO directpush `after` syncpush
mergeAnnex :: CommandStart
mergeAnnex = do
- void $ Annex.Branch.forceUpdate
+ void Annex.Branch.forceUpdate
stop
{- Merges from a branch into the current branch. -}
@@ -218,7 +274,7 @@ mergeFrom branch = do
mergeDirectCleanup d oldsha newsha
_ -> noop
return r
- runmerge a = ifM (a)
+ runmerge a = ifM a
( return True
, resolveMerge
)
@@ -232,72 +288,122 @@ mergeFrom branch = do
-
- This uses the Keys pointed to by the files to construct new
- filenames. So when both sides modified file foo,
- - it will be deleted, and replaced with files foo.KEYA and foo.KEYB.
+ - it will be deleted, and replaced with files foo.variant-A and
+ - foo.variant-B.
-
- On the other hand, when one side deleted foo, and the other modified it,
- it will be deleted, and the modified version stored as file
- - foo.KEYA (or KEYB).
+ - foo.variant-A (or B).
+ -
+ - It's also possible that one side has foo as an annexed file, and
+ - the other as a directory or non-annexed file. The annexed file
+ - is renamed to resolve the merge, and the other object is preserved as-is.
-}
resolveMerge :: Annex Bool
resolveMerge = do
top <- fromRepo Git.repoPath
(fs, cleanup) <- inRepo (LsFiles.unmerged [top])
- merged <- all id <$> mapM resolveMerge' fs
+ mergedfs <- catMaybes <$> mapM resolveMerge' fs
+ let merged = not (null mergedfs)
void $ liftIO cleanup
(deleted, cleanup2) <- inRepo (LsFiles.deleted [top])
unless (null deleted) $
Annex.Queue.addCommand "rm" [Params "--quiet -f --"] deleted
void $ liftIO cleanup2
-
+
when merged $ do
+ unlessM isDirect $
+ cleanConflictCruft mergedfs top
Annex.Queue.flush
void $ inRepo $ Git.Command.runBool
[ Param "commit"
, Param "-m"
, Param "git-annex automatic merge conflict fix"
]
+ showLongNote "Merge conflict was automatically resolved; you may want to examine the result."
return merged
-resolveMerge' :: LsFiles.Unmerged -> Annex Bool
+resolveMerge' :: LsFiles.Unmerged -> Annex (Maybe FilePath)
resolveMerge' u
- | issymlink LsFiles.valUs && issymlink LsFiles.valThem =
- withKey LsFiles.valUs $ \keyUs ->
- withKey LsFiles.valThem $ \keyThem -> do
+ | issymlink LsFiles.valUs && issymlink LsFiles.valThem = do
+ kus <- getKey LsFiles.valUs
+ kthem <- getKey LsFiles.valThem
+ case (kus, kthem) of
+ -- Both sides of conflict are annexed files
+ (Just keyUs, Just keyThem) -> do
+ removeoldfile keyUs
+ if keyUs == keyThem
+ then makelink keyUs
+ else do
+ makelink keyUs
+ makelink keyThem
+ return $ Just file
+ -- Our side is annexed, other side is not.
+ (Just keyUs, Nothing) -> do
ifM isDirect
- ( maybe noop (\k -> removeDirect k file) keyUs
- , liftIO $ nukeFile file
+ -- Move newly added non-annexed object
+ -- out of direct mode merge directory.
+ ( do
+ removeoldfile keyUs
+ makelink keyUs
+ d <- fromRepo gitAnnexMergeDir
+ liftIO $ rename (d </> file) file
+ -- cleaup tree after git merge
+ , do
+ unstageoldfile
+ makelink keyUs
)
- Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file]
- go keyUs keyThem
- | otherwise = return False
+ return $ Just file
+ -- Our side is not annexed, other side is.
+ (Nothing, Just keyThem) -> do
+ makelink keyThem
+ unstageoldfile
+ return $ Just file
+ -- Neither side is annexed; cannot resolve.
+ (Nothing, Nothing) -> return Nothing
+ | otherwise = return Nothing
where
- go keyUs keyThem
- | keyUs == keyThem = do
- makelink keyUs
- return True
- | otherwise = do
- makelink keyUs
- makelink keyThem
- return True
file = LsFiles.unmergedFile u
- issymlink select = any (select (LsFiles.unmergedBlobType u) ==)
- [Just SymlinkBlob, Nothing]
- makelink (Just key) = do
+ issymlink select = select (LsFiles.unmergedBlobType u) `elem` [Just SymlinkBlob, Nothing]
+ makelink key = do
let dest = mergeFile file key
l <- inRepo $ gitAnnexLink dest key
replaceFile dest $ makeAnnexLink l
stageSymlink dest =<< hashSymlink l
- whenM (isDirect) $
+ whenM isDirect $
toDirect key dest
- makelink _ = noop
- withKey select a = do
- let msha = select $ LsFiles.unmergedSha u
- case msha of
- Nothing -> a Nothing
- Just sha -> do
- key <- catKey sha
- maybe (return False) (a . Just) key
+ removeoldfile keyUs = do
+ ifM isDirect
+ ( removeDirect keyUs file
+ , liftIO $ nukeFile file
+ )
+ Annex.Queue.addCommand "rm" [Params "--quiet -f --"] [file]
+ unstageoldfile = Annex.Queue.addCommand "rm" [Params "--quiet -f --cached --"] [file]
+ getKey select = case select (LsFiles.unmergedSha u) of
+ Nothing -> return Nothing
+ Just sha -> catKey sha symLinkMode
+
+{- git-merge moves conflicting files away to files
+ - named something like f~HEAD or f~branch, but the
+ - exact name chosen can vary. Once the conflict is resolved,
+ - this cruft can be deleted. To avoid deleting legitimate
+ - files that look like this, only delete files that are
+ - A) not staged in git and B) look like git-annex symlinks.
+ -}
+cleanConflictCruft :: [FilePath] -> FilePath -> Annex ()
+cleanConflictCruft resolvedfs top = do
+ (fs, cleanup) <- inRepo $ LsFiles.notInRepo False [top]
+ mapM_ clean fs
+ void $ liftIO cleanup
+ where
+ clean f
+ | matchesresolved f = whenM (isJust <$> isAnnexLink f) $
+ liftIO $ nukeFile f
+ | otherwise = noop
+ s = S.fromList resolvedfs
+ matchesresolved f = S.member (base f) s
+ base f = reverse $ drop 1 $ dropWhile (/= '~') $ reverse f
{- The filename to use when resolving a conflicted merge of a file,
- that points to a key.
diff --git a/Command/TransferInfo.hs b/Command/TransferInfo.hs
index 4bebdebcd..93f6c7077 100644
--- a/Command/TransferInfo.hs
+++ b/Command/TransferInfo.hs
@@ -36,7 +36,7 @@ seek = [withWords start]
-}
start :: [String] -> CommandStart
start (k:[]) = do
- case (file2key k) of
+ case file2key k of
Nothing -> error "bad key"
(Just key) -> whenM (inAnnex key) $ do
file <- Fields.getField Fields.associatedFile
diff --git a/Command/TransferKey.hs b/Command/TransferKey.hs
index 849cbc12b..3270ad8f7 100644
--- a/Command/TransferKey.hs
+++ b/Command/TransferKey.hs
@@ -15,23 +15,23 @@ import Logs.Location
import Logs.Transfer
import qualified Remote
import Types.Remote
-import qualified Command.Move
+import GitAnnex.Options
import qualified Option
def :: [Command]
-def = [withOptions options $
+def = [withOptions transferKeyOptions $
noCommit $ command "transferkey" paramKey seek SectionPlumbing
"transfers a key from or to a remote"]
-options :: [Option]
-options = [fileOption, Command.Move.fromOption, Command.Move.toOption]
+transferKeyOptions :: [Option]
+transferKeyOptions = fileOption : fromToOptions
fileOption :: Option
fileOption = Option.field [] "file" paramFile "the associated file"
seek :: [CommandSeek]
-seek = [withField Command.Move.toOption Remote.byNameWithUUID $ \to ->
- withField Command.Move.fromOption Remote.byNameWithUUID $ \from ->
+seek = [withField toOption Remote.byNameWithUUID $ \to ->
+ withField fromOption Remote.byNameWithUUID $ \from ->
withField fileOption return $ \file ->
withKeys $ start to from file]
diff --git a/Command/TransferKeys.hs b/Command/TransferKeys.hs
index 8da29e211..5ac9454aa 100644
--- a/Command/TransferKeys.hs
+++ b/Command/TransferKeys.hs
@@ -41,7 +41,7 @@ seek = [withField readFdOption convertFd $ \readh ->
convertFd :: Maybe String -> Annex (Maybe Handle)
convertFd Nothing = return Nothing
-convertFd (Just s) = liftIO $ do
+convertFd (Just s) = liftIO $
case readish s of
Nothing -> error "bad fd"
Just fd -> Just <$> fdToHandle fd
diff --git a/Command/Unannex.hs b/Command/Unannex.hs
index fbeaffa52..5e3c4279a 100644
--- a/Command/Unannex.hs
+++ b/Command/Unannex.hs
@@ -13,11 +13,11 @@ import Common.Annex
import Command
import Config
import qualified Annex
-import Logs.Location
import Annex.Content
import Annex.Content.Direct
import qualified Git.Command
import qualified Git.LsFiles as LsFiles
+import Utility.CopyFile
def :: [Command]
def = [command "unannex" paramPaths seek SectionUtility
@@ -46,7 +46,7 @@ performIndirect file key = do
-- 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]
- when (not $ null s) $
+ unless (null s) $
inRepo $ Git.Command.run
[ Param "commit"
, Param "-q"
@@ -60,28 +60,24 @@ performIndirect file key = do
cleanupIndirect :: FilePath -> Key -> CommandCleanup
cleanupIndirect file key = do
+ src <- calcRepo $ gitAnnexLocation key
ifM (Annex.getState Annex.fast)
- ( goFast
- , go
+ ( hardlinkfrom src
+ , copyfrom src
)
- return True
where
-#ifdef mingw32_HOST_OS
- goFast = go
-#else
- goFast = do
- -- fast mode: hard link to content in annex
- src <- calcRepo $ gitAnnexLocation key
- -- creating a hard link could fall; fall back to non fast mode
+ copyfrom src =
+ thawContent file `after` liftIO (copyFileExternal src file)
+ hardlinkfrom src =
+#ifndef mingw32_HOST_OS
+ -- creating a hard link could fall; fall back to copying
ifM (liftIO $ catchBoolIO $ createLink src file >> return True)
- ( thawContent file
- , go
+ ( return True
+ , copyfrom src
)
+#else
+ copyfrom src
#endif
- go = do
- fromAnnex key file
- logStatus key InfoMissing
-
performDirect :: FilePath -> Key -> CommandPerform
performDirect file key = do
diff --git a/Command/Uninit.hs b/Command/Uninit.hs
index a40e28399..3fbe6758a 100644
--- a/Command/Uninit.hs
+++ b/Command/Uninit.hs
@@ -11,7 +11,6 @@ import Common.Annex
import Command
import qualified Git
import qualified Git.Command
-import qualified Annex
import qualified Command.Unannex
import Init
import qualified Annex.Branch
@@ -38,7 +37,7 @@ check = do
seek :: [CommandSeek]
seek =
[ withFilesNotInGit $ whenAnnexed startCheckIncomplete
- , withFilesInGit $ whenAnnexed startUnannex
+ , withFilesInGit $ whenAnnexed Command.Unannex.start
, withNothing start
]
@@ -51,14 +50,6 @@ startCheckIncomplete file _ = error $ unlines
, "Not continuing with uninit; either delete or git annex add the file and retry."
]
-startUnannex :: FilePath -> (Key, Backend) -> CommandStart
-startUnannex file info = do
- -- Force fast mode before running unannex. This way, if multiple
- -- files link to a key, it will be left in the annex and hardlinked
- -- to by each.
- Annex.changeState $ \s -> s { Annex.fast = True }
- Command.Unannex.start file info
-
start :: CommandStart
start = next $ next $ do
annexdir <- fromRepo gitAnnexDir
diff --git a/Command/Unused.hs b/Command/Unused.hs
index 0a060aae6..844cdb19b 100644
--- a/Command/Unused.hs
+++ b/Command/Unused.hs
@@ -21,21 +21,22 @@ import Common.Annex
import Command
import Logs.Unused
import Annex.Content
-import Utility.FileMode
import Logs.Location
import Logs.Transfer
import qualified Annex
import qualified Git
import qualified Git.Command
import qualified Git.Ref
+import qualified Git.Branch
import qualified Git.LsFiles as LsFiles
-import qualified Git.LsTree as LsTree
+import qualified Git.DiffTree as DiffTree
import qualified Backend
import qualified Remote
import qualified Annex.Branch
import qualified Option
import Annex.CatFile
import Types.Key
+import Git.FilePath
def :: [Command]
def = [withOptions [fromOption] $ command "unused" paramNothing seek
@@ -241,7 +242,7 @@ withKeysReferenced' mdir initial a = do
( return ([], return True)
, do
top <- fromRepo Git.repoPath
- inRepo $ LsFiles.inRepo [top]
+ inRepo $ LsFiles.allFiles [top]
)
Just dir -> inRepo $ LsFiles.inRepo [dir]
go v [] = return v
@@ -255,35 +256,47 @@ withKeysReferenced' mdir initial a = do
withKeysReferencedInGit :: (Key -> Annex ()) -> Annex ()
withKeysReferencedInGit a = do
- rs <- relevantrefs <$> showref
- forM_ rs (withKeysReferencedInGitRef a)
+ current <- inRepo Git.Branch.currentUnsafe
+ shaHead <- maybe (return Nothing) (inRepo . Git.Ref.sha) current
+ showref >>= mapM_ (withKeysReferencedInGitRef a) .
+ relevantrefs (shaHead, current)
where
showref = inRepo $ Git.Command.pipeReadStrict [Param "show-ref"]
- relevantrefs = map (Git.Ref . snd) .
- nubBy uniqref .
+ relevantrefs headRef = addHead headRef .
filter ourbranches .
- map (separate (== ' ')) . lines
- uniqref (x, _) (y, _) = x == y
+ map (separate (== ' ')) .
+ lines
+ nubRefs = map (Git.Ref . snd) . nubBy (\(x, _) (y, _) -> x == y)
ourbranchend = '/' : show Annex.Branch.name
ourbranches (_, b) = not (ourbranchend `isSuffixOf` b)
&& not ("refs/synced/" `isPrefixOf` b)
-
+ addHead headRef refs = case headRef of
+ -- if HEAD diverges from all branches (except the branch it
+ -- points to), run the actions on staged keys (and keys
+ -- that are only present in the work tree if the repo is
+ -- non bare)
+ (Just (Git.Ref x), Just (Git.Ref b))
+ | all (\(x',b') -> x /= x' || b == b') refs ->
+ Git.Ref.headRef
+ : nubRefs (filter ((/= x) . fst) refs)
+ _ -> nubRefs refs
+
+{- Runs an action on keys referenced in the given Git reference which
+ - differ from those referenced in the index. -}
withKeysReferencedInGitRef :: (Key -> Annex ()) -> Git.Ref -> Annex ()
withKeysReferencedInGitRef a ref = do
showAction $ "checking " ++ Git.Ref.describe ref
- go <=< inRepo $ LsTree.lsTree ref
+ bare <- isBareRepo
+ (ts,clean) <- inRepo $ if bare
+ then DiffTree.diffIndex ref
+ else DiffTree.diffWorkTree ref
+ let lookAtWorkingTree = not bare && ref == Git.Ref.headRef
+ forM_ ts $ tKey lookAtWorkingTree >=> maybe noop a
+ liftIO $ void clean
where
- go [] = noop
- go (l:ls)
- | isSymLink (LsTree.mode l) = do
- content <- encodeW8 . L.unpack
- <$> catFile ref (LsTree.file l)
- case fileKey (takeFileName content) of
- Nothing -> go ls
- Just k -> do
- a k
- go ls
- | otherwise = go ls
+ tKey True = fmap fst <$$> Backend.lookupFile . getTopFilePath . DiffTree.file
+ tKey False = fileKey . takeFileName . encodeW8 . L.unpack <$$>
+ catFile ref . getTopFilePath . DiffTree.file
{- Looks in the specified directory for bad/tmp keys, and returns a list
- of those that might still have value, or might be stale and removable.
@@ -292,7 +305,7 @@ withKeysReferencedInGitRef a ref = do
-}
staleKeysPrune :: (Git.Repo -> FilePath) -> Bool -> Annex [Key]
staleKeysPrune dirspec nottransferred = do
- contents <- staleKeys dirspec
+ contents <- dirKeys dirspec
dups <- filterM inAnnex contents
let stale = contents `exclude` dups
@@ -307,18 +320,6 @@ staleKeysPrune dirspec nottransferred = do
return $ filter (`S.notMember` inprogress) stale
else return stale
-staleKeys :: (Git.Repo -> FilePath) -> Annex [Key]
-staleKeys dirspec = do
- dir <- fromRepo dirspec
- ifM (liftIO $ doesDirectoryExist dir)
- ( do
- contents <- liftIO $ getDirectoryContents dir
- files <- liftIO $ filterM doesFileExist $
- map (dir </>) contents
- return $ mapMaybe (fileKey . takeFileName) files
- , return []
- )
-
data UnusedMaps = UnusedMaps
{ unusedMap :: UnusedMap
, unusedBadMap :: UnusedMap
diff --git a/Command/Upgrade.hs b/Command/Upgrade.hs
index 88ca8622d..66ea0e0eb 100644
--- a/Command/Upgrade.hs
+++ b/Command/Upgrade.hs
@@ -11,6 +11,7 @@ import Common.Annex
import Command
import Upgrade
import Annex.Version
+import Config
def :: [Command]
def = [dontCheck repoExists $ -- because an old version may not seem to exist
@@ -23,6 +24,9 @@ seek = [withNothing start]
start :: CommandStart
start = do
showStart "upgrade" "."
- r <- upgrade
- setVersion defaultVersion
+ r <- upgrade False
+ ifM isDirect
+ ( setVersion directModeVersion
+ , setVersion defaultVersion
+ )
next $ next $ return r
diff --git a/Command/Version.hs b/Command/Version.hs
index c8507cd5a..b330d1ff1 100644
--- a/Command/Version.hs
+++ b/Command/Version.hs
@@ -12,6 +12,10 @@ import Command
import qualified Build.SysConfig as SysConfig
import Annex.Version
import BuildFlags
+import qualified Types.Backend as B
+import qualified Types.Remote as R
+import qualified Remote
+import qualified Backend
def :: [Command]
def = [noCommit $ noRepo showPackageVersion $ dontCheck repoExists $
@@ -25,13 +29,20 @@ start = do
v <- getVersion
liftIO $ do
showPackageVersion
- putStrLn $ "local repository version: " ++ fromMaybe "unknown" v
- putStrLn $ "default repository version: " ++ defaultVersion
- putStrLn $ "supported repository versions: " ++ unwords supportedVersions
- putStrLn $ "upgrade supported from repository versions: " ++ unwords upgradableVersions
+ info "local repository version" $ fromMaybe "unknown" v
+ info "default repository version" defaultVersion
+ info "supported repository versions" $
+ unwords supportedVersions
+ info "upgrade supported from repository versions" $
+ unwords upgradableVersions
stop
showPackageVersion :: IO ()
showPackageVersion = do
- putStrLn $ "git-annex version: " ++ SysConfig.packageversion
- putStrLn $ "build flags: " ++ unwords buildFlags
+ info "git-annex version" SysConfig.packageversion
+ info "build flags" $ unwords buildFlags
+ info "key/value backends" $ unwords $ map B.name Backend.list
+ info "remote types" $ unwords $ map R.typename Remote.remoteTypes
+
+info :: String -> String -> IO ()
+info k v = putStrLn $ k ++ ": " ++ v
diff --git a/Command/Vicfg.hs b/Command/Vicfg.hs
index 1aa8722c5..22c641408 100644
--- a/Command/Vicfg.hs
+++ b/Command/Vicfg.hs
@@ -21,7 +21,9 @@ import Types.Group
import Logs.Trust
import Logs.Group
import Logs.PreferredContent
+import Logs.Schedule
import Types.StandardGroups
+import Types.ScheduledActivity
import Remote
def :: [Command]
@@ -59,6 +61,7 @@ data Cfg = Cfg
{ cfgTrustMap :: TrustMap
, cfgGroupMap :: M.Map UUID (S.Set Group)
, cfgPreferredContentMap :: M.Map UUID String
+ , cfgScheduleMap :: M.Map UUID [ScheduledActivity]
}
getCfg :: Annex Cfg
@@ -66,22 +69,25 @@ getCfg = Cfg
<$> trustMapRaw -- without local trust overrides
<*> (groupsByUUID <$> groupMap)
<*> preferredContentMapRaw
+ <*> scheduleMap
setCfg :: Cfg -> Cfg -> Annex ()
setCfg curcfg newcfg = do
- let (trustchanges, groupchanges, preferredcontentchanges) = diffCfg curcfg newcfg
+ 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)
-diffCfg curcfg newcfg = (diff cfgTrustMap, diff cfgGroupMap, diff cfgPreferredContentMap)
+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)
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]
+genCfg cfg descs = unlines $ concat
+ [intro, trust, groups, preferredcontent, schedule]
where
intro =
[ com "git-annex configuration"
@@ -120,17 +126,25 @@ genCfg cfg descs = unlines $ concat [intro, trust, groups, preferredcontent]
(\(s, u) -> line "content" u s)
(\u -> line "content" u "")
+ schedule = settings 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 (\u -> lcom $ showdefaults u) $ missing field
+ , concatMap (lcom . showdefaults) $ missing field
]
line setting u value =
- [ com $ "(for " ++ (fromMaybe "" $ M.lookup u descs) ++ ")"
+ [ com $ "(for " ++ fromMaybe "" (M.lookup u descs) ++ ")"
, unwords [setting, fromUUID u, "=", value]
]
- lcom = map (\l -> if "#" `isPrefixOf` l then l else "#" ++ l)
+ lcom = map (\l -> if "#" `isPrefixOf` l then l else '#' : l)
missing field = S.toList $ M.keysSet descs `S.difference` M.keysSet (field cfg)
{- If there's a parse error, returns a new version of the file,
@@ -139,7 +153,7 @@ parseCfg :: Cfg -> String -> Either String Cfg
parseCfg curcfg = go [] curcfg . lines
where
go c cfg []
- | null (catMaybes $ map fst c) = Right cfg
+ | null (mapMaybe fst c) = Right cfg
| otherwise = Left $ unlines $
badheader ++ concatMap showerr (reverse c)
go c cfg (l:ls) = case parse (dropWhile isSpace l) cfg of
@@ -173,6 +187,11 @@ parseCfg curcfg = go [] curcfg . lines
Nothing ->
let m = M.insert u value (cfgPreferredContentMap cfg)
in Right $ cfg { cfgPreferredContentMap = 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
showerr (Just msg, l) = [parseerr ++ msg, l]
diff --git a/Command/Content.hs b/Command/Wanted.hs
index d10bdde3c..a7b4a3d9e 100644
--- a/Command/Content.hs
+++ b/Command/Wanted.hs
@@ -5,7 +5,7 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-module Command.Content where
+module Command.Wanted where
import Common.Annex
import Command
@@ -15,7 +15,7 @@ import Logs.PreferredContent
import qualified Data.Map as M
def :: [Command]
-def = [command "content" (paramPair paramRemote (paramOptional paramExpression)) seek
+def = [command "wanted" (paramPair paramRemote (paramOptional paramExpression)) seek
SectionSetup "get or set preferred content expression"]
seek :: [CommandSeek]
@@ -26,7 +26,7 @@ start = parse
where
parse (name:[]) = go name performGet
parse (name:expr:[]) = go name $ \uuid -> do
- showStart "content" name
+ showStart "wanted" name
performSet expr uuid
parse _ = error "Specify a repository."
diff --git a/Command/Watch.hs b/Command/Watch.hs
index c5fd1a8cd..0b34b0f84 100644
--- a/Command/Watch.hs
+++ b/Command/Watch.hs
@@ -11,6 +11,7 @@ import Common.Annex
import Assistant
import Command
import Option
+import Utility.HumanTime
def :: [Command]
def = [notBareRepo $ withOptions [foregroundOption, stopOption] $
@@ -19,7 +20,7 @@ def = [notBareRepo $ withOptions [foregroundOption, stopOption] $
seek :: [CommandSeek]
seek = [withFlag stopOption $ \stopdaemon ->
withFlag foregroundOption $ \foreground ->
- withNothing $ start False foreground stopdaemon]
+ withNothing $ start False foreground stopdaemon Nothing]
foregroundOption :: Option
foregroundOption = Option.flag [] "foreground" "do not daemonize"
@@ -27,9 +28,9 @@ foregroundOption = Option.flag [] "foreground" "do not daemonize"
stopOption :: Option
stopOption = Option.flag [] "stop" "stop daemon"
-start :: Bool -> Bool -> Bool -> CommandStart
-start assistant foreground stopdaemon = do
+start :: Bool -> Bool -> Bool -> Maybe Duration -> CommandStart
+start assistant foreground stopdaemon startdelay = do
if stopdaemon
then stopDaemon
- else startDaemon assistant foreground Nothing Nothing -- does not return
+ else startDaemon assistant foreground startdelay Nothing Nothing -- does not return
stop
diff --git a/Command/WebApp.hs b/Command/WebApp.hs
index eeb23a164..88c1537d0 100644
--- a/Command/WebApp.hs
+++ b/Command/WebApp.hs
@@ -55,7 +55,7 @@ start = start' True
start' :: Bool -> Maybe HostName -> CommandStart
start' allowauto listenhost = do
- liftIO $ ensureInstalled
+ liftIO ensureInstalled
ifM isInitialized ( go , auto )
stop
where
@@ -69,7 +69,7 @@ start' allowauto listenhost = do
url <- liftIO . readFile
=<< fromRepo gitAnnexUrlFile
liftIO $ openBrowser browser f url Nothing Nothing
- , startDaemon True True listenhost $ Just $
+ , startDaemon True True Nothing listenhost $ Just $
\origout origerr url htmlshim ->
if isJust listenhost
then maybe noop (`hPutStrLn` url) origout
@@ -155,7 +155,7 @@ firstRun listenhost = do
_wait <- takeMVar v
state <- Annex.new =<< Git.CurrentRepo.get
Annex.eval state $
- startDaemon True True listenhost $ Just $
+ startDaemon True True Nothing listenhost $ Just $
sendurlback v
sendurlback v _origout _origerr url _htmlshim = do
recordUrl url
@@ -209,7 +209,7 @@ openBrowser mcmd htmlshim realurl outh errh = do
, std_err = maybe Inherit UseHandle errh
}
exitcode <- waitForProcess pid
- unless (exitcode == ExitSuccess) $ do
+ unless (exitcode == ExitSuccess) $
hPutStrLn (fromMaybe stderr errh) "failed to start web browser"
{- web.browser is a generic git config setting for a web browser program -}
diff --git a/Common.hs b/Common.hs
index 5dc3cfbb2..a6203b9a6 100644
--- a/Common.hs
+++ b/Common.hs
@@ -28,6 +28,7 @@ import Utility.Process as X
import Utility.Path as X
import Utility.Directory as X
import Utility.Monad as X
+import Utility.Data as X
import Utility.Applicative as X
import Utility.FileSystemEncoding as X
diff --git a/Config.hs b/Config.hs
index 4d93a2af5..0c6b64f50 100644
--- a/Config.hs
+++ b/Config.hs
@@ -18,10 +18,16 @@ import Config.Cost
type UnqualifiedConfigKey = String
data ConfigKey = ConfigKey String
+instance Show ConfigKey where
+ show (ConfigKey s) = s
+
{- Looks up a setting in git config. -}
getConfig :: ConfigKey -> String -> Annex String
getConfig (ConfigKey key) def = fromRepo $ Git.Config.get key def
+getConfigMaybe :: ConfigKey -> Annex (Maybe String)
+getConfigMaybe (ConfigKey key) = fromRepo $ Git.Config.getMaybe key
+
{- Changes a git config setting in both internal state and .git/config -}
setConfig :: ConfigKey -> String -> Annex ()
setConfig (ConfigKey key) value = do
@@ -30,8 +36,11 @@ setConfig (ConfigKey key) value = do
{- Unsets a git config setting. (Leaves it in state currently.) -}
unsetConfig :: ConfigKey -> Annex ()
-unsetConfig (ConfigKey key) = inRepo $ Git.Command.run
- [Param "config", Param "--unset", Param key]
+unsetConfig ck@(ConfigKey key) = ifM (isJust <$> getConfigMaybe ck)
+ ( inRepo $ Git.Command.run
+ [Param "config", Param "--unset", Param key]
+ , noop -- avoid unsetting something not set; that would fail
+ )
{- A per-remote config setting in git config. -}
remoteConfig :: Git.Repo -> UnqualifiedConfigKey -> ConfigKey
@@ -62,11 +71,6 @@ getNumCopies Nothing = annexNumCopies <$> Annex.getGitConfig
isDirect :: Annex Bool
isDirect = annexDirect <$> Annex.getGitConfig
-setDirect :: Bool -> Annex ()
-setDirect b = do
- setConfig (annexConfig "direct") (Git.Config.boolConfig b)
- Annex.changeGitConfig $ \c -> c { annexDirect = b }
-
crippledFileSystem :: Annex Bool
crippledFileSystem = annexCrippledFileSystem <$> Annex.getGitConfig
diff --git a/Config/Cost.hs b/Config/Cost.hs
index dc391a5a5..2d94a6b15 100644
--- a/Config/Cost.hs
+++ b/Config/Cost.hs
@@ -65,7 +65,7 @@ costBetween x y
| x == y = x
| x > y = -- avoid fractions unless needed
let mid = y + (x - y) / 2
- mid' = fromIntegral ((floor mid) :: Int)
+ mid' = fromIntegral (floor mid :: Int)
in if mid' > y then mid' else mid
| otherwise = costBetween y x
diff --git a/Config/Files.hs b/Config/Files.hs
index 3db2bb74c..30ed0a3cf 100644
--- a/Config/Files.hs
+++ b/Config/Files.hs
@@ -34,7 +34,7 @@ modifyAutoStartFile func = do
when (dirs' /= dirs) $ do
f <- autoStartFile
createDirectoryIfMissing True (parentDir f)
- viaTmp writeFile f $ unlines $ dirs'
+ viaTmp writeFile f $ unlines dirs'
{- Adds a directory to the autostart file. If the directory is already
- present, it's moved to the top, so it will be used as the default
diff --git a/Creds.hs b/Creds.hs
index 7791ce85d..c79c16cce 100644
--- a/Creds.hs
+++ b/Creds.hs
@@ -15,11 +15,8 @@ import Utility.FileMode
import Crypto
import Types.Remote (RemoteConfig, RemoteConfigKey)
import Remote.Helper.Encryptable (remoteCipher, embedCreds)
-#ifndef mingw32_HOST_OS
-import Utility.Env (setEnv)
-#endif
+import Utility.Env (setEnv, getEnv)
-import System.Environment
import qualified Data.ByteString.Lazy.Char8 as L
import qualified Data.Map as M
import Utility.Base64
@@ -52,7 +49,7 @@ setRemoteCredPair c storage = go =<< getRemoteCredPair c storage
return c
storeconfig creds key (Just cipher) = do
- s <- liftIO $ encrypt (GpgOpts []) cipher
+ s <- liftIO $ encrypt [] cipher
(feedBytes $ L.pack $ encodeCredPair creds)
(readBytes $ return . L.unpack)
return $ M.insert key (toB64 s) c
@@ -101,11 +98,10 @@ getRemoteCredPair c storage = maybe fromcache (return . Just) =<< fromenv
{- Gets a CredPair from the environment. -}
getEnvCredPair :: CredPairStorage -> IO (Maybe CredPair)
getEnvCredPair storage = liftM2 (,)
- <$> get uenv
- <*> get penv
+ <$> getEnv uenv
+ <*> getEnv penv
where
(uenv, penv) = credPairEnvironment storage
- get = catchMaybeIO . getEnv
{- Stores a CredPair in the environment. -}
setEnvCredPair :: CredPair -> CredPairStorage -> IO ()
diff --git a/Crypto.hs b/Crypto.hs
index 21b1ae41b..371bbcaf1 100644
--- a/Crypto.hs
+++ b/Crypto.hs
@@ -8,6 +8,8 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE FlexibleInstances #-}
+
module Crypto (
Cipher,
KeyIds(..),
@@ -22,9 +24,8 @@ module Crypto (
feedBytes,
readBytes,
encrypt,
- decrypt,
- GpgOpts(..),
- getGpgOpts,
+ decrypt,
+ getGpgEncParams,
prop_HmacSha1WithCipher_sane
) where
@@ -32,17 +33,18 @@ module Crypto (
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Lazy.UTF8 (fromString)
import Control.Applicative
+import qualified Data.Map as M
import Common.Annex
import qualified Utility.Gpg as Gpg
-import Utility.Gpg.Types
import Types.Key
import Types.Crypto
+import Types.Remote
{- The beginning of a Cipher is used for MAC'ing; the remainder is used
- - as the GPG symmetric encryption passphrase. Note that the cipher
- - itself is base-64 encoded, hence the string is longer than
- - 'cipherSize': 683 characters, padded to 684.
+ - as the GPG symmetric encryption passphrase when using the hybrid
+ - scheme. Note that the cipher itself is base-64 encoded, hence the
+ - string is longer than 'cipherSize': 683 characters, padded to 684.
-
- The 256 first characters that feed the MAC represent at best 192
- bytes of entropy. However that's more than enough for both the
@@ -62,59 +64,79 @@ cipherSize = 512
cipherPassphrase :: Cipher -> String
cipherPassphrase (Cipher c) = drop cipherBeginning c
+cipherPassphrase (MacOnlyCipher _) = error "MAC-only cipher"
cipherMac :: Cipher -> String
cipherMac (Cipher c) = take cipherBeginning c
+cipherMac (MacOnlyCipher c) = c
{- Creates a new Cipher, encrypted to the specified key id. -}
-genEncryptedCipher :: String -> Bool -> IO StorableCipher
-genEncryptedCipher keyid highQuality = do
+genEncryptedCipher :: String -> EncryptedCipherVariant -> Bool -> IO StorableCipher
+genEncryptedCipher keyid variant highQuality = do
ks <- Gpg.findPubKeys keyid
- random <- Gpg.genRandom highQuality cipherSize
- encryptCipher (Cipher random) ks
+ random <- Gpg.genRandom highQuality size
+ encryptCipher (mkCipher random) variant ks
+ where
+ (mkCipher, size) = case variant of
+ Hybrid -> (Cipher, cipherSize) -- used for MAC + symmetric
+ PubKey -> (MacOnlyCipher, cipherBeginning) -- only used for MAC
{- Creates a new, shared Cipher. -}
genSharedCipher :: Bool -> IO StorableCipher
genSharedCipher highQuality =
SharedCipher <$> Gpg.genRandom highQuality cipherSize
-{- Updates an existing Cipher, re-encrypting it to add a keyid. -}
-updateEncryptedCipher :: String -> StorableCipher -> IO StorableCipher
-updateEncryptedCipher _ (SharedCipher _) = undefined
-updateEncryptedCipher keyid encipher@(EncryptedCipher _ ks) = do
- ks' <- Gpg.findPubKeys keyid
+{- Updates an existing Cipher, re-encrypting it to add or remove keyids,
+ - depending on whether the first component is True or False. -}
+updateEncryptedCipher :: [(Bool, String)] -> StorableCipher -> IO StorableCipher
+updateEncryptedCipher _ SharedCipher{} = undefined
+updateEncryptedCipher [] encipher = return encipher
+updateEncryptedCipher newkeys encipher@(EncryptedCipher _ variant (KeyIds ks)) = do
+ dropKeys <- listKeyIds [ k | (False, k) <- newkeys ]
+ forM_ dropKeys $ \k -> unless (k `elem` ks) $
+ error $ "Key " ++ k ++ " was not present; cannot remove."
+ addKeys <- listKeyIds [ k | (True, k) <- newkeys ]
+ let ks' = (addKeys ++ ks) \\ dropKeys
+ when (null ks') $
+ error "Cannot remove the last key."
cipher <- decryptCipher encipher
- encryptCipher cipher (merge ks ks')
+ encryptCipher cipher variant $ KeyIds ks'
where
- merge (KeyIds a) (KeyIds b) = KeyIds $ a ++ b
+ listKeyIds = concat <$$> mapM (keyIds <$$> Gpg.findPubKeys)
describeCipher :: StorableCipher -> String
describeCipher (SharedCipher _) = "shared cipher"
-describeCipher (EncryptedCipher _ (KeyIds ks)) =
- "with gpg " ++ keys ks ++ " " ++ unwords ks
+describeCipher (EncryptedCipher _ variant (KeyIds ks)) =
+ scheme ++ " with gpg " ++ keys ks ++ " " ++ unwords ks
where
+ scheme = case variant of
+ Hybrid -> "hybrid cipher"
+ PubKey -> "pubkey crypto"
keys [_] = "key"
keys _ = "keys"
{- Encrypts a Cipher to the specified KeyIds. -}
-encryptCipher :: Cipher -> KeyIds -> IO StorableCipher
-encryptCipher (Cipher c) (KeyIds ks) = do
+encryptCipher :: Cipher -> EncryptedCipherVariant -> KeyIds -> IO StorableCipher
+encryptCipher c variant (KeyIds ks) = do
-- gpg complains about duplicate recipient keyids
let ks' = nub $ sort ks
- encipher <- Gpg.pipeStrict (Params "--encrypt" : recipients ks') c
- return $ EncryptedCipher encipher (KeyIds ks')
+ let params = Gpg.pkEncTo ks' ++ Gpg.stdEncryptionParams False
+ encipher <- Gpg.pipeStrict params cipher
+ return $ EncryptedCipher encipher variant (KeyIds ks')
where
- recipients l = force_recipients :
- concatMap (\k -> [Param "--recipient", Param k]) l
- -- Force gpg to only encrypt to the specified
- -- recipients, not configured defaults.
- force_recipients = Params "--no-encrypt-to --no-default-recipient"
+ cipher = case c of
+ Cipher x -> x
+ MacOnlyCipher x -> x
{- Decrypting an EncryptedCipher is expensive; the Cipher should be cached. -}
decryptCipher :: StorableCipher -> IO Cipher
decryptCipher (SharedCipher t) = return $ Cipher t
-decryptCipher (EncryptedCipher t _) =
- Cipher <$> Gpg.pipeStrict [ Param "--decrypt" ] t
+decryptCipher (EncryptedCipher t variant _) =
+ mkCipher <$> Gpg.pipeStrict [ Param "--decrypt" ] t
+ where
+ mkCipher = case variant of
+ Hybrid -> Cipher
+ PubKey -> MacOnlyCipher
{- Generates an encrypted form of a Key. The encryption does not need to be
- reversable, nor does it need to be the same type of encryption used
@@ -139,17 +161,25 @@ feedBytes = flip L.hPut
readBytes :: (L.ByteString -> IO a) -> Reader a
readBytes a h = L.hGetContents h >>= a
-{- Runs a Feeder action, that generates content that is symmetrically encrypted
- - with the Cipher using the given GnuPG options, and then read by the Reader
- - action. -}
-encrypt :: GpgOpts -> Cipher -> Feeder -> Reader a -> IO a
-encrypt opts = Gpg.feedRead ( Params "--symmetric --force-mdc" : toParams opts )
- . cipherPassphrase
+{- Runs a Feeder action, that generates content that is symmetrically
+ - encrypted with the Cipher (unless it is empty, in which case
+ - public-key encryption is used) using the given gpg options, and then
+ - read by the Reader action. Note: For public-key encryption,
+ - recipients MUST be included in 'params' (for instance using
+ - 'getGpgEncParams'). -}
+encrypt :: [CommandParam] -> Cipher -> Feeder -> Reader a -> IO a
+encrypt params cipher = case cipher of
+ Cipher{} -> Gpg.feedRead (params ++ Gpg.stdEncryptionParams True) $
+ cipherPassphrase cipher
+ MacOnlyCipher{} -> Gpg.pipeLazy $ params ++ Gpg.stdEncryptionParams False
{- Runs a Feeder action, that generates content that is decrypted with the
- - Cipher, and read by the Reader action. -}
+ - Cipher (or using a private key if the Cipher is empty), and read by the
+ - Reader action. -}
decrypt :: Cipher -> Feeder -> Reader a -> IO a
-decrypt = Gpg.feedRead [Param "--decrypt"] . cipherPassphrase
+decrypt cipher = case cipher of
+ Cipher{} -> Gpg.feedRead [Param "--decrypt"] $ cipherPassphrase cipher
+ MacOnlyCipher{} -> Gpg.pipeLazy [Param "--decrypt"]
macWithCipher :: Mac -> Cipher -> String -> String
macWithCipher mac c = macWithCipher' mac (cipherMac c)
@@ -161,3 +191,21 @@ prop_HmacSha1WithCipher_sane :: Bool
prop_HmacSha1WithCipher_sane = known_good == macWithCipher' HmacSha1 "foo" "bar"
where
known_good = "46b4ec586117154dacd49d664e5d63fdc88efb51"
+
+{- Return some options suitable for GnuPG encryption, symmetric or not. -}
+class LensGpgEncParams a where getGpgEncParams :: a -> [CommandParam]
+
+{- Extract the GnuPG options from a pair of a Remote Config and a Remote
+ - Git Config. If the remote is configured to use public-key encryption,
+ - look up the recipient keys and add them to the option list. -}
+instance LensGpgEncParams (RemoteConfig, RemoteGitConfig) where
+ getGpgEncParams (c,gc) = map Param (remoteAnnexGnupgOptions gc) ++ recipients
+ where
+ recipients = case M.lookup "encryption" c of
+ Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $
+ M.lookup "cipherkeys" c
+ _ -> []
+
+{- Extract the GnuPG options from a Remote. -}
+instance LensGpgEncParams (RemoteA a) where
+ getGpgEncParams r = getGpgEncParams (config r, gitconfig r)
diff --git a/Git/Branch.hs b/Git/Branch.hs
index d4a684016..7b3297d74 100644
--- a/Git/Branch.hs
+++ b/Git/Branch.hs
@@ -13,7 +13,7 @@ import Common
import Git
import Git.Sha
import Git.Command
-import Git.Ref (headRef)
+import qualified Git.Ref
{- The currently checked out branch.
-
@@ -36,7 +36,7 @@ current r = do
{- The current branch, which may not really exist yet. -}
currentUnsafe :: Repo -> IO (Maybe Git.Ref)
currentUnsafe r = parse . firstLine
- <$> pipeReadStrict [Param "symbolic-ref", Param $ show headRef] r
+ <$> pipeReadStrict [Param "symbolic-ref", Param $ show Git.Ref.headRef] r
where
parse l
| null l = Nothing
@@ -96,8 +96,38 @@ commit message branch parentrefs repo = do
pipeReadStrict [Param "write-tree"] repo
sha <- getSha "commit-tree" $ pipeWriteRead
(map Param $ ["commit-tree", show tree] ++ ps)
- message repo
- run [Param "update-ref", Param $ show branch, Param $ show sha] repo
+ (Just $ flip hPutStr message) repo
+ update branch sha repo
return sha
where
ps = concatMap (\r -> ["-p", show r]) parentrefs
+
+{- A leading + makes git-push force pushing a branch. -}
+forcePush :: String -> String
+forcePush b = "+" ++ b
+
+{- Updates a branch (or other ref) to a new Sha. -}
+update :: Branch -> Sha -> Repo -> IO ()
+update branch sha = run
+ [ Param "update-ref"
+ , Param $ show branch
+ , Param $ show sha
+ ]
+
+{- Checks out a branch, creating it if necessary. -}
+checkout :: Branch -> Repo -> IO ()
+checkout branch = run
+ [ Param "checkout"
+ , Param "-q"
+ , Param "-B"
+ , Param $ show $ Git.Ref.base branch
+ ]
+
+{- Removes a branch. -}
+delete :: Branch -> Repo -> IO ()
+delete branch = run
+ [ Param "branch"
+ , Param "-q"
+ , Param "-D"
+ , Param $ show $ Git.Ref.base branch
+ ]
diff --git a/Git/CatFile.hs b/Git/CatFile.hs
index 46b59c631..aee6bd19f 100644
--- a/Git/CatFile.hs
+++ b/Git/CatFile.hs
@@ -8,8 +8,10 @@
module Git.CatFile (
CatFileHandle,
catFileStart,
+ catFileStart',
catFileStop,
catFile,
+ catTree,
catObject,
catObjectDetails,
) where
@@ -17,9 +19,9 @@ module Git.CatFile (
import System.IO
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
-import Data.Digest.Pure.SHA
-import Data.Char
-import System.Process (std_out, std_err)
+import Data.Tuple.Utils
+import Numeric
+import System.Posix.Types
import Common
import Git
@@ -32,8 +34,11 @@ import qualified Utility.CoProcess as CoProcess
data CatFileHandle = CatFileHandle CoProcess.CoProcessHandle Repo
catFileStart :: Repo -> IO CatFileHandle
-catFileStart repo = do
- coprocess <- CoProcess.rawMode =<< gitCoProcessStart True
+catFileStart = catFileStart' True
+
+catFileStart' :: Bool -> Repo -> IO CatFileHandle
+catFileStart' restartable repo = do
+ coprocess <- CoProcess.rawMode =<< gitCoProcessStart restartable
[ Param "cat-file"
, Param "--batch"
] repo
@@ -50,11 +55,10 @@ catFile h branch file = catObject h $ Ref $
{- Uses a running git cat-file read the content of an object.
- Objects that do not exist will have "" returned. -}
catObject :: CatFileHandle -> Ref -> IO L.ByteString
-catObject h object = maybe L.empty fst <$> catObjectDetails h object
+catObject h object = maybe L.empty fst3 <$> catObjectDetails h object
-{- Gets both the content of an object, and its Sha. -}
-catObjectDetails :: CatFileHandle -> Ref -> IO (Maybe (L.ByteString, Sha))
-catObjectDetails (CatFileHandle hdl repo) object = CoProcess.query hdl send receive
+catObjectDetails :: CatFileHandle -> Ref -> IO (Maybe (L.ByteString, Sha, ObjectType))
+catObjectDetails (CatFileHandle hdl _) object = CoProcess.query hdl send receive
where
query = show object
send to = hPutStrLn to query
@@ -62,46 +66,43 @@ catObjectDetails (CatFileHandle hdl repo) object = CoProcess.query hdl send rece
header <- hGetLine from
case words header of
[sha, objtype, size]
- | length sha == shaSize &&
- isJust (readObjectType objtype) ->
- case reads size of
- [(bytes, "")] -> readcontent bytes from sha
+ | length sha == shaSize ->
+ case (readObjectType objtype, reads size) of
+ (Just t, [(bytes, "")]) -> readcontent t bytes from sha
_ -> dne
| otherwise -> dne
_
| header == show object ++ " missing" -> dne
- | otherwise ->
- if any isSpace query
- then fallback
- else error $ "unknown response from git cat-file " ++ show (header, object)
- readcontent bytes from sha = do
+ | otherwise -> error $ "unknown response from git cat-file " ++ show (header, object)
+ readcontent objtype bytes from sha = do
content <- S.hGet from bytes
eatchar '\n' from
- return $ Just (L.fromChunks [content], Ref sha)
+ return $ Just (L.fromChunks [content], Ref sha, objtype)
dne = return Nothing
eatchar expected from = do
c <- hGetChar from
when (c /= expected) $
error $ "missing " ++ (show expected) ++ " from git cat-file"
- {- Work around a bug in git 1.8.4 rc0 which broke it for filenames
- - containing spaces. http://bugs.debian.org/718517
- - Slow! Also can use a lot of memory, if the object is large. -}
- fallback = do
- let p = gitCreateProcess
- [ Param "cat-file"
- , Param "-p"
- , Param query
- ] repo
- (_, Just h, _, pid) <- withNullHandle $ \h ->
- createProcess p
- { std_out = CreatePipe
- , std_err = UseHandle h
- }
- fileEncoding h
- content <- L.hGetContents h
- let sha = (\s -> length s `seq` s) (showDigest $ sha1 content)
- ok <- checkSuccessProcess pid
- return $ if ok
- then Just (content, Ref sha)
- else Nothing
+{- Gets a list of files and directories in a tree. (Not recursive.) -}
+catTree :: CatFileHandle -> Ref -> IO [(FilePath, FileMode)]
+catTree h treeref = go <$> catObjectDetails h treeref
+ where
+ go (Just (b, _, TreeObject)) = parsetree [] b
+ go _ = []
+
+ parsetree c b = case L.break (== 0) b of
+ (modefile, rest)
+ | L.null modefile -> c
+ | otherwise -> parsetree
+ (parsemodefile modefile:c)
+ (dropsha rest)
+
+ -- these 20 bytes after the NUL hold the file's sha
+ -- TODO: convert from raw form to regular sha
+ dropsha = L.drop 21
+
+ parsemodefile b =
+ let (modestr, file) = separate (== ' ') (encodeW8 $ L.unpack b)
+ in (file, readmode modestr)
+ readmode = fst . fromMaybe (0, undefined) . headMaybe . readOct
diff --git a/Git/CheckAttr.hs b/Git/CheckAttr.hs
index 24fa2be87..94ead5b4c 100644
--- a/Git/CheckAttr.hs
+++ b/Git/CheckAttr.hs
@@ -13,6 +13,8 @@ import Git.Command
import qualified Git.BuildVersion
import qualified Utility.CoProcess as CoProcess
+import System.IO.Error
+
type CheckAttrHandle = (CoProcess.CoProcessHandle, [Attr], String)
type Attr = String
@@ -37,16 +39,41 @@ checkAttrStop (h, _, _) = CoProcess.stop h
{- Gets an attribute of a file. -}
checkAttr :: CheckAttrHandle -> Attr -> FilePath -> IO String
checkAttr (h, attrs, cwd) want file = do
- pairs <- CoProcess.query h send receive
+ pairs <- CoProcess.query h send (receive "")
let vals = map snd $ filter (\(attr, _) -> attr == want) pairs
case vals of
[v] -> return v
_ -> error $ "unable to determine " ++ want ++ " attribute of " ++ file
where
send to = hPutStr to $ file' ++ "\0"
- receive from = forM attrs $ \attr -> do
- l <- hGetLine from
- return (attr, attrvalue attr l)
+ receive c from = do
+ s <- hGetSomeString from 1024
+ if null s
+ then eofError
+ else do
+ let v = c ++ s
+ maybe (receive v from) return (parse v)
+ eofError = ioError $ mkIOError userErrorType "git check-attr EOF" Nothing Nothing
+ parse s
+ -- new null separated output
+ | '\0' `elem` s = if "\0" `isSuffixOf` s
+ then
+ let bits = segment (== '\0') s
+ in if length bits == (numattrs * 3) + 1
+ then Just $ getattrvalues bits []
+ else Nothing -- more attributes to come
+ else Nothing -- output incomplete
+ -- old one line per value output
+ | otherwise = if "\n" `isSuffixOf` s
+ then
+ let ls = lines s
+ in if length ls == numattrs
+ then Just $ map (\(attr, val) -> (attr, oldattrvalue attr val))
+ (zip attrs ls)
+ else Nothing -- more attributes to come
+ else Nothing -- line incomplete
+ numattrs = length attrs
+
{- Before git 1.7.7, git check-attr worked best with
- absolute filenames; using them worked around some bugs
- with relative filenames.
@@ -58,7 +85,9 @@ checkAttr (h, attrs, cwd) want file = do
file'
| oldgit = absPathFrom cwd file
| otherwise = relPathDirToFile cwd $ absPathFrom cwd file
- attrvalue attr l = end bits !! 0
+ oldattrvalue attr l = end bits !! 0
where
bits = split sep l
sep = ": " ++ attr ++ ": "
+ getattrvalues (_filename:attr:val:rest) c = getattrvalues rest ((attr,val):c)
+ getattrvalues _ c = c
diff --git a/Git/Command.hs b/Git/Command.hs
index 2d68540e6..adcc53bcd 100644
--- a/Git/Command.hs
+++ b/Git/Command.hs
@@ -1,10 +1,12 @@
{- running git commands
-
- - Copyright 2010-2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Git.Command where
import System.Process (std_out, env)
@@ -13,15 +15,27 @@ import Common
import Git
import Git.Types
import qualified Utility.CoProcess as CoProcess
+#ifdef mingw32_HOST_OS
+import Git.FilePath
+#endif
{- Constructs a git command line operating on the specified repo. -}
gitCommandLine :: [CommandParam] -> Repo -> [CommandParam]
-gitCommandLine params Repo { location = l@(Local _ _ ) } = setdir : settree ++ params
+gitCommandLine params r@(Repo { location = l@(Local _ _ ) }) =
+ setdir : settree ++ gitGlobalOpts r ++ params
where
- setdir = Param $ "--git-dir=" ++ gitdir l
+ setdir = Param $ "--git-dir=" ++ gitpath (gitdir l)
settree = case worktree l of
Nothing -> []
- Just t -> [Param $ "--work-tree=" ++ t]
+ Just t -> [Param $ "--work-tree=" ++ gitpath t]
+#ifdef mingw32_HOST_OS
+ -- despite running on windows, msysgit wants a unix-formatted path
+ gitpath s
+ | isAbsolute s = "/" ++ dropDrive (toInternalGitPath s)
+ | otherwise = s
+#else
+ gitpath = id
+#endif
gitCommandLine _ repo = assertLocal repo $ error "internal"
{- Runs git in the specified repo. -}
@@ -72,13 +86,13 @@ pipeReadStrict params repo = assertLocal repo $
where
p = gitCreateProcess params repo
-{- Runs a git command, feeding it input, and returning its output,
+{- Runs a git command, feeding it an input, and returning its output,
- which is expected to be fairly small, since it's all read into memory
- strictly. -}
-pipeWriteRead :: [CommandParam] -> String -> Repo -> IO String
-pipeWriteRead params s repo = assertLocal repo $
+pipeWriteRead :: [CommandParam] -> Maybe (Handle -> IO ()) -> Repo -> IO String
+pipeWriteRead params writer repo = assertLocal repo $
writeReadProcessEnv "git" (toCommand $ gitCommandLine params repo)
- (gitEnv repo) s (Just adjusthandle)
+ (gitEnv repo) writer (Just adjusthandle)
where
adjusthandle h = do
fileEncoding h
diff --git a/Git/Config.hs b/Git/Config.hs
index adc75a208..1919ecedf 100644
--- a/Git/Config.hs
+++ b/Git/Config.hs
@@ -10,6 +10,7 @@ module Git.Config where
import qualified Data.Map as M
import Data.Char
import System.Process (cwd, env)
+import Control.Exception.Extensible
import Common
import Git
@@ -152,4 +153,41 @@ boolConfig True = "true"
boolConfig False = "false"
isBare :: Repo -> Bool
-isBare r = fromMaybe False $ isTrue =<< getMaybe "core.bare" r
+isBare r = fromMaybe False $ isTrue =<< getMaybe coreBare r
+
+coreBare :: String
+coreBare = "core.bare"
+
+{- Runs a command to get the configuration of a repo,
+ - and returns a repo populated with the configuration, as well as the raw
+ - output of the command. -}
+fromPipe :: Repo -> String -> [CommandParam] -> IO (Either SomeException (Repo, String))
+fromPipe r cmd params = try $
+ withHandle StdoutHandle createProcessSuccess p $ \h -> do
+ fileEncoding h
+ val <- hGetContentsStrict h
+ r' <- store val r
+ return (r', val)
+ where
+ p = proc cmd $ toCommand params
+
+{- Reads git config from a specified file and returns the repo populated
+ - with the configuration. -}
+fromFile :: Repo -> FilePath -> IO (Either SomeException (Repo, String))
+fromFile r f = fromPipe r "git"
+ [ Param "config"
+ , Param "--file"
+ , File f
+ , Param "--list"
+ ]
+
+{- Changes a git config setting in the specified config file.
+ - (Creates the file if it does not already exist.) -}
+changeFile :: FilePath -> String -> String -> IO Bool
+changeFile f k v = boolSystem "git"
+ [ Param "config"
+ , Param "--file"
+ , File f
+ , Param k
+ , Param v
+ ]
diff --git a/Git/Construct.hs b/Git/Construct.hs
index 586fa8c03..71a13f49f 100644
--- a/Git/Construct.hs
+++ b/Git/Construct.hs
@@ -23,12 +23,8 @@ module Git.Construct (
checkForRepo,
) where
-{-# LANGUAGE CPP #-}
-
#ifndef mingw32_HOST_OS
import System.Posix.User
-#else
-import Git.FilePath
#endif
import qualified Data.Map as M hiding (map, split)
import Network.URI
@@ -36,6 +32,7 @@ import Network.URI
import Common
import Git.Types
import Git
+import Git.Remote
import qualified Git.Url as Url
import Utility.UserInfo
@@ -91,7 +88,7 @@ fromUrl url
fromUrlStrict :: String -> IO Repo
fromUrlStrict url
- | startswith "file://" url = fromAbsPath $ uriPath u
+ | startswith "file://" url = fromAbsPath $ unEscapeString $ uriPath u
| otherwise = newFrom $ Url u
where
u = fromMaybe bad $ parseURI url
@@ -107,14 +104,16 @@ localToUrl :: Repo -> Repo -> Repo
localToUrl reference r
| not $ repoIsUrl reference = error "internal error; reference repo not url"
| repoIsUrl r = r
- | otherwise = r { location = Url $ fromJust $ parseURI absurl }
- where
- absurl = concat
- [ Url.scheme reference
- , "//"
- , Url.authority reference
- , repoPath r
- ]
+ | otherwise = case Url.authority reference of
+ Nothing -> r
+ Just auth ->
+ let absurl = concat
+ [ Url.scheme reference
+ , "//"
+ , auth
+ , repoPath r
+ ]
+ in r { location = Url $ fromJust $ parseURI absurl }
{- Calculates a list of a repo's configured remotes, by parsing its config. -}
fromRemotes :: Repo -> IO [Repo]
@@ -143,51 +142,10 @@ remoteNamedFromKey k = remoteNamed basename
{- Constructs a new Repo for one of a Repo's remotes using a given
- location (ie, an url). -}
fromRemoteLocation :: String -> Repo -> IO Repo
-fromRemoteLocation s repo = gen $ calcloc s
+fromRemoteLocation s repo = gen $ parseRemoteLocation s repo
where
- gen v
-#ifdef mingw32_HOST_OS
- | dosstyle v = fromRemotePath (dospath v) repo
-#endif
- | scpstyle v = fromUrl $ scptourl v
- | urlstyle v = fromUrl v
- | otherwise = fromRemotePath v repo
- -- insteadof config can rewrite remote location
- calcloc l
- | null insteadofs = l
- | otherwise = replacement ++ drop (length bestvalue) l
- where
- replacement = drop (length prefix) $
- take (length bestkey - length suffix) bestkey
- (bestkey, bestvalue) = maximumBy longestvalue insteadofs
- longestvalue (_, a) (_, b) = compare b a
- insteadofs = filterconfig $ \(k, v) ->
- startswith prefix k &&
- endswith suffix k &&
- startswith v l
- filterconfig f = filter f $
- concatMap splitconfigs $ M.toList $ fullconfig repo
- splitconfigs (k, vs) = map (\v -> (k, v)) vs
- (prefix, suffix) = ("url." , ".insteadof")
- urlstyle v = isURI v || ":" `isInfixOf` v && "//" `isInfixOf` v
- -- git remotes can be written scp style -- [user@]host:dir
- -- but foo::bar is a git-remote-helper location instead
- scpstyle v = ":" `isInfixOf` v
- && not ("//" `isInfixOf` v)
- && not ("::" `isInfixOf` v)
- scptourl v = "ssh://" ++ host ++ slash dir
- where
- (host, dir) = separate (== ':') v
- slash d | d == "" = "/~/" ++ d
- | "/" `isPrefixOf` d = d
- | "~" `isPrefixOf` d = '/':d
- | otherwise = "/~/" ++ d
-#ifdef mingw32_HOST_OS
- -- git on Windows will write a path to .git/config with "drive:",
- -- which is not to be confused with a "host:"
- dosstyle = hasDrive
- dospath = fromInternalGitPath
-#endif
+ gen (RemotePath p) = fromRemotePath p repo
+ gen (RemoteUrl u) = fromUrl u
{- Constructs a Repo from the path specified in the git remotes of
- another Repo. -}
@@ -272,6 +230,7 @@ newFrom l = return Repo
, remotes = []
, remoteName = Nothing
, gitEnv = Nothing
+ , gitGlobalOpts = []
}
diff --git a/Git/DiffTree.hs b/Git/DiffTree.hs
index cf8a37600..e7787caee 100644
--- a/Git/DiffTree.hs
+++ b/Git/DiffTree.hs
@@ -10,6 +10,7 @@ module Git.DiffTree (
diffTree,
diffTreeRecursive,
diffIndex,
+ diffWorkTree,
) where
import Numeric
@@ -19,6 +20,7 @@ import Common
import Git
import Git.Sha
import Git.Command
+import Git.FilePath
import qualified Git.Filename
import qualified Git.Ref
@@ -28,7 +30,7 @@ data DiffTreeItem = DiffTreeItem
, srcsha :: Sha -- nullSha if file was added
, dstsha :: Sha -- nullSha if file was deleted
, status :: String
- , file :: FilePath
+ , file :: TopFilePath
} deriving Show
{- Diffs two tree Refs. -}
@@ -41,15 +43,26 @@ diffTreeRecursive :: Ref -> Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
diffTreeRecursive src dst = getdiff (Param "diff-tree")
[Param "-r", Param (show src), Param (show dst)]
-{- Diffs between the repository and index. Does nothing if there is not
- - yet a commit in the repository. -}
-diffIndex :: Repo -> IO ([DiffTreeItem], IO Bool)
-diffIndex repo = do
+{- Diffs between a tree and the index. Does nothing if there is not yet a
+ - commit in the repository. -}
+diffIndex :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
+diffIndex ref = diffIndex' ref [Param "--cached"]
+
+{- Diffs between a tree and the working tree. Does nothing if there is not
+ - yet a commit in the repository, of if the repository is bare. -}
+diffWorkTree :: Ref -> Repo -> IO ([DiffTreeItem], IO Bool)
+diffWorkTree ref repo =
+ ifM (Git.Ref.headExists repo)
+ ( diffIndex' ref [] repo
+ , return ([], return True)
+ )
+
+diffIndex' :: Ref -> [CommandParam] -> Repo -> IO ([DiffTreeItem], IO Bool)
+diffIndex' ref params repo =
ifM (Git.Ref.headExists repo)
( getdiff (Param "diff-index")
- [ Param "--cached"
- , Param $ show Git.Ref.headRef
- ] repo
+ ( params ++ [Param $ show ref] )
+ repo
, return ([], return True)
)
@@ -74,7 +87,7 @@ parseDiffTree l = go l []
, srcsha = fromMaybe (error "bad srcsha") $ extractSha ssha
, dstsha = fromMaybe (error "bad dstsha") $ extractSha dsha
, status = s
- , file = Git.Filename.decode f
+ , file = asTopFilePath $ Git.Filename.decode f
}
where
readmode = fst . Prelude.head . readOct
diff --git a/Git/FileMode.hs b/Git/FileMode.hs
new file mode 100644
index 000000000..fc4d0264e
--- /dev/null
+++ b/Git/FileMode.hs
@@ -0,0 +1,23 @@
+{- git file modes
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Git.FileMode where
+
+import Utility.FileMode
+
+import System.PosixCompat.Types
+
+symLinkMode :: FileMode
+symLinkMode = 40960
+
+{- Git uses a special file mode to indicate a symlink. This is the case
+ - even on Windows, so we hard code the valuse here, rather than using
+ - System.Posix.Files.symbolicLinkMode. -}
+isSymLink :: FileMode -> Bool
+isSymLink = checkMode symLinkMode
diff --git a/Git/FilePath.hs b/Git/FilePath.hs
index 891f9991d..37d740f25 100644
--- a/Git/FilePath.hs
+++ b/Git/FilePath.hs
@@ -14,6 +14,7 @@
module Git.FilePath (
TopFilePath,
+ fromTopFilePath,
getTopFilePath,
toTopFilePath,
asTopFilePath,
@@ -27,6 +28,11 @@ import Git
{- A FilePath, relative to the top of the git repository. -}
newtype TopFilePath = TopFilePath { getTopFilePath :: FilePath }
+ deriving (Show)
+
+{- Returns an absolute FilePath. -}
+fromTopFilePath :: TopFilePath -> Git.Repo -> FilePath
+fromTopFilePath p repo = absPathFrom (repoPath repo) (getTopFilePath p)
{- The input FilePath can be absolute, or relative to the CWD. -}
toTopFilePath :: FilePath -> Git.Repo -> IO TopFilePath
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
new file mode 100644
index 000000000..2c9423005
--- /dev/null
+++ b/Git/Fsck.hs
@@ -0,0 +1,87 @@
+{- git fsck interface
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Fsck (
+ FsckResults,
+ MissingObjects,
+ findBroken,
+ foundBroken,
+ findMissing,
+) where
+
+import Common
+import Git
+import Git.Command
+import Git.Sha
+import Git.CatFile
+import Utility.Batch
+
+import qualified Data.Set as S
+
+type MissingObjects = S.Set Sha
+
+{- If fsck succeeded, Just a set of missing objects it found.
+ - If it failed, Nothing. -}
+type FsckResults = Maybe MissingObjects
+
+{- Runs fsck to find some of the broken objects in the repository.
+ - May not find all broken objects, if fsck fails on bad data in some of
+ - the broken objects it does find.
+ -
+ - Strategy: Rather than parsing fsck's current specific output,
+ - look for anything in its output (both stdout and stderr) that appears
+ - to be a git sha. Not all such shas are of broken objects, so ask git
+ - to try to cat the object, and see if it fails.
+ -}
+findBroken :: Bool -> Repo -> IO FsckResults
+findBroken batchmode r = do
+ (output, fsckok) <- processTranscript command' (toCommand params') Nothing
+ let objs = parseFsckOutput output
+ badobjs <- findMissing objs r
+ if S.null badobjs && not fsckok
+ then return Nothing
+ else return $ Just badobjs
+ where
+ (command, params) = ("git", fsckParams r)
+ (command', params')
+ | batchmode = toBatchCommand (command, params)
+ | otherwise = (command, params)
+
+foundBroken :: FsckResults -> Bool
+foundBroken Nothing = True
+foundBroken (Just s) = not (S.null s)
+
+{- Finds objects that are missing from the git repsitory, or are corrupt.
+ -
+ - Note that catting a corrupt object will cause cat-file to crash;
+ - this is detected and it's restarted.
+ -}
+findMissing :: [Sha] -> Repo -> IO MissingObjects
+findMissing objs r = go objs [] =<< start
+ where
+ start = catFileStart' False r
+ go [] c h = do
+ catFileStop h
+ return $ S.fromList c
+ go (o:os) c h = do
+ v <- tryIO $ isNothing <$> catObjectDetails h o
+ case v of
+ Left _ -> do
+ void $ tryIO $ catFileStop h
+ go os (o:c) =<< start
+ Right True -> go os (o:c) h
+ Right False -> go os c h
+
+parseFsckOutput :: String -> [Sha]
+parseFsckOutput = catMaybes . map extractSha . concat . map words . lines
+
+fsckParams :: Repo -> [CommandParam]
+fsckParams = gitCommandLine
+ [ Param "fsck"
+ , Param "--no-dangling"
+ , Param "--no-reflogs"
+ ]
diff --git a/Git/GCrypt.hs b/Git/GCrypt.hs
new file mode 100644
index 000000000..156441dae
--- /dev/null
+++ b/Git/GCrypt.hs
@@ -0,0 +1,103 @@
+{- git-remote-gcrypt support
+ -
+ - https://github.com/blake2-ppc/git-remote-gcrypt
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.GCrypt where
+
+import Common
+import Git.Types
+import Git.Construct
+import qualified Git.Config as Config
+import qualified Git.Command as Command
+import Utility.Gpg
+
+urlPrefix :: String
+urlPrefix = "gcrypt::"
+
+isEncrypted :: Repo -> Bool
+isEncrypted Repo { location = Url url } = urlPrefix `isPrefixOf` show url
+isEncrypted _ = False
+
+{- The first Repo is the git repository that has the second Repo
+ - as one of its remotes.
+ -
+ - When the remote Repo uses gcrypt, returns the actual underlying
+ - git repository that gcrypt is using to store its data.
+ -
+ - Throws an exception if an url is invalid or the repo does not use
+ - gcrypt.
+ -}
+encryptedRemote :: Repo -> Repo -> IO Repo
+encryptedRemote baserepo = go
+ where
+ go Repo { location = Url url }
+ | urlPrefix `isPrefixOf` u =
+ fromRemoteLocation (drop plen u) baserepo
+ | otherwise = notencrypted
+ where
+ u = show url
+ plen = length urlPrefix
+ go _ = notencrypted
+ notencrypted = error "not a gcrypt encrypted repository"
+
+data ProbeResult = Decryptable | NotDecryptable | NotEncrypted
+
+{- Checks if the git repo at a location uses gcrypt.
+ -
+ - Rather expensive -- many need to fetch the entire repo contents.
+ - (Which is fine if the repo is going to be added as a remote..)
+ -}
+probeRepo :: String -> Repo -> IO ProbeResult
+probeRepo loc baserepo = do
+ let p = proc "git" $ toCommand $ Command.gitCommandLine
+ [ Param "remote-gcrypt"
+ , Param "--check"
+ , Param loc
+ ] baserepo
+ (_, _, _, pid) <- createProcess p
+ code <- waitForProcess pid
+ return $ case code of
+ ExitSuccess -> Decryptable
+ ExitFailure 1 -> NotDecryptable
+ ExitFailure _ -> NotEncrypted
+
+type GCryptId = String
+
+{- gcrypt gives each encrypted repository a uique gcrypt-id,
+ - which is stored in the repository (in encrypted form)
+ - and cached in a per-remote gcrypt-id configuration setting. -}
+remoteRepoId :: Repo -> Maybe RemoteName -> Maybe GCryptId
+remoteRepoId = getRemoteConfig "gcrypt-id"
+
+getRemoteConfig :: String -> Repo -> Maybe RemoteName -> Maybe String
+getRemoteConfig field repo remotename = do
+ n <- remotename
+ Config.getMaybe (remoteConfigKey field n) repo
+
+{- Gpg keys that the remote is encrypted for.
+ - If empty, gcrypt uses --default-recipient-self -}
+getParticiantList :: Maybe Repo -> Repo -> Maybe RemoteName -> KeyIds
+getParticiantList globalconfigrepo repo remotename = KeyIds $ parse $ firstJust
+ [ getRemoteConfig "gcrypt-participants" repo remotename
+ , Config.getMaybe defaultkey repo
+ , Config.getMaybe defaultkey =<< globalconfigrepo
+ ]
+ where
+ defaultkey = "gcrypt.participants"
+ parse (Just "simple") = []
+ parse (Just l) = words l
+ parse Nothing = []
+
+remoteParticipantConfigKey :: RemoteName -> String
+remoteParticipantConfigKey = remoteConfigKey "gcrypt-participants"
+
+remoteSigningKey :: RemoteName -> String
+remoteSigningKey = remoteConfigKey "gcrypt-signingkey"
+
+remoteConfigKey :: String -> RemoteName -> String
+remoteConfigKey key remotename = "remote." ++ remotename ++ "." ++ key
diff --git a/Git/HashObject.hs b/Git/HashObject.hs
index c6e1d2349..bb9b20d96 100644
--- a/Git/HashObject.hs
+++ b/Git/HashObject.hs
@@ -36,8 +36,11 @@ hashFile h file = CoProcess.query h send receive
{- Injects some content into git, returning its Sha. -}
hashObject :: ObjectType -> String -> Repo -> IO Sha
-hashObject objtype content repo = getSha subcmd $
- pipeWriteRead (map Param params) content repo
+hashObject objtype content = hashObject' objtype (flip hPutStr content)
+
+hashObject' :: ObjectType -> (Handle -> IO ()) -> Repo -> IO Sha
+hashObject' objtype writer repo = getSha subcmd $
+ pipeWriteRead (map Param params) (Just writer) repo
where
subcmd = "hash-object"
params = [subcmd, "-t", show objtype, "-w", "--stdin", "--no-filters"]
diff --git a/Git/Hook.hs b/Git/Hook.hs
new file mode 100644
index 000000000..d56a4a565
--- /dev/null
+++ b/Git/Hook.hs
@@ -0,0 +1,54 @@
+{- git hooks
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Hook where
+
+import Common
+import Git
+import Utility.Tmp
+
+data Hook = Hook
+ { hookName :: FilePath
+ , hookScript :: String
+ }
+
+hookFile :: Hook -> Repo -> FilePath
+hookFile h r = localGitDir r </> "hooks" </> hookName h
+
+{- Writes a hook. Returns False if the hook already exists with a different
+ - content. -}
+hookWrite :: Hook -> Repo -> IO Bool
+hookWrite h r = do
+ let f = hookFile h r
+ ifM (doesFileExist f)
+ ( expectedContent h r
+ , do
+ viaTmp writeFile f (hookScript h)
+ p <- getPermissions f
+ setPermissions f $ p {executable = True}
+ return True
+ )
+
+{- Removes a hook. Returns False if the hook contained something else, and
+ - could not be removed. -}
+hookUnWrite :: Hook -> Repo -> IO Bool
+hookUnWrite h r = do
+ let f = hookFile h r
+ ifM (doesFileExist f)
+ ( ifM (expectedContent h r)
+ ( do
+ removeFile f
+ return True
+ , return False
+ )
+ , return True
+ )
+
+expectedContent :: Hook -> Repo -> IO Bool
+expectedContent h r = do
+ content <- readFile $ hookFile h r
+ return $ content == hookScript h
diff --git a/Git/LsFiles.hs b/Git/LsFiles.hs
index f4e467215..8aaa09067 100644
--- a/Git/LsFiles.hs
+++ b/Git/LsFiles.hs
@@ -8,8 +8,10 @@
module Git.LsFiles (
inRepo,
notInRepo,
+ allFiles,
deleted,
modified,
+ modifiedOthers,
staged,
stagedNotDeleted,
stagedOthersDetails,
@@ -19,6 +21,7 @@ module Git.LsFiles (
Conflicting(..),
Unmerged(..),
unmerged,
+ StagedDetails,
) where
import Common
@@ -27,6 +30,9 @@ import Git.Command
import Git.Types
import Git.Sha
+import Numeric
+import System.Posix.Types
+
{- Scans for files that are checked into git at the specified locations. -}
inRepo :: [FilePath] -> Repo -> IO ([FilePath], IO Bool)
inRepo l = pipeNullSplit $ Params "ls-files --cached -z --" : map File l
@@ -41,6 +47,11 @@ notInRepo include_ignored l repo = pipeNullSplit params repo
| include_ignored = []
| otherwise = [Param "--exclude-standard"]
+{- Finds all files in the specified locations, whether checked into git or
+ - not. -}
+allFiles :: [FilePath] -> Repo -> IO ([FilePath], IO Bool)
+allFiles l = pipeNullSplit $ Params "ls-files --cached --others -z --" : map File l
+
{- Returns a list of files in the specified locations that have been
- deleted. -}
deleted :: [FilePath] -> Repo -> IO ([FilePath], IO Bool)
@@ -55,6 +66,12 @@ modified l repo = pipeNullSplit params repo
where
params = [Params "ls-files --modified -z --"] ++ map File l
+{- Files that have been modified or are not checked into git. -}
+modifiedOthers :: [FilePath] -> Repo -> IO ([FilePath], IO Bool)
+modifiedOthers l repo = pipeNullSplit params repo
+ where
+ params = [Params "ls-files --modified --others -z --"] ++ map File l
+
{- Returns a list of all files that are staged for commit. -}
staged :: [FilePath] -> Repo -> IO ([FilePath], IO Bool)
staged = staged' []
@@ -70,18 +87,20 @@ staged' ps l = pipeNullSplit $ prefix ++ ps ++ suffix
prefix = [Params "diff --cached --name-only -z"]
suffix = Param "--" : map File l
+type StagedDetails = (FilePath, Maybe Sha, Maybe FileMode)
+
{- Returns details about files that are staged in the index,
- as well as files not yet in git. Skips ignored files. -}
-stagedOthersDetails :: [FilePath] -> Repo -> IO ([(FilePath, Maybe Sha)], IO Bool)
+stagedOthersDetails :: [FilePath] -> Repo -> IO ([StagedDetails], IO Bool)
stagedOthersDetails = stagedDetails' [Params "--others --exclude-standard"]
{- Returns details about all files that are staged in the index. -}
-stagedDetails :: [FilePath] -> Repo -> IO ([(FilePath, Maybe Sha)], IO Bool)
+stagedDetails :: [FilePath] -> Repo -> IO ([StagedDetails], IO Bool)
stagedDetails = stagedDetails' []
{- Gets details about staged files, including the Sha of their staged
- contents. -}
-stagedDetails' :: [CommandParam] -> [FilePath] -> Repo -> IO ([(FilePath, Maybe Sha)], IO Bool)
+stagedDetails' :: [CommandParam] -> [FilePath] -> Repo -> IO ([StagedDetails], IO Bool)
stagedDetails' ps l repo = do
(ls, cleanup) <- pipeNullSplit params repo
return (map parse ls, cleanup)
@@ -89,10 +108,12 @@ stagedDetails' ps l repo = do
params = Params "ls-files --stage -z" : ps ++
Param "--" : map File l
parse s
- | null file = (s, Nothing)
- | otherwise = (file, extractSha $ take shaSize $ drop 7 metadata)
+ | null file = (s, Nothing, Nothing)
+ | otherwise = (file, extractSha $ take shaSize rest, readmode mode)
where
(metadata, file) = separate (== '\t') s
+ (mode, rest) = separate (== ' ') metadata
+ readmode = fst <$$> headMaybe . readOct
{- Returns a list of the files in the specified locations that are staged
- for commit, and whose type has changed. -}
diff --git a/Git/LsTree.hs b/Git/LsTree.hs
index 6e4cd8470..956f9f5b4 100644
--- a/Git/LsTree.hs
+++ b/Git/LsTree.hs
@@ -8,6 +8,7 @@
module Git.LsTree (
TreeItem(..),
lsTree,
+ lsTreeParams,
lsTreeFiles,
parseLsTree
) where
@@ -20,26 +21,30 @@ import Common
import Git
import Git.Command
import Git.Sha
+import Git.FilePath
import qualified Git.Filename
data TreeItem = TreeItem
{ mode :: FileMode
, typeobj :: String
, sha :: String
- , file :: FilePath
+ , file :: TopFilePath
} deriving Show
-{- Lists the complete contents of a tree, with lazy output. -}
+{- Lists the complete contents of a tree, recursing into sub-trees,
+ - with lazy output. -}
lsTree :: Ref -> Repo -> IO [TreeItem]
-lsTree t repo = map parseLsTree <$> pipeNullSplitZombie ps repo
- where
- ps = [Params "ls-tree --full-tree -z -r --", File $ show t]
+lsTree t repo = map parseLsTree
+ <$> pipeNullSplitZombie (lsTreeParams t) repo
+
+lsTreeParams :: Ref -> [CommandParam]
+lsTreeParams t = [ Params "ls-tree --full-tree -z -r --", File $ show t ]
{- Lists specified files in a tree. -}
lsTreeFiles :: Ref -> [FilePath] -> Repo -> IO [TreeItem]
lsTreeFiles t fs repo = map parseLsTree <$> pipeNullSplitStrict ps repo
where
- ps = [Params "ls-tree -z --", File $ show t] ++ map File fs
+ ps = [Params "ls-tree --full-tree -z --", File $ show t] ++ map File fs
{- Parses a line of ls-tree output.
- (The --long format is not currently supported.) -}
@@ -48,7 +53,7 @@ parseLsTree l = TreeItem
{ mode = fst $ Prelude.head $ readOct m
, typeobj = t
, sha = s
- , file = Git.Filename.decode f
+ , file = asTopFilePath $ Git.Filename.decode f
}
where
-- l = <mode> SP <type> SP <sha> TAB <file>
diff --git a/Git/Objects.hs b/Git/Objects.hs
new file mode 100644
index 000000000..b1c580533
--- /dev/null
+++ b/Git/Objects.hs
@@ -0,0 +1,29 @@
+{- .git/objects
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Objects where
+
+import Common
+import Git
+
+objectsDir :: Repo -> FilePath
+objectsDir r = localGitDir r </> "objects"
+
+packDir :: Repo -> FilePath
+packDir r = objectsDir r </> "pack"
+
+listPackFiles :: Repo -> IO [FilePath]
+listPackFiles r = filter (".pack" `isSuffixOf`)
+ <$> catchDefaultIO [] (dirContents $ packDir r)
+
+packIdxFile :: FilePath -> FilePath
+packIdxFile = flip replaceExtension "idx"
+
+looseObjectFile :: Repo -> Sha -> FilePath
+looseObjectFile r sha = objectsDir r </> prefix </> rest
+ where
+ (prefix, rest) = splitAt 2 (show sha)
diff --git a/Git/Queue.hs b/Git/Queue.hs
index b8e863658..9bb7f77d1 100644
--- a/Git/Queue.hs
+++ b/Git/Queue.hs
@@ -5,7 +5,7 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE CPP, BangPatterns #-}
module Git.Queue (
Queue,
@@ -26,7 +26,7 @@ import Common
import Git
import Git.Command
import qualified Git.UpdateIndex
-
+
{- Queable actions that can be performed in a git repository.
-}
data Action
@@ -147,13 +147,21 @@ runAction :: Repo -> Action -> IO ()
runAction repo (UpdateIndexAction streamers) =
-- list is stored in reverse order
Git.UpdateIndex.streamUpdateIndex repo $ reverse streamers
-runAction repo action@(CommandAction {}) =
+runAction repo action@(CommandAction {}) =
+#ifndef mingw32_HOST_OS
withHandle StdinHandle createProcessSuccess p $ \h -> do
fileEncoding h
hPutStr h $ intercalate "\0" $ toCommand $ getFiles action
hClose h
+#else
+ -- Using xargs on Windows is problimatic, so just run the command
+ -- once per file (not as efficient.)
+ if null (getFiles action)
+ then void $ boolSystem "git" gitparams
+ else forM_ (getFiles action) $ \f ->
+ void $ boolSystem "git" (gitparams ++ [f])
+#endif
where
- p = (proc "xargs" params) { env = gitEnv repo }
- params = "-0":"git":baseparams
- baseparams = toCommand $ gitCommandLine
+ p = (proc "xargs" $ "-0":"git":toCommand gitparams) { env = gitEnv repo }
+ gitparams = gitCommandLine
(Param (getSubcommand action):getParams action) repo
diff --git a/Git/Ref.hs b/Git/Ref.hs
index 954b61a2e..6ce1b8784 100644
--- a/Git/Ref.hs
+++ b/Git/Ref.hs
@@ -29,17 +29,42 @@ base = Ref . remove "refs/heads/" . remove "refs/remotes/" . show
| prefix `isPrefixOf` s = drop (length prefix) s
| otherwise = s
+{- Given a directory and any ref, takes the basename of the ref and puts
+ - it under the directory. -}
+under :: String -> Ref -> Ref
+under dir r = Ref $ dir ++ "/" ++
+ (reverse $ takeWhile (/= '/') $ reverse $ show r)
+
{- Given a directory such as "refs/remotes/origin", and a ref such as
- refs/heads/master, yields a version of that ref under the directory,
- such as refs/remotes/origin/master. -}
-under :: String -> Ref -> Ref
-under dir r = Ref $ dir </> show (base r)
+underBase :: String -> Ref -> Ref
+underBase dir r = Ref $ dir ++ "/" ++ show (base r)
+
+{- A Ref that can be used to refer to a file in the repository, as staged
+ - in the index.
+ -
+ - Prefixing the file with ./ makes this work even if in a subdirectory
+ - of a repo.
+ -}
+fileRef :: FilePath -> Ref
+fileRef f = Ref $ ":./" ++ f
+
+{- A Ref that can be used to refer to a file in the repository as it
+ - appears in a given Ref. -}
+fileFromRef :: Ref -> FilePath -> Ref
+fileFromRef (Ref r) f = let (Ref fr) = fileRef f in Ref (r ++ fr)
{- Checks if a ref exists. -}
exists :: Ref -> Repo -> IO Bool
exists ref = runBool
[Param "show-ref", Param "--verify", Param "-q", Param $ show ref]
+{- The file used to record a ref. (Git also stores some refs in a
+ - packed-refs file.) -}
+file :: Ref -> Repo -> FilePath
+file ref repo = localGitDir repo </> show ref
+
{- Checks if HEAD exists. It generally will, except for in a repository
- that was just created. -}
headExists :: Repo -> IO Bool
diff --git a/Git/RefLog.hs b/Git/RefLog.hs
new file mode 100644
index 000000000..3f41e8eaa
--- /dev/null
+++ b/Git/RefLog.hs
@@ -0,0 +1,22 @@
+{- git reflog interface
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.RefLog where
+
+import Common
+import Git
+import Git.Command
+import Git.Sha
+
+{- Gets the reflog for a given branch. -}
+get :: Branch -> Repo -> IO [Sha]
+get b = mapMaybe extractSha . lines <$$> pipeReadStrict
+ [ Param "log"
+ , Param "-g"
+ , Param "--format=%H"
+ , Param (show b)
+ ]
diff --git a/Git/Remote.hs b/Git/Remote.hs
index 5640e9ff2..9d969c416 100644
--- a/Git/Remote.hs
+++ b/Git/Remote.hs
@@ -5,10 +5,22 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Git.Remote where
import Common
+import Git
+import Git.Types
+import qualified Git.Command
+import qualified Git.BuildVersion
+
import Data.Char
+import qualified Data.Map as M
+import Network.URI
+#ifdef mingw32_HOST_OS
+import Git.FilePath
+#endif
{- Construct a legal git remote name out of an arbitrary input string.
-
@@ -16,7 +28,7 @@ import Data.Char
- just some ad-hoc checks, and some other things that fail with certian
- types of names (like ones starting with '-').
-}
-makeLegalName :: String -> String
+makeLegalName :: String -> RemoteName
makeLegalName s = case filter legal $ replace "/" "_" s of
-- it can't be empty
[] -> "unnamed"
@@ -31,3 +43,73 @@ makeLegalName s = case filter legal $ replace "/" "_" s of
legal '_' = True
legal '.' = True
legal c = isAlphaNum c
+
+remove :: RemoteName -> Repo -> IO ()
+remove remotename = Git.Command.run
+ [ Param "remote"
+ -- name of this subcommand changed
+ , Param $
+ if Git.BuildVersion.older "1.8.0"
+ then "rm"
+ else "remove"
+ , Param remotename
+ ]
+
+data RemoteLocation = RemoteUrl String | RemotePath FilePath
+
+remoteLocationIsUrl :: RemoteLocation -> Bool
+remoteLocationIsUrl (RemoteUrl _) = True
+remoteLocationIsUrl _ = False
+
+remoteLocationIsSshUrl :: RemoteLocation -> Bool
+remoteLocationIsSshUrl (RemoteUrl u) = "ssh://" `isPrefixOf` u
+remoteLocationIsSshUrl _ = False
+
+{- Determines if a given remote location is an url, or a local
+ - path. Takes the repository's insteadOf configuration into account. -}
+parseRemoteLocation :: String -> Repo -> RemoteLocation
+parseRemoteLocation s repo = ret $ calcloc s
+ where
+ ret v
+#ifdef mingw32_HOST_OS
+ | dosstyle v = RemotePath (dospath v)
+#endif
+ | scpstyle v = RemoteUrl (scptourl v)
+ | urlstyle v = RemoteUrl v
+ | otherwise = RemotePath v
+ -- insteadof config can rewrite remote location
+ calcloc l
+ | null insteadofs = l
+ | otherwise = replacement ++ drop (length bestvalue) l
+ where
+ replacement = drop (length prefix) $
+ take (length bestkey - length suffix) bestkey
+ (bestkey, bestvalue) = maximumBy longestvalue insteadofs
+ longestvalue (_, a) (_, b) = compare b a
+ insteadofs = filterconfig $ \(k, v) ->
+ startswith prefix k &&
+ endswith suffix k &&
+ startswith v l
+ filterconfig f = filter f $
+ concatMap splitconfigs $ M.toList $ fullconfig repo
+ splitconfigs (k, vs) = map (\v -> (k, v)) vs
+ (prefix, suffix) = ("url." , ".insteadof")
+ urlstyle v = isURI v || ":" `isInfixOf` v && "//" `isInfixOf` v
+ -- git remotes can be written scp style -- [user@]host:dir
+ -- but foo::bar is a git-remote-helper location instead
+ scpstyle v = ":" `isInfixOf` v
+ && not ("//" `isInfixOf` v)
+ && not ("::" `isInfixOf` v)
+ scptourl v = "ssh://" ++ host ++ slash dir
+ where
+ (host, dir) = separate (== ':') v
+ slash d | d == "" = "/~/" ++ d
+ | "/" `isPrefixOf` d = d
+ | "~" `isPrefixOf` d = '/':d
+ | otherwise = "/~/" ++ d
+#ifdef mingw32_HOST_OS
+ -- git on Windows will write a path to .git/config with "drive:",
+ -- which is not to be confused with a "host:"
+ dosstyle = hasDrive
+ dospath = fromInternalGitPath
+#endif
diff --git a/Git/Repair.hs b/Git/Repair.hs
new file mode 100644
index 000000000..4265f8796
--- /dev/null
+++ b/Git/Repair.hs
@@ -0,0 +1,534 @@
+{- git repository recovery
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Repair (
+ runRepair,
+ runRepairOf,
+ cleanCorruptObjects,
+ retrieveMissingObjects,
+ resetLocalBranches,
+ removeTrackingBranches,
+ checkIndex,
+ missingIndex,
+ nukeIndex,
+ emptyGoodCommits,
+) where
+
+import Common
+import Git
+import Git.Command
+import Git.Objects
+import Git.Sha
+import Git.Types
+import Git.Fsck
+import qualified Git.Config as Config
+import qualified Git.Construct as Construct
+import qualified Git.LsTree as LsTree
+import qualified Git.LsFiles as LsFiles
+import qualified Git.Ref as Ref
+import qualified Git.RefLog as RefLog
+import qualified Git.UpdateIndex as UpdateIndex
+import qualified Git.Branch as Branch
+import Utility.Tmp
+import Utility.Rsync
+
+import qualified Data.Set as S
+import qualified Data.ByteString.Lazy as L
+import Data.Tuple.Utils
+
+{- Given a set of bad objects found by git fsck, removes all
+ - corrupt objects, and returns a list of missing objects,
+ - which need to be found elsewhere to finish recovery.
+ -
+ - Since git fsck may crash on corrupt objects, and so not
+ - report the full set of corrupt or missing objects,
+ - this removes corrupt objects, and re-runs fsck, until it
+ - stabalizes.
+ -
+ - To remove corrupt objects, unpack all packs, and remove the packs
+ - (to handle corrupt packs), and remove loose object files.
+ -}
+cleanCorruptObjects :: FsckResults -> Repo -> IO MissingObjects
+cleanCorruptObjects mmissing r = check mmissing
+ where
+ check Nothing = do
+ putStrLn "git fsck found a problem but no specific broken objects. Perhaps a corrupt pack file?"
+ ifM (explodePacks r)
+ ( retry S.empty
+ , return S.empty
+ )
+ check (Just bad)
+ | S.null bad = return S.empty
+ | otherwise = do
+ putStrLn $ unwords
+ [ "git fsck found"
+ , show (S.size bad)
+ , "broken objects."
+ ]
+ exploded <- explodePacks r
+ removed <- removeLoose r bad
+ if exploded || removed
+ then retry bad
+ else return bad
+ retry oldbad = do
+ putStrLn "Re-running git fsck to see if it finds more problems."
+ v <- findBroken False r
+ case v of
+ Nothing -> error $ unwords
+ [ "git fsck found a problem, which was not corrected after removing"
+ , show (S.size oldbad)
+ , "corrupt objects."
+ ]
+ Just newbad -> do
+ removed <- removeLoose r newbad
+ let s = S.union oldbad newbad
+ if not removed || s == oldbad
+ then return s
+ else retry s
+
+removeLoose :: Repo -> MissingObjects -> IO Bool
+removeLoose r s = do
+ let fs = map (looseObjectFile r) (S.toList s)
+ count <- length <$> filterM doesFileExist fs
+ if (count > 0)
+ then do
+ putStrLn $ unwords
+ [ "removing"
+ , show count
+ , "corrupt loose objects"
+ ]
+ mapM_ nukeFile fs
+ return True
+ else return False
+
+explodePacks :: Repo -> IO Bool
+explodePacks r = do
+ packs <- listPackFiles r
+ if null packs
+ then return False
+ else do
+ putStrLn "Unpacking all pack files."
+ mapM_ go packs
+ return True
+ where
+ go packfile = do
+ -- May fail, if pack file is corrupt.
+ void $ tryIO $
+ pipeWrite [Param "unpack-objects"] r $ \h ->
+ L.hPut h =<< L.readFile packfile
+ nukeFile packfile
+ nukeFile $ packIdxFile packfile
+
+{- Try to retrieve a set of missing objects, from the remotes of a
+ - repository. Returns any that could not be retreived.
+ -
+ - If another clone of the repository exists locally, which might not be a
+ - remote of the repo being repaired, its path can be passed as a reference
+ - repository.
+ -}
+retrieveMissingObjects :: MissingObjects -> Maybe FilePath -> Repo -> IO MissingObjects
+retrieveMissingObjects missing referencerepo r
+ | S.null missing = return missing
+ | otherwise = withTmpDir "tmprepo" $ \tmpdir -> do
+ unlessM (boolSystem "git" [Params "init", File tmpdir]) $
+ error $ "failed to create temp repository in " ++ tmpdir
+ tmpr <- Config.read =<< Construct.fromAbsPath tmpdir
+ stillmissing <- pullremotes tmpr (remotes r) fetchrefstags missing
+ if S.null stillmissing
+ then return stillmissing
+ else pullremotes tmpr (remotes r) fetchallrefs stillmissing
+ where
+ pullremotes tmpr [] fetchrefs stillmissing = case referencerepo of
+ Nothing -> return stillmissing
+ Just p -> ifM (fetchfrom p fetchrefs tmpr)
+ ( do
+ void $ copyObjects tmpr r
+ findMissing (S.toList stillmissing) r
+ , return stillmissing
+ )
+ pullremotes tmpr (rmt:rmts) fetchrefs s
+ | S.null s = return s
+ | otherwise = do
+ putStrLn $ "Trying to recover missing objects from remote " ++ repoDescribe rmt
+ ifM (fetchfrom (repoLocation rmt) fetchrefs tmpr)
+ ( do
+ void $ copyObjects tmpr r
+ stillmissing <- findMissing (S.toList s) r
+ pullremotes tmpr rmts fetchrefs stillmissing
+ , do
+ putStrLn $ unwords
+ [ "failed to fetch from remote"
+ , repoDescribe rmt
+ , "(will continue without it, but making this remote available may improve recovery)"
+ ]
+ pullremotes tmpr rmts fetchrefs s
+ )
+ fetchfrom fetchurl ps = runBool $
+ [ Param "fetch"
+ , Param fetchurl
+ , Params "--force --update-head-ok --quiet"
+ ] ++ ps
+ -- fetch refs and tags
+ fetchrefstags = [ Param "+refs/heads/*:refs/heads/*", Param "--tags"]
+ -- Fetch all available refs (more likely to fail,
+ -- as the remote may have refs it refuses to send).
+ fetchallrefs = [ Param "+*:*" ]
+
+{- Copies all objects from the src repository to the dest repository.
+ - This is done using rsync, so it copies all missing object, and all
+ - objects they rely on. -}
+copyObjects :: Repo -> Repo -> IO Bool
+copyObjects srcr destr = rsync
+ [ Param "-qr"
+ , File $ addTrailingPathSeparator $ objectsDir srcr
+ , File $ addTrailingPathSeparator $ objectsDir destr
+ ]
+
+{- To deal with missing objects that cannot be recovered, resets any
+ - local branches to point to an old commit before the missing
+ - objects. Returns all branches that were changed, and deleted.
+ -}
+resetLocalBranches :: MissingObjects -> GoodCommits -> Repo -> IO ([Branch], [Branch], GoodCommits)
+resetLocalBranches missing goodcommits r =
+ go [] [] goodcommits =<< filter islocalbranch <$> getAllRefs r
+ where
+ islocalbranch b = "refs/heads/" `isPrefixOf` show b
+ go changed deleted gcs [] = return (changed, deleted, gcs)
+ go changed deleted gcs (b:bs) = do
+ (mc, gcs') <- findUncorruptedCommit missing gcs b r
+ case mc of
+ Just c
+ | c == b -> go changed deleted gcs' bs
+ | otherwise -> do
+ reset b c
+ go (b:changed) deleted gcs' bs
+ Nothing -> do
+ nukeBranchRef b r
+ go changed (b:deleted) gcs' bs
+ reset b c = do
+ nukeBranchRef b r
+ void $ runBool
+ [ Param "branch"
+ , Param (show $ Ref.base b)
+ , Param (show c)
+ ] r
+
+{- To deal with missing objects that cannot be recovered, removes
+ - any remote tracking branches that reference them. Returns a list of
+ - all removed branches.
+ -}
+removeTrackingBranches :: MissingObjects -> GoodCommits -> Repo -> IO ([Branch], GoodCommits)
+removeTrackingBranches missing goodcommits r =
+ go [] goodcommits =<< filter istrackingbranch <$> getAllRefs r
+ where
+ istrackingbranch b = "refs/remotes/" `isPrefixOf` show b
+ go removed gcs [] = return (removed, gcs)
+ go removed gcs (b:bs) = do
+ (ok, gcs') <- verifyCommit missing gcs b r
+ if ok
+ then go removed gcs' bs
+ else do
+ nukeBranchRef b r
+ go (b:removed) gcs' bs
+
+{- Gets all refs, including ones that are corrupt.
+ - git show-ref does not output refs to commits that are directly
+ - corrupted, so it is not used.
+ -}
+getAllRefs :: Repo -> IO [Ref]
+getAllRefs r = do
+ packedrs <- mapMaybe parsePacked . lines
+ <$> catchDefaultIO "" (readFile $ packedRefsFile r)
+ loosers <- map toref <$> dirContentsRecursive refdir
+ return $ packedrs ++ loosers
+ where
+ refdir = localGitDir r </> "refs"
+ toref = Ref . relPathDirToFile (localGitDir r)
+
+packedRefsFile :: Repo -> FilePath
+packedRefsFile r = localGitDir r </> "packed-refs"
+
+parsePacked :: String -> Maybe Ref
+parsePacked l = case words l of
+ (sha:ref:[])
+ | isJust (extractSha sha) -> Just $ Ref ref
+ _ -> Nothing
+
+{- git-branch -d cannot be used to remove a branch that is directly
+ - pointing to a corrupt commit. However, it's tried first. -}
+nukeBranchRef :: Branch -> Repo -> IO ()
+nukeBranchRef b r = void $ usegit <||> byhand
+ where
+ usegit = runBool
+ [ Param "branch"
+ , Params "-r -d"
+ , Param $ show $ Ref.base b
+ ] r
+ byhand = do
+ nukeFile $ localGitDir r </> show b
+ whenM (doesFileExist packedrefs) $
+ withTmpFile "packed-refs" $ \tmp h -> do
+ ls <- lines <$> readFile packedrefs
+ hPutStr h $ unlines $
+ filter (not . skiprefline) ls
+ hClose h
+ renameFile tmp packedrefs
+ return True
+ skiprefline l = case parsePacked l of
+ Just packedref
+ | packedref == b -> True
+ _ -> False
+ packedrefs = packedRefsFile r
+
+{- Finds the most recent commit to a branch that does not need any
+ - of the missing objects. If the input branch is good as-is, returns it.
+ - Otherwise, tries to traverse the commits in the branch to find one
+ - that is ok. That might fail, if one of them is corrupt, or if an object
+ - at the root of the branch is missing. Finally, looks for an old version
+ - of the branch from the reflog.
+ -}
+findUncorruptedCommit :: MissingObjects -> GoodCommits -> Branch -> Repo -> IO (Maybe Sha, GoodCommits)
+findUncorruptedCommit missing goodcommits branch r = do
+ (ok, goodcommits') <- verifyCommit missing goodcommits branch r
+ if ok
+ then return (Just branch, goodcommits')
+ else do
+ (ls, cleanup) <- pipeNullSplit
+ [ Param "log"
+ , Param "-z"
+ , Param "--format=%H"
+ , Param (show branch)
+ ] r
+ let branchshas = catMaybes $ map extractSha ls
+ reflogshas <- RefLog.get branch r
+ -- XXX Could try a bit harder here, and look
+ -- for uncorrupted old commits in branches in the
+ -- reflog.
+ cleanup `after` findfirst goodcommits (branchshas ++ reflogshas)
+ where
+ findfirst gcs [] = return (Nothing, gcs)
+ findfirst gcs (c:cs) = do
+ (ok, gcs') <- verifyCommit missing gcs c r
+ if ok
+ then return (Just c, gcs')
+ else findfirst gcs' cs
+
+{- Verifies tha 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
+ - uncorrupted commit. -}
+verifyCommit :: MissingObjects -> GoodCommits -> Sha -> Repo -> IO (Bool, GoodCommits)
+verifyCommit missing goodcommits commit r
+ | checkGoodCommit commit goodcommits = return (True, goodcommits)
+ | otherwise = do
+ (ls, cleanup) <- pipeNullSplit
+ [ Param "log"
+ , Param "-z"
+ , Param "--format=%H %T"
+ , Param (show commit)
+ ] r
+ let committrees = map parse ls
+ if any isNothing committrees || null committrees
+ then do
+ void cleanup
+ return (False, goodcommits)
+ else do
+ let cts = catMaybes committrees
+ ifM (cleanup <&&> check cts)
+ ( return (True, addGoodCommits (map fst cts) goodcommits)
+ , return (False, goodcommits)
+ )
+ where
+ parse l = case words l of
+ (commitsha:treesha:[]) -> (,)
+ <$> extractSha commitsha
+ <*> extractSha treesha
+ _ -> Nothing
+ check [] = return True
+ check ((c, t):rest)
+ | checkGoodCommit c goodcommits = return True
+ | otherwise = verifyTree missing t r <&&> check rest
+
+{- Verifies that a tree is good, including all trees and blobs
+ - referenced by it. -}
+verifyTree :: MissingObjects -> Sha -> Repo -> IO Bool
+verifyTree missing treesha r
+ | S.member treesha missing = return False
+ | otherwise = do
+ (ls, cleanup) <- pipeNullSplit (LsTree.lsTreeParams treesha) r
+ let objshas = map (extractSha . LsTree.sha . LsTree.parseLsTree) ls
+ if any isNothing objshas || any (`S.member` missing) (catMaybes objshas)
+ then do
+ void cleanup
+ return False
+ -- as long as ls-tree succeeded, we're good
+ else cleanup
+
+{- Checks that the index file only refers to objects that are not missing,
+ - and is not itself corrupt. Note that a missing index file is not
+ - considered a problem (repo may be new). -}
+checkIndex :: MissingObjects -> Repo -> IO Bool
+checkIndex missing r = do
+ (bad, _good, cleanup) <- partitionIndex missing r
+ if null bad
+ then cleanup
+ else do
+ void cleanup
+ return False
+
+missingIndex :: Repo -> IO Bool
+missingIndex r = not <$> doesFileExist (localGitDir r </> "index")
+
+partitionIndex :: MissingObjects -> Repo -> IO ([LsFiles.StagedDetails], [LsFiles.StagedDetails], IO Bool)
+partitionIndex missing r = do
+ (indexcontents, cleanup) <- LsFiles.stagedDetails [repoPath r] r
+ let (bad, good) = partition ismissing indexcontents
+ return (bad, good, cleanup)
+ where
+ getblob (_file, Just sha, Just _mode) = Just sha
+ getblob _ = Nothing
+ ismissing = maybe False (`S.member` missing) . getblob
+
+{- Rewrites the index file, removing from it any files whose blobs are
+ - missing. Returns the list of affected files. -}
+rewriteIndex :: MissingObjects -> Repo -> IO [FilePath]
+rewriteIndex missing r
+ | repoIsLocalBare r = return []
+ | otherwise = do
+ (bad, good, cleanup) <- partitionIndex missing r
+ unless (null bad) $ do
+ nukeIndex r
+ UpdateIndex.streamUpdateIndex r
+ =<< (catMaybes <$> mapM reinject good)
+ void cleanup
+ return $ map fst3 bad
+ where
+ reinject (file, Just sha, Just mode) = case toBlobType mode of
+ Nothing -> return Nothing
+ Just blobtype -> Just <$>
+ UpdateIndex.stageFile sha blobtype file r
+ reinject _ = return Nothing
+
+nukeIndex :: Repo -> IO ()
+nukeIndex r = nukeFile (localGitDir r </> "index")
+
+newtype GoodCommits = GoodCommits (S.Set Sha)
+
+emptyGoodCommits :: GoodCommits
+emptyGoodCommits = GoodCommits S.empty
+
+checkGoodCommit :: Sha -> GoodCommits -> Bool
+checkGoodCommit sha (GoodCommits s) = S.member sha s
+
+addGoodCommits :: [Sha] -> GoodCommits -> GoodCommits
+addGoodCommits shas (GoodCommits s) = GoodCommits $
+ S.union s (S.fromList shas)
+
+displayList :: [String] -> String -> IO ()
+displayList items header
+ | null items = return ()
+ | otherwise = do
+ putStrLn header
+ putStr $ unlines $ map (\i -> "\t" ++ i) truncateditems
+ where
+ numitems = length items
+ truncateditems
+ | numitems > 10 = take 10 items ++ ["(and " ++ show (numitems - 10) ++ " more)"]
+ | otherwise = items
+
+{- Put it all together. -}
+runRepair :: Bool -> Repo -> IO (Bool, MissingObjects, [Branch])
+runRepair forced g = do
+ putStrLn "Running git fsck ..."
+ fsckresult <- findBroken False g
+ if foundBroken fsckresult
+ then runRepairOf fsckresult forced Nothing g
+ else do
+ putStrLn "No problems found."
+ return (True, S.empty, [])
+
+runRepairOf :: FsckResults -> Bool -> Maybe FilePath -> Repo -> IO (Bool, MissingObjects, [Branch])
+runRepairOf fsckresult forced referencerepo g = do
+ missing <- cleanCorruptObjects fsckresult g
+ stillmissing <- retrieveMissingObjects missing referencerepo g
+ if S.null stillmissing
+ then if repoIsLocalBare g
+ then successfulfinish stillmissing []
+ else ifM (checkIndex stillmissing g)
+ ( successfulfinish stillmissing []
+ , do
+ putStrLn "No missing objects found, but the index file is corrupt!"
+ if forced
+ then corruptedindex
+ else needforce stillmissing
+ )
+ else do
+ putStrLn $ unwords
+ [ show (S.size stillmissing)
+ , "missing objects could not be recovered!"
+ ]
+ if forced
+ then continuerepairs stillmissing
+ else unsuccessfulfinish stillmissing
+ where
+ continuerepairs stillmissing = do
+ (remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g
+ unless (null remotebranches) $
+ putStrLn $ unwords
+ [ "removed"
+ , show (length remotebranches)
+ , "remote tracking branches that referred to missing objects"
+ ]
+ (resetbranches, deletedbranches, _) <- resetLocalBranches stillmissing goodcommits g
+ displayList (map show resetbranches)
+ "Reset these local branches to old versions before the missing objects were committed:"
+ displayList (map show deletedbranches)
+ "Deleted these local branches, which could not be recovered due to missing objects:"
+ deindexedfiles <- rewriteIndex stillmissing 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 stillmissing modifiedbranches
+ else 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"
+ , show 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, stillmissing, modifiedbranches)
+
+ corruptedindex = do
+ nukeIndex g
+ 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 (True, S.empty, [])
+
+ successfulfinish stillmissing 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, stillmissing, modifiedbranches)
+ unsuccessfulfinish stillmissing = do
+ if repoIsLocalBare g
+ then do
+ putStrLn "If you have a clone of this bare repository, you should add it as a remote of this repository, and re-run git-recover-repository."
+ putStrLn "If there are no clones of this repository, you can instead run git-recover-repository with the --force parameter to force recovery to a possibly usable state."
+ return (False, stillmissing, [])
+ else needforce stillmissing
+ needforce stillmissing = do
+ putStrLn "To force a recovery to a usable state, run this command again with the --force parameter."
+ return (False, stillmissing, [])
diff --git a/Git/Types.hs b/Git/Types.hs
index 4765aad6c..e63e93077 100644
--- a/Git/Types.hs
+++ b/Git/Types.hs
@@ -9,6 +9,8 @@ module Git.Types where
import Network.URI
import qualified Data.Map as M
+import System.Posix.Types
+import Utility.SafeCommand
{- Support repositories on local disk, and repositories accessed via an URL.
-
@@ -34,11 +36,15 @@ data Repo = Repo
, fullconfig :: M.Map String [String]
, remotes :: [Repo]
-- remoteName holds the name used for this repo in remotes
- , remoteName :: Maybe String
+ , remoteName :: Maybe RemoteName
-- alternate environment to use when running git commands
, gitEnv :: Maybe [(String, String)]
+ -- global options to pass to git when running git commands
+ , gitGlobalOpts :: [CommandParam]
} deriving (Show, Eq)
+type RemoteName = String
+
{- A git ref. Can be a sha1, or a branch or tag name. -}
newtype Ref = Ref String
deriving (Eq, Ord)
@@ -81,3 +87,9 @@ readBlobType "100644" = Just FileBlob
readBlobType "100755" = Just ExecutableBlob
readBlobType "120000" = Just SymlinkBlob
readBlobType _ = Nothing
+
+toBlobType :: FileMode -> Maybe BlobType
+toBlobType 0o100644 = Just FileBlob
+toBlobType 0o100755 = Just ExecutableBlob
+toBlobType 0o120000 = Just SymlinkBlob
+toBlobType _ = Nothing
diff --git a/Git/UpdateIndex.hs b/Git/UpdateIndex.hs
index 5d07e2011..3b33ac846 100644
--- a/Git/UpdateIndex.hs
+++ b/Git/UpdateIndex.hs
@@ -13,6 +13,7 @@ module Git.UpdateIndex (
streamUpdateIndex,
lsTree,
updateIndexLine,
+ stageFile,
unstageFile,
stageSymlink
) where
@@ -61,6 +62,11 @@ updateIndexLine :: Sha -> BlobType -> TopFilePath -> String
updateIndexLine sha filetype file =
show filetype ++ " blob " ++ show sha ++ "\t" ++ indexPath file
+stageFile :: Sha -> BlobType -> FilePath -> Repo -> IO Streamer
+stageFile sha filetype file repo = do
+ p <- toTopFilePath file repo
+ return $ pureStreamer $ updateIndexLine sha filetype p
+
{- A streamer that removes a file from the index. -}
unstageFile :: FilePath -> Repo -> IO Streamer
unstageFile file repo = do
diff --git a/Git/Url.hs b/Git/Url.hs
index 7befc4669..d383a6aca 100644
--- a/Git/Url.hs
+++ b/Git/Url.hs
@@ -37,32 +37,33 @@ uriRegName' a = fixup $ uriRegName a
fixup x = x
{- Hostname of an URL repo. -}
-host :: Repo -> String
+host :: Repo -> Maybe String
host = authpart uriRegName'
{- Port of an URL repo, if it has a nonstandard one. -}
port :: Repo -> Maybe Integer
port r =
case authpart uriPort r of
- ":" -> Nothing
- (':':p) -> readish p
- _ -> Nothing
+ Nothing -> Nothing
+ Just ":" -> Nothing
+ Just (':':p) -> readish p
+ Just _ -> Nothing
{- Hostname of an URL repo, including any username (ie, "user@host") -}
-hostuser :: Repo -> String
-hostuser r = authpart uriUserInfo r ++ authpart uriRegName' r
+hostuser :: Repo -> Maybe String
+hostuser r = (++)
+ <$> authpart uriUserInfo r
+ <*> authpart uriRegName' r
{- The full authority portion an URL repo. (ie, "user@host:port") -}
-authority :: Repo -> String
+authority :: Repo -> Maybe String
authority = authpart assemble
where
assemble a = uriUserInfo a ++ uriRegName' a ++ uriPort a
{- Applies a function to extract part of the uriAuthority of an URL repo. -}
-authpart :: (URIAuth -> a) -> Repo -> a
-authpart a Repo { location = Url u } = a auth
- where
- auth = fromMaybe (error $ "bad url " ++ show u) (uriAuthority u)
+authpart :: (URIAuth -> a) -> Repo -> Maybe a
+authpart a Repo { location = Url u } = a <$> uriAuthority u
authpart _ repo = notUrl repo
notUrl :: Repo -> a
diff --git a/GitAnnex.hs b/GitAnnex.hs
index 9553f2277..61d8b918a 100644
--- a/GitAnnex.hs
+++ b/GitAnnex.hs
@@ -5,7 +5,7 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, OverloadedStrings #-}
module GitAnnex where
@@ -34,6 +34,7 @@ import qualified Command.Describe
import qualified Command.InitRemote
import qualified Command.EnableRemote
import qualified Command.Fsck
+import qualified Command.Repair
import qualified Command.Unused
import qualified Command.DropUnused
import qualified Command.AddUnused
@@ -42,8 +43,10 @@ import qualified Command.Lock
import qualified Command.PreCommit
import qualified Command.Find
import qualified Command.Whereis
+import qualified Command.List
import qualified Command.Log
import qualified Command.Merge
+import qualified Command.Info
import qualified Command.Status
import qualified Command.Migrate
import qualified Command.Uninit
@@ -52,10 +55,12 @@ import qualified Command.Untrust
import qualified Command.Semitrust
import qualified Command.Dead
import qualified Command.Group
-import qualified Command.Content
+import qualified Command.Wanted
+import qualified Command.Schedule
import qualified Command.Ungroup
import qualified Command.Vicfg
import qualified Command.Sync
+import qualified Command.Mirror
import qualified Command.AddUrl
#ifdef WITH_FEED
import qualified Command.ImportFeed
@@ -66,6 +71,7 @@ import qualified Command.Map
import qualified Command.Direct
import qualified Command.Indirect
import qualified Command.Upgrade
+import qualified Command.Forget
import qualified Command.Version
import qualified Command.Help
#ifdef WITH_ASSISTANT
@@ -82,6 +88,9 @@ import qualified Command.XMPPGit
import qualified Command.Test
import qualified Command.FuzzTest
#endif
+#ifdef WITH_EKG
+import System.Remote.Monitoring
+#endif
cmds :: [Command]
cmds = concat
@@ -93,6 +102,7 @@ cmds = concat
, Command.Unlock.def
, Command.Lock.def
, Command.Sync.def
+ , Command.Mirror.def
, Command.AddUrl.def
#ifdef WITH_FEED
, Command.ImportFeed.def
@@ -112,7 +122,8 @@ cmds = concat
, Command.Semitrust.def
, Command.Dead.def
, Command.Group.def
- , Command.Content.def
+ , Command.Wanted.def
+ , Command.Schedule.def
, Command.Ungroup.def
, Command.Vicfg.def
, Command.FromKey.def
@@ -124,19 +135,23 @@ cmds = concat
, Command.ReKey.def
, Command.Fix.def
, Command.Fsck.def
+ , Command.Repair.def
, Command.Unused.def
, Command.DropUnused.def
, Command.AddUnused.def
, Command.Find.def
, Command.Whereis.def
+ , Command.List.def
, Command.Log.def
, Command.Merge.def
+ , Command.Info.def
, Command.Status.def
, Command.Migrate.def
, Command.Map.def
, Command.Direct.def
, Command.Indirect.def
, Command.Upgrade.def
+ , Command.Forget.def
, Command.Version.def
, Command.Help.def
#ifdef WITH_ASSISTANT
@@ -159,4 +174,8 @@ header :: String
header = "git-annex command [option ...]"
run :: [String] -> IO ()
-run args = dispatch True args cmds options [] header Git.CurrentRepo.get
+run args = do
+#ifdef WITH_EKG
+ _ <- forkServer "localhost" 4242
+#endif
+ dispatch True args cmds options [] header Git.CurrentRepo.get
diff --git a/GitAnnex/Options.hs b/GitAnnex/Options.hs
index 2cfdfafd2..88fad948a 100644
--- a/GitAnnex/Options.hs
+++ b/GitAnnex/Options.hs
@@ -11,11 +11,13 @@ import System.Console.GetOpt
import Common.Annex
import qualified Git.Config
+import Git.Types
import Command
import Types.TrustLevel
import qualified Annex
import qualified Remote
import qualified Limit
+import qualified Limit.Wanted
import qualified Option
options :: [Option]
@@ -33,30 +35,39 @@ options = Option.common ++
, Option ['x'] ["exclude"] (ReqArg Limit.addExclude paramGlob)
"skip files matching the glob pattern"
, Option ['I'] ["include"] (ReqArg Limit.addInclude paramGlob)
- "don't skip files matching the glob pattern"
+ "limit to files matching the glob pattern"
, Option ['i'] ["in"] (ReqArg Limit.addIn paramRemote)
- "skip files not present in a remote"
+ "match files present in a remote"
, Option ['C'] ["copies"] (ReqArg Limit.addCopies paramNumber)
"skip files with fewer copies"
, Option ['B'] ["inbackend"] (ReqArg Limit.addInBackend paramName)
- "skip files not using a key-value backend"
+ "match files using a key-value backend"
, Option [] ["inallgroup"] (ReqArg Limit.addInAllGroup paramGroup)
- "skip files not present in all remotes in a group"
+ "match files present in all remotes in a group"
, Option [] ["largerthan"] (ReqArg Limit.addLargerThan paramSize)
- "skip files larger than a size"
+ "match files larger than a size"
, Option [] ["smallerthan"] (ReqArg Limit.addSmallerThan paramSize)
- "skip files smaller than a size"
+ "match files smaller than a size"
+ , Option [] ["want-get"] (NoArg Limit.Wanted.addWantGet)
+ "match files the repository wants to get"
+ , Option [] ["want-drop"] (NoArg Limit.Wanted.addWantDrop)
+ "match files the repository wants to drop"
, Option ['T'] ["time-limit"] (ReqArg Limit.addTimeLimit paramTime)
"stop after the specified amount of time"
+ , Option [] ["user-agent"] (ReqArg setuseragent paramName)
+ "override default User-Agent"
, Option [] ["trust-glacier"] (NoArg (Annex.setFlag "trustglacier"))
"Trust Amazon Glacier inventory"
] ++ Option.matcher
where
+ trustArg t = ReqArg (Remote.forceTrust t) paramRemote
setnumcopies v = maybe noop
(\n -> Annex.changeState $ \s -> s { Annex.forcenumcopies = Just n })
(readish v)
- setgitconfig v = Annex.changeGitRepo =<< inRepo (Git.Config.store v)
- trustArg t = ReqArg (Remote.forceTrust t) paramRemote
+ setuseragent v = Annex.changeState $ \s -> s { Annex.useragent = Just v }
+ setgitconfig v = inRepo (Git.Config.store v)
+ >>= pure . (\r -> r { gitGlobalOpts = gitGlobalOpts r ++ [Param "-c", Param v] })
+ >>= Annex.changeGitRepo
keyOptions :: [Option]
keyOptions =
@@ -65,3 +76,12 @@ keyOptions =
, Option ['U'] ["unused"] (NoArg (Annex.setFlag "unused"))
"operate on files found by last run of git-annex unused"
]
+
+fromOption :: Option
+fromOption = Option.field ['f'] "from" paramRemote "source remote"
+
+toOption :: Option
+toOption = Option.field ['t'] "to" paramRemote "destination remote"
+
+fromToOptions :: [Option]
+fromToOptions = [fromOption, toOption]
diff --git a/GitAnnexShell.hs b/GitAnnexShell.hs
index 6f03ac73b..b5f6804e7 100644
--- a/GitAnnexShell.hs
+++ b/GitAnnexShell.hs
@@ -19,6 +19,9 @@ import Annex (setField)
import qualified Option
import Fields
import Utility.UserInfo
+import Remote.GCrypt (getGCryptUUID)
+import qualified Annex
+import Init
import qualified Command.ConfigList
import qualified Command.InAnnex
@@ -27,20 +30,22 @@ import qualified Command.RecvKey
import qualified Command.SendKey
import qualified Command.TransferInfo
import qualified Command.Commit
+import qualified Command.GCryptSetup
cmds_readonly :: [Command]
cmds_readonly = concat
- [ Command.ConfigList.def
- , Command.InAnnex.def
- , Command.SendKey.def
- , Command.TransferInfo.def
+ [ gitAnnexShellCheck Command.ConfigList.def
+ , gitAnnexShellCheck Command.InAnnex.def
+ , gitAnnexShellCheck Command.SendKey.def
+ , gitAnnexShellCheck Command.TransferInfo.def
]
cmds_notreadonly :: [Command]
cmds_notreadonly = concat
- [ Command.RecvKey.def
- , Command.DropKey.def
- , Command.Commit.def
+ [ gitAnnexShellCheck Command.RecvKey.def
+ , gitAnnexShellCheck Command.DropKey.def
+ , gitAnnexShellCheck Command.Commit.def
+ , Command.GCryptSetup.def
]
cmds :: [Command]
@@ -50,17 +55,22 @@ cmds = map adddirparam $ cmds_readonly ++ cmds_notreadonly
options :: [OptDescr (Annex ())]
options = Option.common ++
- [ Option [] ["uuid"] (ReqArg checkuuid paramUUID) "local repository uuid"
+ [ Option [] ["uuid"] (ReqArg checkUUID paramUUID) "local repository uuid"
]
where
- checkuuid expected = getUUID >>= check
+ checkUUID expected = getUUID >>= check
where
check u | u == toUUID expected = noop
- check NoUUID = unexpected "uninitialized repository"
- check u = unexpected $ "UUID " ++ fromUUID u
- unexpected s = error $
- "expected repository UUID " ++
- expected ++ " but found " ++ s
+ check NoUUID = checkGCryptUUID expected
+ check u = unexpectedUUID expected u
+ checkGCryptUUID expected = check =<< getGCryptUUID True =<< gitRepo
+ where
+ check (Just u) | u == toUUID expected = noop
+ check Nothing = unexpected expected "uninitialized repository"
+ check (Just u) = unexpectedUUID expected u
+ unexpectedUUID expected u = unexpected expected $ "UUID " ++ fromUUID u
+ unexpected expected s = error $
+ "expected repository UUID " ++ expected ++ " but found " ++ s
header :: String
header = "git-annex-shell [-c] command [parameters ...] [option ...]"
@@ -180,3 +190,11 @@ checkEnv var = do
Nothing -> noop
Just "" -> noop
Just _ -> error $ "Action blocked by " ++ var
+
+{- Modifies a Command to check that it is run in either a git-annex
+ - repository, or a repository with a gcrypt-id set. -}
+gitAnnexShellCheck :: [Command] -> [Command]
+gitAnnexShellCheck = map $ addCheck okforshell . dontCheck repoExists
+ where
+ okforshell = unlessM (isInitialized <||> isJust . gcryptId <$> Annex.getGitConfig) $
+ error "Not a git-annex or gcrypt repository."
diff --git a/Init.hs b/Init.hs
index 7e7e5041d..453ad5ae9 100644
--- a/Init.hs
+++ b/Init.hs
@@ -12,11 +12,10 @@ module Init (
isInitialized,
initialize,
uninitialize,
- probeCrippledFileSystem
+ probeCrippledFileSystem,
) where
import Common.Annex
-import Utility.Tmp
import Utility.Network
import qualified Annex
import qualified Git
@@ -26,7 +25,6 @@ import qualified Annex.Branch
import Logs.UUID
import Annex.Version
import Annex.UUID
-import Utility.Shell
import Config
import Annex.Direct
import Annex.Content.Direct
@@ -36,6 +34,8 @@ import Backend
import Utility.UserInfo
import Utility.FileMode
#endif
+import Annex.Hook
+import Upgrade
genDescription :: Maybe String -> Annex String
genDescription (Just d) = return d
@@ -53,10 +53,19 @@ genDescription Nothing = do
initialize :: Maybe String -> Annex ()
initialize mdescription = do
prepUUID
- setVersion defaultVersion
- checkCrippledFileSystem
checkFifoSupport
- gitPreCommitHookWrite
+ checkCrippledFileSystem
+ unlessM isBare $
+ hookWrite preCommitHook
+ ifM (crippledFileSystem <&&> not <$> isBare)
+ ( do
+ enableDirectMode
+ setDirect True
+ setVersion directModeVersion
+ , do
+ setVersion defaultVersion
+ setDirect False
+ )
createInodeSentinalFile
u <- getUUID
{- This will make the first commit to git, so ensure git is set up
@@ -67,16 +76,19 @@ initialize mdescription = do
uninitialize :: Annex ()
uninitialize = do
- gitPreCommitHookUnWrite
+ hookUnWrite preCommitHook
removeRepoUUID
removeVersion
{- Will automatically initialize if there is already a git-annex
- branch from somewhere. Otherwise, require a manual init
- to avoid git-annex accidentially being run in git
- - repos that did not intend to use it. -}
+ - repos that did not intend to use it.
+ -
+ - Checks repository version and handles upgrades too.
+ -}
ensureInitialized :: Annex ()
-ensureInitialized = getVersion >>= maybe needsinit checkVersion
+ensureInitialized = getVersion >>= maybe needsinit checkUpgrade
where
needsinit = ifM Annex.Branch.hasSibling
( initialize Nothing
@@ -87,45 +99,8 @@ ensureInitialized = getVersion >>= maybe needsinit checkVersion
isInitialized :: Annex Bool
isInitialized = maybe Annex.Branch.hasSibling (const $ return True) =<< getVersion
-{- set up a git pre-commit hook, if one is not already present -}
-gitPreCommitHookWrite :: Annex ()
-gitPreCommitHookWrite = unlessBare $ do
- hook <- preCommitHook
- ifM (liftIO $ doesFileExist hook)
- ( do
- content <- liftIO $ readFile hook
- when (content /= preCommitScript) $
- warning $ "pre-commit hook (" ++ hook ++ ") already exists, not configuring"
- , unlessM crippledFileSystem $
- liftIO $ do
- viaTmp writeFile hook preCommitScript
- p <- getPermissions hook
- setPermissions hook $ p {executable = True}
- )
-
-gitPreCommitHookUnWrite :: Annex ()
-gitPreCommitHookUnWrite = unlessBare $ do
- hook <- preCommitHook
- whenM (liftIO $ doesFileExist hook) $
- ifM (liftIO $ (==) preCommitScript <$> readFile hook)
- ( liftIO $ removeFile hook
- , warning $ "pre-commit hook (" ++ hook ++
- ") contents modified; not deleting." ++
- " Edit it to remove call to git annex."
- )
-
-unlessBare :: Annex () -> Annex ()
-unlessBare = unlessM $ fromRepo Git.repoIsLocalBare
-
-preCommitHook :: Annex FilePath
-preCommitHook = (</>) <$> fromRepo Git.localGitDir <*> pure "hooks/pre-commit"
-
-preCommitScript :: String
-preCommitScript = unlines
- [ shebang_local
- , "# automatically configured by git-annex"
- , "git annex pre-commit ."
- ]
+isBare :: Annex Bool
+isBare = fromRepo Git.repoIsLocalBare
{- A crippled filesystem is one that does not allow making symlinks,
- or removing write access from files. -}
@@ -158,25 +133,15 @@ checkCrippledFileSystem = whenM probeCrippledFileSystem $ do
warning "Detected a crippled filesystem."
setCrippledFileSystem True
- {- Normally git disables core.symlinks itself when the filesystem does
- - not support them, but in Cygwin, git does support symlinks, while
- - git-annex, not linking with Cygwin, does not. -}
+ {- Normally git disables core.symlinks itself when the
+ - filesystem does not support them, but in Cygwin, git
+ - does support symlinks, while git-annex, not linking
+ - with Cygwin, does not. -}
whenM (coreSymlinks <$> Annex.getGitConfig) $ do
warning "Disabling core.symlinks."
setConfig (ConfigKey "core.symlinks")
(Git.Config.boolConfig False)
- unlessBare $ do
- unlessM isDirect $ do
- warning "Enabling direct mode."
- top <- fromRepo Git.repoPath
- (l, clean) <- inRepo $ Git.LsFiles.inRepo [top]
- forM_ l $ \f ->
- maybe noop (`toDirect` f) =<< isAnnexLink f
- void $ liftIO clean
- setDirect True
- setVersion directModeVersion
-
probeFifoSupport :: Annex Bool
probeFifoSupport = do
#ifdef mingw32_HOST_OS
@@ -199,3 +164,12 @@ checkFifoSupport = unlessM probeFifoSupport $ do
warning "Detected a filesystem without fifo support."
warning "Disabling ssh connection caching."
setConfig (annexConfig "sshcaching") (Git.Config.boolConfig False)
+
+enableDirectMode :: Annex ()
+enableDirectMode = unlessM isDirect $ do
+ warning "Enabling direct mode."
+ top <- fromRepo Git.repoPath
+ (l, clean) <- inRepo $ Git.LsFiles.inRepo [top]
+ forM_ l $ \f ->
+ maybe noop (`toDirect` f) =<< isAnnexLink f
+ void $ liftIO clean
diff --git a/Limit.hs b/Limit.hs
index 71dbce168..f3586e029 100644
--- a/Limit.hs
+++ b/Limit.hs
@@ -27,6 +27,7 @@ import Types.TrustLevel
import Types.Key
import Types.Group
import Types.FileMatcher
+import Types.Limit
import Logs.Group
import Utility.HumanTime
import Utility.DataUnits
@@ -41,10 +42,6 @@ import Types.FileMatcher
#endif
#endif
-type MatchFiles = AssumeNotPresent -> FileInfo -> Annex Bool
-type MkLimit = String -> Either String MatchFiles
-type AssumeNotPresent = S.Set UUID
-
{- Checks if there are user-specified limits. -}
limited :: Annex Bool
limited = (not . Utility.Matcher.isEmpty) <$> getMatcher'
@@ -238,7 +235,8 @@ limitSize vs s = case readSize dataUnits s of
addTimeLimit :: String -> Annex ()
addTimeLimit s = do
- let seconds = fromMaybe (error "bad time-limit") $ parseDuration s
+ let seconds = maybe (error "bad time-limit") durationToPOSIXTime $
+ parseDuration s
start <- liftIO getPOSIXTime
let cutoff = start + seconds
addLimit $ Right $ const $ const $ do
diff --git a/Limit/Wanted.hs b/Limit/Wanted.hs
new file mode 100644
index 000000000..ed4529dea
--- /dev/null
+++ b/Limit/Wanted.hs
@@ -0,0 +1,21 @@
+{- git-annex limits by wanted status
+ -
+ - Copyright 2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Limit.Wanted where
+
+import Common.Annex
+import Annex.Wanted
+import Limit
+import Types.FileMatcher
+
+addWantGet :: Annex ()
+addWantGet = addLimit $ Right $ const $
+ \fileinfo -> wantGet False (Just $ matchFile fileinfo)
+
+addWantDrop :: Annex ()
+addWantDrop = addLimit $ Right $ const $
+ \fileinfo -> wantDrop False Nothing (Just $ matchFile fileinfo)
diff --git a/Locations.hs b/Locations.hs
index 1cbbb9886..47a009590 100644
--- a/Locations.hs
+++ b/Locations.hs
@@ -1,6 +1,6 @@
{- git-annex file locations
-
- - Copyright 2010-2011 Joey Hess <joey@kitenet.net>
+ - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -10,6 +10,8 @@ module Locations (
fileKey,
keyPaths,
keyPath,
+ annexDir,
+ objectDir,
gitAnnexLocation,
gitAnnexLink,
gitAnnexMapping,
@@ -26,6 +28,8 @@ module Locations (
gitAnnexBadLocation,
gitAnnexUnusedLog,
gitAnnexFsckState,
+ gitAnnexFsckResultsLog,
+ gitAnnexScheduleState,
gitAnnexTransferDir,
gitAnnexCredsDir,
gitAnnexFeedStateDir,
@@ -34,7 +38,8 @@ module Locations (
gitAnnexJournalDir,
gitAnnexJournalLock,
gitAnnexIndex,
- gitAnnexIndexLock,
+ gitAnnexIndexStatus,
+ gitAnnexIgnoredRefs,
gitAnnexPidFile,
gitAnnexDaemonStatusFile,
gitAnnexLogFile,
@@ -49,6 +54,7 @@ module Locations (
annexHashes,
hashDirMixed,
hashDirLower,
+ preSanitizeKeyName,
prop_idempotent_fileKey
) where
@@ -56,10 +62,12 @@ module Locations (
import Data.Bits
import Data.Word
import Data.Hash.MD5
+import Data.Char
import Common
import Types
import Types.Key
+import Types.UUID
import qualified Git
{- Conventions:
@@ -187,6 +195,15 @@ gitAnnexUnusedLog prefix r = gitAnnexDir r </> (prefix ++ "unused")
gitAnnexFsckState :: Git.Repo -> FilePath
gitAnnexFsckState r = gitAnnexDir r </> "fsckstate"
+{- .git/annex/fsckresults/uuid is used to store results of git fscks -}
+gitAnnexFsckResultsLog :: UUID -> Git.Repo -> FilePath
+gitAnnexFsckResultsLog u r = gitAnnexDir r </> "fsckresults" </> fromUUID u
+
+{- .git/annex/schedulestate is used to store information about when
+ - scheduled jobs were last run. -}
+gitAnnexScheduleState :: Git.Repo -> FilePath
+gitAnnexScheduleState r = gitAnnexDir r </> "schedulestate"
+
{- .git/annex/creds/ is used to store credentials to access some special
- remotes. -}
gitAnnexCredsDir :: Git.Repo -> FilePath
@@ -221,9 +238,16 @@ gitAnnexJournalLock r = gitAnnexDir r </> "journal.lck"
gitAnnexIndex :: Git.Repo -> FilePath
gitAnnexIndex r = gitAnnexDir r </> "index"
-{- Lock file for .git/annex/index. -}
-gitAnnexIndexLock :: Git.Repo -> FilePath
-gitAnnexIndexLock r = gitAnnexDir r </> "index.lck"
+{- Holds the ref of the git-annex branch that the index was last updated to.
+ -
+ - The .lck in the name is a historical accident; this is not used as a
+ - lock. -}
+gitAnnexIndexStatus :: Git.Repo -> FilePath
+gitAnnexIndexStatus r = gitAnnexDir r </> "index.lck"
+
+{- List of refs that should not be merged into the git-annex branch. -}
+gitAnnexIgnoredRefs :: Git.Repo -> FilePath
+gitAnnexIgnoredRefs r = gitAnnexDir r </> "ignoredrefs"
{- Pid file for daemon mode. -}
gitAnnexPidFile :: Git.Repo -> FilePath
@@ -275,6 +299,32 @@ gitAnnexAssistantDefaultDir = "annex"
isLinkToAnnex :: FilePath -> Bool
isLinkToAnnex s = (pathSeparator:objectDir) `isInfixOf` s
+{- Sanitizes a String that will be used as part of a Key's keyName,
+ - dealing with characters that cause problems on substandard filesystems.
+ -
+ - This is used when a new Key is initially being generated, eg by getKey.
+ - Unlike keyFile and fileKey, it does not need to be a reversable
+ - escaping. Also, it's ok to change this to add more problimatic
+ - characters later. Unlike changing keyFile, which could result in the
+ - filenames used for existing keys changing and contents getting lost.
+ -
+ - It is, however, important that the input and output of this function
+ - have a 1:1 mapping, to avoid two different inputs from mapping to the
+ - same key.
+ -}
+preSanitizeKeyName :: String -> String
+preSanitizeKeyName = concatMap escape
+ where
+ escape c
+ | isAsciiUpper c || isAsciiLower c || isDigit c = [c]
+ | c `elem` ".-_ " = [c] -- common, assumed safe
+ | c `elem` "/%:" = [c] -- handled by keyFile
+ -- , is safe and uncommon, so will be used to escape
+ -- other characters. By itself, it is escaped to
+ -- doubled form.
+ | c == ',' = ",,"
+ | otherwise = ',' : show(ord(c))
+
{- Converts a key into a filename fragment without any directory.
-
- Escape "/" in the key name, to keep a flat tree of files and avoid
@@ -284,13 +334,30 @@ isLinkToAnnex s = (pathSeparator:objectDir) `isInfixOf` s
- a slash
- "%" is escaped to "&s", and "&" to "&a"; this ensures that the mapping
- is one to one.
- - ":" is escaped to "&c", because despite it being 2011, people still care
- - about FAT.
+ - ":" is escaped to "&c", because it seemed like a good idea at the time.
+ -
+ - Changing what this function escapes and how is not a good idea, as it
+ - can cause existing objects to get lost.
-}
keyFile :: Key -> FilePath
keyFile key = replace "/" "%" $ replace ":" "&c" $
replace "%" "&s" $ replace "&" "&a" $ key2file key
+{- Reverses keyFile, converting a filename fragment (ie, the basename of
+ - the symlink target) into a key. -}
+fileKey :: FilePath -> Maybe Key
+fileKey file = file2key $
+ replace "&a" "&" $ replace "&s" "%" $
+ replace "&c" ":" $ replace "%" "/" file
+
+{- for quickcheck -}
+prop_idempotent_fileKey :: String -> Bool
+prop_idempotent_fileKey s
+ | null s = True -- it's not legal for a key to have no keyName
+ | otherwise= Just k == fileKey (keyFile k)
+ where
+ k = stubKey { keyName = s, keyBackendName = "test" }
+
{- A location to store a key on the filesystem. A directory hash is used,
- to protect against filesystems that dislike having many items in a
- single directory.
@@ -307,19 +374,6 @@ keyPath key hasher = hasher key </> f </> f
keyPaths :: Key -> [FilePath]
keyPaths key = map (keyPath key) annexHashes
-{- Reverses keyFile, converting a filename fragment (ie, the basename of
- - the symlink target) into a key. -}
-fileKey :: FilePath -> Maybe Key
-fileKey file = file2key $
- replace "&a" "&" $ replace "&s" "%" $
- replace "&c" ":" $ replace "%" "/" file
-
-{- for quickcheck -}
-prop_idempotent_fileKey :: String -> Bool
-prop_idempotent_fileKey s = Just k == fileKey (keyFile k)
- where
- k = stubKey { keyName = s, keyBackendName = "test" }
-
{- Two different directory hashes may be used. The mixed case hash
- came first, and is fine, except for the problem of case-strict
- filesystems such as Linux VFAT (mounted with shortname=mixed),
diff --git a/Logs.hs b/Logs.hs
new file mode 100644
index 000000000..4386b7fd7
--- /dev/null
+++ b/Logs.hs
@@ -0,0 +1,114 @@
+{- git-annex log file names
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs where
+
+import Common.Annex
+import Types.Key
+
+data LogVariety = UUIDBasedLog | PresenceLog Key
+ deriving (Show)
+
+{- Converts a path from the git-annex branch into one of the varieties
+ - of logs used by git-annex, if it's a known path. -}
+getLogVariety :: FilePath -> Maybe LogVariety
+getLogVariety f
+ | f `elem` uuidBasedLogs = Just UUIDBasedLog
+ | otherwise = PresenceLog <$> firstJust (presenceLogs f)
+
+{- All the uuid-based logs stored in the git-annex branch. -}
+uuidBasedLogs :: [FilePath]
+uuidBasedLogs =
+ [ uuidLog
+ , remoteLog
+ , trustLog
+ , groupLog
+ , preferredContentLog
+ , scheduleLog
+ ]
+
+{- All the ways to get a key from a presence log file -}
+presenceLogs :: FilePath -> [Maybe Key]
+presenceLogs f =
+ [ urlLogFileKey f
+ , locationLogFileKey f
+ ]
+
+uuidLog :: FilePath
+uuidLog = "uuid.log"
+
+remoteLog :: FilePath
+remoteLog = "remote.log"
+
+trustLog :: FilePath
+trustLog = "trust.log"
+
+groupLog :: FilePath
+groupLog = "group.log"
+
+preferredContentLog :: FilePath
+preferredContentLog = "preferred-content.log"
+
+scheduleLog :: FilePath
+scheduleLog = "schedule.log"
+
+{- The pathname of the location log file for a given key. -}
+locationLogFile :: Key -> String
+locationLogFile key = hashDirLower key ++ keyFile key ++ ".log"
+
+{- Converts a pathname into a key if it's a location log. -}
+locationLogFileKey :: FilePath -> Maybe Key
+locationLogFileKey path
+ | ["remote", "web"] `isPrefixOf` splitDirectories dir = Nothing
+ | ext == ".log" = fileKey base
+ | otherwise = Nothing
+ where
+ (dir, file) = splitFileName path
+ (base, ext) = splitAt (length file - 4) file
+
+{- The filename of the url log for a given key. -}
+urlLogFile :: Key -> FilePath
+urlLogFile key = hashDirLower key </> keyFile key ++ urlLogExt
+
+{- Old versions stored the urls elsewhere. -}
+oldurlLogs :: Key -> [FilePath]
+oldurlLogs key =
+ [ "remote/web" </> hashDirLower key </> key2file key ++ ".log"
+ , "remote/web" </> hashDirLower key </> keyFile key ++ ".log"
+ ]
+
+urlLogExt :: String
+urlLogExt = ".log.web"
+
+{- Converts a url log file into a key.
+ - (Does not work on oldurlLogs.) -}
+urlLogFileKey :: FilePath -> Maybe Key
+urlLogFileKey path
+ | ext == urlLogExt = fileKey base
+ | otherwise = Nothing
+ where
+ file = takeFileName path
+ (base, ext) = splitAt (length file - extlen) file
+ extlen = length urlLogExt
+
+{- Does not work on oldurllogs. -}
+isUrlLog :: FilePath -> Bool
+isUrlLog file = urlLogExt `isSuffixOf` file
+
+prop_logs_sane :: Key -> Bool
+prop_logs_sane dummykey = all id
+ [ isNothing (getLogVariety "unknown")
+ , expect isUUIDBasedLog (getLogVariety uuidLog)
+ , expect isPresenceLog (getLogVariety $ locationLogFile dummykey)
+ , expect isPresenceLog (getLogVariety $ urlLogFile dummykey)
+ ]
+ where
+ expect = maybe False
+ isUUIDBasedLog UUIDBasedLog = True
+ isUUIDBasedLog _ = False
+ isPresenceLog (PresenceLog k) = k == dummykey
+ isPresenceLog _ = False
diff --git a/Logs/FsckResults.hs b/Logs/FsckResults.hs
new file mode 100644
index 000000000..75ed7389c
--- /dev/null
+++ b/Logs/FsckResults.hs
@@ -0,0 +1,43 @@
+{- git-annex fsck results log files
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.FsckResults (
+ writeFsckResults,
+ readFsckResults
+) where
+
+import Common.Annex
+import Utility.Tmp
+import Git.Fsck
+import Git.Types
+
+import qualified Data.Set as S
+
+writeFsckResults :: UUID -> FsckResults -> Annex ()
+writeFsckResults u fsckresults = do
+ logfile <- fromRepo $ gitAnnexFsckResultsLog u
+ liftIO $
+ case fsckresults of
+ Nothing -> store S.empty logfile
+ Just s
+ | S.null s -> nukeFile logfile
+ | otherwise -> store s logfile
+ where
+ store s logfile = do
+ createDirectoryIfMissing True (parentDir logfile)
+ liftIO $ viaTmp writeFile logfile $ serialize s
+ serialize = unlines . map show . S.toList
+
+readFsckResults :: UUID -> Annex FsckResults
+readFsckResults u = do
+ logfile <- fromRepo $ gitAnnexFsckResultsLog u
+ liftIO $ catchDefaultIO (Just S.empty) $
+ deserialize <$> readFile logfile
+ where
+ deserialize l =
+ let s = S.fromList $ map Ref $ lines l
+ in if S.null s then Nothing else Just s
diff --git a/Logs/Group.hs b/Logs/Group.hs
index ee3b75b86..3f88b627d 100644
--- a/Logs/Group.hs
+++ b/Logs/Group.hs
@@ -21,16 +21,13 @@ import qualified Data.Set as S
import Data.Time.Clock.POSIX
import Common.Annex
+import Logs
import qualified Annex.Branch
import qualified Annex
import Logs.UUIDBased
import Types.Group
import Types.StandardGroups
-{- Filename of group.log. -}
-groupLog :: FilePath
-groupLog = "group.log"
-
{- Returns the groups of a given repo UUID. -}
lookupGroups :: UUID -> Annex (S.Set Group)
lookupGroups u = (fromMaybe S.empty . M.lookup u) . groupsByUUID <$> groupMap
diff --git a/Logs/Location.hs b/Logs/Location.hs
index 0f57b6663..f751c00de 100644
--- a/Logs/Location.hs
+++ b/Logs/Location.hs
@@ -20,36 +20,35 @@ module Logs.Location (
loggedLocations,
loggedKeys,
loggedKeysFor,
- logFile,
- logFileKey
) where
import Common.Annex
import qualified Annex.Branch
+import Logs
import Logs.Presence
import Annex.UUID
{- Log a change in the presence of a key's value in current repository. -}
logStatus :: Key -> LogStatus -> Annex ()
-logStatus key status = do
+logStatus key s = do
u <- getUUID
- logChange key u status
+ logChange key u s
{- Log a change in the presence of a key's value in a repository. -}
logChange :: Key -> UUID -> LogStatus -> Annex ()
-logChange key (UUID u) s = addLog (logFile key) =<< logNow s u
+logChange key (UUID u) s = addLog (locationLogFile key) =<< logNow s u
logChange _ NoUUID _ = noop
{- Returns a list of repository UUIDs that, according to the log, have
- the value of a key.
-}
loggedLocations :: Key -> Annex [UUID]
-loggedLocations key = map toUUID <$> (currentLog . logFile) key
+loggedLocations key = map toUUID <$> (currentLog . locationLogFile) key
{- Finds all keys that have location log information.
- (There may be duplicate keys in the list.) -}
loggedKeys :: Annex [Key]
-loggedKeys = mapMaybe (logFileKey . takeFileName) <$> Annex.Branch.files
+loggedKeys = mapMaybe locationLogFileKey <$> Annex.Branch.files
{- Finds all keys that have location log information indicating
- they are present for the specified repository. -}
@@ -62,15 +61,3 @@ loggedKeysFor u = filterM isthere =<< loggedKeys
us <- loggedLocations k
let !there = u `elem` us
return there
-
-{- The filename of the log file for a given key. -}
-logFile :: Key -> String
-logFile key = hashDirLower key ++ keyFile key ++ ".log"
-
-{- Converts a log filename into a key. -}
-logFileKey :: FilePath -> Maybe Key
-logFileKey file
- | ext == ".log" = fileKey base
- | otherwise = Nothing
- where
- (base, ext) = splitAt (length file - 4) file
diff --git a/Logs/PreferredContent.hs b/Logs/PreferredContent.hs
index 8005fc0d3..57367148c 100644
--- a/Logs/PreferredContent.hs
+++ b/Logs/PreferredContent.hs
@@ -24,21 +24,18 @@ import Data.Time.Clock.POSIX
import Common.Annex
import qualified Annex.Branch
import qualified Annex
+import Logs
import Logs.UUIDBased
-import Limit
import qualified Utility.Matcher
import Annex.FileMatcher
import Annex.UUID
+import Types.Limit
import Types.Group
import Types.Remote (RemoteConfig)
import Logs.Group
import Logs.Remote
import Types.StandardGroups
-{- Filename of preferred-content.log. -}
-preferredContentLog :: FilePath
-preferredContentLog = "preferred-content.log"
-
{- Changes the preferred content configuration of a remote. -}
preferredContentSet :: UUID -> String -> Annex ()
preferredContentSet uuid@(UUID _) val = do
diff --git a/Logs/Presence.hs b/Logs/Presence.hs
index ec5cec209..516d59618 100644
--- a/Logs/Presence.hs
+++ b/Logs/Presence.hs
@@ -12,36 +12,18 @@
-}
module Logs.Presence (
- LogStatus(..),
- LogLine(LogLine),
+ module X,
addLog,
readLog,
- getLog,
- parseLog,
- showLog,
logNow,
- compactLog,
- currentLog,
- prop_parse_show_log,
+ currentLog
) where
import Data.Time.Clock.POSIX
-import Data.Time
-import System.Locale
-import qualified Data.Map as M
+import Logs.Presence.Pure as X
import Common.Annex
import qualified Annex.Branch
-import Utility.QuickCheck
-
-data LogLine = LogLine {
- date :: POSIXTime,
- status :: LogStatus,
- info :: String
-} deriving (Eq, Show)
-
-data LogStatus = InfoPresent | InfoMissing
- deriving (Eq, Show, Bounded, Enum)
addLog :: FilePath -> LogLine -> Annex ()
addLog file line = Annex.Branch.change file $ \s ->
@@ -52,29 +34,6 @@ addLog file line = Annex.Branch.change file $ \s ->
readLog :: FilePath -> Annex [LogLine]
readLog = parseLog <$$> Annex.Branch.get
-{- Parses a log file. Unparseable lines are ignored. -}
-parseLog :: String -> [LogLine]
-parseLog = mapMaybe parseline . lines
- where
- parseline l = LogLine
- <$> (utcTimeToPOSIXSeconds <$> parseTime defaultTimeLocale "%s%Qs" d)
- <*> parsestatus s
- <*> pure rest
- where
- (d, pastd) = separate (== ' ') l
- (s, rest) = separate (== ' ') pastd
- parsestatus "1" = Just InfoPresent
- parsestatus "0" = Just InfoMissing
- parsestatus _ = Nothing
-
-{- Generates a log file. -}
-showLog :: [LogLine] -> String
-showLog = unlines . map genline
- where
- genline (LogLine d s i) = unwords [show d, genstatus s, i]
- genstatus InfoPresent = "1"
- genstatus InfoMissing = "0"
-
{- Generates a new LogLine with the current date. -}
logNow :: LogStatus -> String -> Annex LogLine
logNow s i = do
@@ -84,39 +43,3 @@ logNow s i = do
{- Reads a log and returns only the info that is still in effect. -}
currentLog :: FilePath -> Annex [String]
currentLog file = map info . filterPresent <$> readLog file
-
-{- Given a log, returns only the info that is are still in effect. -}
-getLog :: String -> [String]
-getLog = map info . filterPresent . parseLog
-
-{- Returns the info from LogLines that are in effect. -}
-filterPresent :: [LogLine] -> [LogLine]
-filterPresent = filter (\l -> InfoPresent == status l) . compactLog
-
-{- Compacts a set of logs, returning a subset that contains the current
- - status. -}
-compactLog :: [LogLine] -> [LogLine]
-compactLog = M.elems . foldr mapLog M.empty
-
-type LogMap = M.Map String LogLine
-
-{- Inserts a log into a map of logs, if the log has better (ie, newer)
- - information than the other logs in the map -}
-mapLog :: LogLine -> LogMap -> LogMap
-mapLog l m
- | better = M.insert i l m
- | otherwise = m
- where
- better = maybe True newer $ M.lookup i m
- newer l' = date l' <= date l
- i = info l
-
-instance Arbitrary LogLine where
- arbitrary = LogLine
- <$> arbitrary
- <*> elements [minBound..maxBound]
- <*> arbitrary `suchThat` ('\n' `notElem`)
-
-prop_parse_show_log :: [LogLine] -> Bool
-prop_parse_show_log l = parseLog (showLog l) == l
-
diff --git a/Logs/Presence/Pure.hs b/Logs/Presence/Pure.hs
new file mode 100644
index 000000000..ffeb78b26
--- /dev/null
+++ b/Logs/Presence/Pure.hs
@@ -0,0 +1,84 @@
+{- git-annex presence log, pure operations
+ -
+ - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.Presence.Pure where
+
+import Data.Time.Clock.POSIX
+import Data.Time
+import System.Locale
+import qualified Data.Map as M
+
+import Common.Annex
+import Utility.QuickCheck
+
+data LogLine = LogLine {
+ date :: POSIXTime,
+ status :: LogStatus,
+ info :: String
+} deriving (Eq, Show)
+
+data LogStatus = InfoPresent | InfoMissing
+ deriving (Eq, Show, Bounded, Enum)
+
+{- Parses a log file. Unparseable lines are ignored. -}
+parseLog :: String -> [LogLine]
+parseLog = mapMaybe parseline . lines
+ where
+ parseline l = LogLine
+ <$> (utcTimeToPOSIXSeconds <$> parseTime defaultTimeLocale "%s%Qs" d)
+ <*> parsestatus s
+ <*> pure rest
+ where
+ (d, pastd) = separate (== ' ') l
+ (s, rest) = separate (== ' ') pastd
+ parsestatus "1" = Just InfoPresent
+ parsestatus "0" = Just InfoMissing
+ parsestatus _ = Nothing
+
+{- Generates a log file. -}
+showLog :: [LogLine] -> String
+showLog = unlines . map genline
+ where
+ genline (LogLine d s i) = unwords [show d, genstatus s, i]
+ genstatus InfoPresent = "1"
+ genstatus InfoMissing = "0"
+
+{- Given a log, returns only the info that is are still in effect. -}
+getLog :: String -> [String]
+getLog = map info . filterPresent . parseLog
+
+{- Returns the info from LogLines that are in effect. -}
+filterPresent :: [LogLine] -> [LogLine]
+filterPresent = filter (\l -> InfoPresent == status l) . compactLog
+
+{- Compacts a set of logs, returning a subset that contains the current
+ - status. -}
+compactLog :: [LogLine] -> [LogLine]
+compactLog = M.elems . foldr mapLog M.empty
+
+type LogMap = M.Map String LogLine
+
+{- Inserts a log into a map of logs, if the log has better (ie, newer)
+ - information than the other logs in the map -}
+mapLog :: LogLine -> LogMap -> LogMap
+mapLog l m
+ | better = M.insert i l m
+ | otherwise = m
+ where
+ better = maybe True newer $ M.lookup i m
+ newer l' = date l' <= date l
+ i = info l
+
+instance Arbitrary LogLine where
+ arbitrary = LogLine
+ <$> arbitrary
+ <*> elements [minBound..maxBound]
+ <*> arbitrary `suchThat` ('\n' `notElem`)
+
+prop_parse_show_log :: [LogLine] -> Bool
+prop_parse_show_log l = parseLog (showLog l) == l
+
diff --git a/Logs/Remote.hs b/Logs/Remote.hs
index 89792b054..48ee9eb60 100644
--- a/Logs/Remote.hs
+++ b/Logs/Remote.hs
@@ -25,12 +25,9 @@ import Data.Char
import Common.Annex
import qualified Annex.Branch
import Types.Remote
+import Logs
import Logs.UUIDBased
-{- Filename of remote.log. -}
-remoteLog :: FilePath
-remoteLog = "remote.log"
-
{- Adds or updates a remote's config in the log. -}
configSet :: UUID -> RemoteConfig -> Annex ()
configSet u c = do
diff --git a/Logs/Schedule.hs b/Logs/Schedule.hs
new file mode 100644
index 000000000..1d78467bb
--- /dev/null
+++ b/Logs/Schedule.hs
@@ -0,0 +1,72 @@
+{- git-annex scheduled activities log
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.Schedule (
+ scheduleLog,
+ scheduleSet,
+ scheduleAdd,
+ scheduleRemove,
+ scheduleChange,
+ scheduleGet,
+ scheduleMap,
+ getLastRunTimes,
+ setLastRunTime,
+) where
+
+import qualified Data.Map as M
+import qualified Data.Set as S
+import Data.Time.Clock.POSIX
+import Data.Time.LocalTime
+
+import Common.Annex
+import Types.ScheduledActivity
+import qualified Annex.Branch
+import Logs
+import Logs.UUIDBased
+import Utility.Tmp
+
+scheduleSet :: UUID -> [ScheduledActivity] -> Annex ()
+scheduleSet uuid@(UUID _) activities = do
+ ts <- liftIO getPOSIXTime
+ Annex.Branch.change scheduleLog $
+ showLog id . changeLog ts uuid val . parseLog Just
+ where
+ val = fromScheduledActivities activities
+scheduleSet NoUUID _ = error "unknown UUID; cannot modify"
+
+scheduleMap :: Annex (M.Map UUID [ScheduledActivity])
+scheduleMap = simpleMap
+ . parseLogWithUUID parser
+ <$> Annex.Branch.get scheduleLog
+ where
+ parser _uuid = eitherToMaybe . parseScheduledActivities
+
+scheduleGet :: UUID -> Annex (S.Set ScheduledActivity)
+scheduleGet u = do
+ m <- scheduleMap
+ return $ maybe S.empty S.fromList (M.lookup u m)
+
+scheduleRemove :: UUID -> ScheduledActivity -> Annex ()
+scheduleRemove u activity = scheduleChange u $ S.delete activity
+
+scheduleAdd :: UUID -> ScheduledActivity -> Annex ()
+scheduleAdd u activity = scheduleChange u $ S.insert activity
+
+scheduleChange :: UUID -> (S.Set ScheduledActivity -> S.Set ScheduledActivity) -> Annex ()
+scheduleChange u a = scheduleSet u . S.toList . a =<< scheduleGet u
+
+getLastRunTimes :: Annex (M.Map ScheduledActivity LocalTime)
+getLastRunTimes = do
+ f <- fromRepo gitAnnexScheduleState
+ liftIO $ fromMaybe M.empty
+ <$> catchDefaultIO Nothing (readish <$> readFile f)
+
+setLastRunTime :: ScheduledActivity -> LocalTime -> Annex ()
+setLastRunTime activity lastrun = do
+ f <- fromRepo gitAnnexScheduleState
+ liftIO . viaTmp writeFile f . show . M.insert activity lastrun
+ =<< getLastRunTimes
diff --git a/Logs/Transfer.hs b/Logs/Transfer.hs
index 13f94ea20..24fb940d5 100644
--- a/Logs/Transfer.hs
+++ b/Logs/Transfer.hs
@@ -262,6 +262,12 @@ getFailedTransfers u = catMaybes <$> (liftIO . getpairs =<< concat <$> findfiles
findfiles = liftIO . mapM dirContentsRecursive
=<< mapM (fromRepo . failedTransferDir u) [Download, Upload]
+clearFailedTransfers :: UUID -> Annex [(Transfer, TransferInfo)]
+clearFailedTransfers u = do
+ failed <- getFailedTransfers u
+ mapM_ (removeFailedTransfer . fst) failed
+ return failed
+
removeFailedTransfer :: Transfer -> Annex ()
removeFailedTransfer t = do
f <- fromRepo $ failedTransferFile t
diff --git a/Logs/Transitions.hs b/Logs/Transitions.hs
new file mode 100644
index 000000000..64e9d3344
--- /dev/null
+++ b/Logs/Transitions.hs
@@ -0,0 +1,86 @@
+{- git-annex transitions log
+ -
+ - This is used to record transitions that have been performed on the
+ - git-annex branch, and when the transition was first started.
+ -
+ - We can quickly detect when the local branch has already had an transition
+ - done that is listed in the remote branch by checking that the local
+ - branch contains the same transition, with the same or newer start time.
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.Transitions where
+
+import Data.Time.Clock.POSIX
+import Data.Time
+import System.Locale
+import qualified Data.Set as S
+
+import Common.Annex
+
+transitionsLog :: FilePath
+transitionsLog = "transitions.log"
+
+data Transition
+ = ForgetGitHistory
+ | ForgetDeadRemotes
+ deriving (Show, Ord, Eq, Read)
+
+data TransitionLine = TransitionLine
+ { transitionStarted :: POSIXTime
+ , transition :: Transition
+ } deriving (Show, Ord, Eq)
+
+type Transitions = S.Set TransitionLine
+
+describeTransition :: Transition -> String
+describeTransition ForgetGitHistory = "forget git history"
+describeTransition ForgetDeadRemotes = "forget dead remotes"
+
+noTransitions :: Transitions
+noTransitions = S.empty
+
+addTransition :: POSIXTime -> Transition -> Transitions -> Transitions
+addTransition ts t = S.insert $ TransitionLine ts t
+
+showTransitions :: Transitions -> String
+showTransitions = unlines . map showTransitionLine . S.elems
+
+{- If the log contains new transitions we don't support, returns Nothing. -}
+parseTransitions :: String -> Maybe Transitions
+parseTransitions = check . map parseTransitionLine . lines
+ where
+ check l
+ | all isJust l = Just $ S.fromList $ catMaybes l
+ | otherwise = Nothing
+
+parseTransitionsStrictly :: String -> String -> Transitions
+parseTransitionsStrictly source = fromMaybe badsource . parseTransitions
+ where
+ badsource = error $ "unknown transitions listed in " ++ source ++ "; upgrade git-annex!"
+
+showTransitionLine :: TransitionLine -> String
+showTransitionLine (TransitionLine ts t) = unwords [show t, show ts]
+
+parseTransitionLine :: String -> Maybe TransitionLine
+parseTransitionLine s = TransitionLine <$> pdate ds <*> readish ts
+ where
+ ws = words s
+ ts = Prelude.head ws
+ ds = unwords $ Prelude.tail ws
+ pdate = utcTimeToPOSIXSeconds <$$> parseTime defaultTimeLocale "%s%Qs"
+
+combineTransitions :: [Transitions] -> Transitions
+combineTransitions = S.unions
+
+transitionList :: Transitions -> [Transition]
+transitionList = map transition . S.elems
+
+{- Typically ran with Annex.Branch.change, but we can't import Annex.Branch
+ - here since it depends on this module. -}
+recordTransitions :: (FilePath -> (String -> String) -> Annex ()) -> Transitions -> Annex ()
+recordTransitions changer t = changer transitionsLog $
+ showTransitions . S.union t . parseTransitionsStrictly "local"
diff --git a/Logs/Trust.hs b/Logs/Trust.hs
index eb6e42ad7..c6f0ad3ab 100644
--- a/Logs/Trust.hs
+++ b/Logs/Trust.hs
@@ -6,6 +6,7 @@
-}
module Logs.Trust (
+ module X,
trustLog,
TrustLevel(..),
trustGet,
@@ -16,8 +17,6 @@ module Logs.Trust (
lookupTrust,
trustMapLoad,
trustMapRaw,
-
- prop_parse_show_TrustLog,
) where
import qualified Data.Map as M
@@ -27,13 +26,11 @@ import Common.Annex
import Types.TrustLevel
import qualified Annex.Branch
import qualified Annex
+import Logs
import Logs.UUIDBased
import Remote.List
import qualified Types.Remote
-
-{- Filename of trust.log. -}
-trustLog :: FilePath
-trustLog = "trust.log"
+import Logs.Trust.Pure as X
{- Returns a list of UUIDs that the trustLog indicates have the
- specified trust level.
@@ -97,26 +94,4 @@ trustMapLoad = do
{- Does not include forcetrust or git config values, just those from the
- log file. -}
trustMapRaw :: Annex TrustMap
-trustMapRaw = simpleMap . parseLog (Just . parseTrustLog)
- <$> Annex.Branch.get trustLog
-
-{- The trust.log used to only list trusted repos, without a field for the
- - trust status, which is why this defaults to Trusted. -}
-parseTrustLog :: String -> TrustLevel
-parseTrustLog s = maybe Trusted parse $ headMaybe $ words s
- where
- parse "1" = Trusted
- parse "0" = UnTrusted
- parse "X" = DeadTrusted
- parse _ = SemiTrusted
-
-showTrustLog :: TrustLevel -> String
-showTrustLog Trusted = "1"
-showTrustLog UnTrusted = "0"
-showTrustLog DeadTrusted = "X"
-showTrustLog SemiTrusted = "?"
-
-prop_parse_show_TrustLog :: Bool
-prop_parse_show_TrustLog = all check [minBound .. maxBound]
- where
- check l = parseTrustLog (showTrustLog l) == l
+trustMapRaw = calcTrustMap <$> Annex.Branch.get trustLog
diff --git a/Logs/Trust/Pure.hs b/Logs/Trust/Pure.hs
new file mode 100644
index 000000000..11cfbe056
--- /dev/null
+++ b/Logs/Trust/Pure.hs
@@ -0,0 +1,36 @@
+{- git-annex trust log, pure operations
+ -
+ - Copyright 2010-2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Logs.Trust.Pure where
+
+import Common.Annex
+import Types.TrustLevel
+import Logs.UUIDBased
+
+calcTrustMap :: String -> TrustMap
+calcTrustMap = simpleMap . parseLog (Just . parseTrustLog)
+
+{- The trust.log used to only list trusted repos, without a field for the
+ - trust status, which is why this defaults to Trusted. -}
+parseTrustLog :: String -> TrustLevel
+parseTrustLog s = maybe Trusted parse $ headMaybe $ words s
+ where
+ parse "1" = Trusted
+ parse "0" = UnTrusted
+ parse "X" = DeadTrusted
+ parse _ = SemiTrusted
+
+showTrustLog :: TrustLevel -> String
+showTrustLog Trusted = "1"
+showTrustLog UnTrusted = "0"
+showTrustLog DeadTrusted = "X"
+showTrustLog SemiTrusted = "?"
+
+prop_parse_show_TrustLog :: Bool
+prop_parse_show_TrustLog = all check [minBound .. maxBound]
+ where
+ check l = parseTrustLog (showTrustLog l) == l
diff --git a/Logs/UUID.hs b/Logs/UUID.hs
index 2f24a388e..154f86d51 100644
--- a/Logs/UUID.hs
+++ b/Logs/UUID.hs
@@ -28,13 +28,10 @@ import Types.UUID
import Common.Annex
import qualified Annex
import qualified Annex.Branch
+import Logs
import Logs.UUIDBased
import qualified Annex.UUID
-{- Filename of uuid.log. -}
-uuidLog :: FilePath
-uuidLog = "uuid.log"
-
{- Records a description for a uuid in the log. -}
describeUUID :: UUID -> String -> Annex ()
describeUUID uuid desc = do
@@ -59,7 +56,7 @@ fixBadUUID = M.fromList . map fixup . M.toList
| otherwise = (k, v)
where
kuuid = fromUUID k
- isbad = not (isuuid kuuid) && isuuid lastword
+ isbad = not (isuuid kuuid) && not (null ws) && isuuid lastword
ws = words $ value v
lastword = Prelude.last ws
fixeduuid = toUUID lastword
diff --git a/Logs/UUIDBased.hs b/Logs/UUIDBased.hs
index c1901eef7..10b3bf55d 100644
--- a/Logs/UUIDBased.hs
+++ b/Logs/UUIDBased.hs
@@ -63,6 +63,11 @@ parseLogWithUUID :: (UUID -> String -> Maybe a) -> String -> Log a
parseLogWithUUID parser = M.fromListWith best . mapMaybe parse . lines
where
parse line
+ -- This is a workaround for a bug that caused
+ -- NoUUID items to be stored in the log.
+ -- It can be removed at any time; is just here to clean
+ -- up logs where that happened temporarily.
+ | " " `isPrefixOf` line = Nothing
| null ws = Nothing
| otherwise = parser u (unwords info) >>= makepair
where
diff --git a/Logs/Web.hs b/Logs/Web.hs
index cbce7a36e..ede600ec2 100644
--- a/Logs/Web.hs
+++ b/Logs/Web.hs
@@ -11,17 +11,19 @@ module Logs.Web (
getUrls,
setUrlPresent,
setUrlMissing,
- urlLog,
- urlLogKey,
- knownUrls
+ knownUrls,
+ Downloader(..),
+ getDownloader,
+ setDownloader,
) where
import qualified Data.ByteString.Lazy.Char8 as L
+import Data.Tuple.Utils
import Common.Annex
+import Logs
import Logs.Presence
import Logs.Location
-import Types.Key
import qualified Annex.Branch
import Annex.CatFile
import qualified Git
@@ -33,35 +35,9 @@ type URLString = String
webUUID :: UUID
webUUID = UUID "00000000-0000-0000-0000-000000000001"
-urlLogExt :: String
-urlLogExt = ".log.web"
-
-urlLog :: Key -> FilePath
-urlLog key = hashDirLower key </> keyFile key ++ urlLogExt
-
-{- Converts a url log file into a key.
- - (Does not work on oldurlLogs.) -}
-urlLogKey :: FilePath -> Maybe Key
-urlLogKey file
- | ext == urlLogExt = fileKey base
- | otherwise = Nothing
- where
- (base, ext) = splitAt (length file - extlen) file
- extlen = length urlLogExt
-
-isUrlLog :: FilePath -> Bool
-isUrlLog file = urlLogExt `isSuffixOf` file
-
-{- Used to store the urls elsewhere. -}
-oldurlLogs :: Key -> [FilePath]
-oldurlLogs key =
- [ "remote/web" </> hashDirLower key </> key2file key ++ ".log"
- , "remote/web" </> hashDirLower key </> keyFile key ++ ".log"
- ]
-
{- Gets all urls that a key might be available from. -}
getUrls :: Key -> Annex [URLString]
-getUrls key = go $ urlLog key : oldurlLogs key
+getUrls key = go $ urlLogFile key : oldurlLogs key
where
go [] = return []
go (l:ls) = do
@@ -74,13 +50,13 @@ setUrlPresent :: Key -> URLString -> Annex ()
setUrlPresent key url = do
us <- getUrls key
unless (url `elem` us) $ do
- addLog (urlLog key) =<< logNow InfoPresent url
+ addLog (urlLogFile key) =<< logNow InfoPresent url
-- update location log to indicate that the web has the key
logChange key webUUID InfoPresent
setUrlMissing :: Key -> URLString -> Annex ()
setUrlMissing key url = do
- addLog (urlLog key) =<< logNow InfoMissing url
+ addLog (urlLogFile key) =<< logNow InfoMissing url
whenM (null <$> getUrls key) $
logChange key webUUID InfoMissing
@@ -95,9 +71,25 @@ knownUrls = do
Annex.Branch.withIndex $ do
top <- fromRepo Git.repoPath
(l, cleanup) <- inRepo $ Git.LsFiles.stagedDetails [top]
- r <- mapM (geturls . snd) $ filter (isUrlLog . fst) l
+ r <- mapM (geturls . snd3) $ filter (isUrlLog . fst3) l
void $ liftIO cleanup
return $ concat r
where
geturls Nothing = return []
geturls (Just logsha) = getLog . L.unpack <$> catObject logsha
+
+data Downloader = DefaultDownloader | QuviDownloader
+
+{- Determines the downloader for an URL.
+ -
+ - Some URLs are not downloaded by normal means, and this is indicated
+ - by prefixing them with downloader: when they are recorded in the url
+ - logs. -}
+getDownloader :: URLString -> (URLString, Downloader)
+getDownloader u = case separate (== ':') u of
+ ("quvi", u') -> (u', QuviDownloader)
+ _ -> (u, DefaultDownloader)
+
+setDownloader :: URLString -> Downloader -> URLString
+setDownloader u DefaultDownloader = u
+setDownloader u QuviDownloader = "quvi:" ++ u
diff --git a/Makefile b/Makefile
index 4d3542f13..3f3ed350a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,7 @@ mans=git-annex.1 git-annex-shell.1
all=git-annex $(mans) docs
GHC?=ghc
-GHCMAKE=$(GHC) $(GHCFLAGS) --make
-PREFIX=/usr
+PREFIX?=/usr
CABAL?=cabal # set to "./Setup" if you lack a cabal program
# Am I typing :make in vim? Do a fast build.
@@ -28,8 +27,15 @@ git-annex.1: doc/git-annex.mdwn
git-annex-shell.1: doc/git-annex-shell.mdwn
./Build/mdwn2man git-annex-shell 1 doc/git-annex-shell.mdwn > git-annex-shell.1
+# These are not built normally.
git-union-merge.1: doc/git-union-merge.mdwn
./Build/mdwn2man git-union-merge 1 doc/git-union-merge.mdwn > git-union-merge.1
+git-recover-repository.1: doc/git-recover-repository.mdwn
+ ./Build/mdwn2man git-recover-repository 1 doc/git-recover-repository.mdwn > git-recover-repository.1
+git-union-merge:
+ $(GHC) --make -threaded $@
+git-recover-repository:
+ $(GHC) --make -threaded $@
install-mans: $(mans)
install -d $(DESTDIR)$(PREFIX)/share/man/man1
@@ -75,8 +81,10 @@ clean:
rm -rf tmp dist git-annex $(mans) configure *.tix .hpc \
doc/.ikiwiki html dist tags Build/SysConfig.hs build-stamp \
Setup Build/InstallDesktopFile Build/EvilSplicer \
- Build/Standalone Build/OSXMkLibs
- find -name \*.o -or -name \*.hi -exec rm {} \;
+ Build/Standalone Build/OSXMkLibs \
+ git-union-merge git-recover-repository
+ find -name \*.o -exec rm {} \;
+ find -name \*.hi -exec rm {} \;
Build/InstallDesktopFile: Build/InstallDesktopFile.hs
$(GHC) --make $@
@@ -159,12 +167,12 @@ osxapp: Build/Standalone Build/OSXMkLibs
rm -f tmp/git-annex.dmg.bz2
bzip2 --fast tmp/git-annex.dmg
-ANDROID_FLAGS?=
+ANDROID_FLAGS?=-f-XMPP
# Cross compile for Android.
# Uses https://github.com/neurocyte/ghc-android
android: Build/EvilSplicer
echo "Running native build, to get TH splices.."
- if [ ! -e dist/setup/setup ]; then $(CABAL) configure -f"-Production $(ANDROID_FLAGS)" -O0; fi
+ if [ ! -e dist/setup/setup ]; then $(CABAL) configure -f-Production -O0 $(ANDROID_FLAGS); fi
mkdir -p tmp
if ! $(CABAL) build --ghc-options=-ddump-splices 2> tmp/dump-splices; then tail tmp/dump-splices >&2; exit 1; fi
echo "Setting up Android build tree.."
@@ -181,14 +189,16 @@ android: Build/EvilSplicer
sed -i 's/GHC-Options: \(.*\)-Wall/GHC-Options: \1-Wall -fno-warn-unused-imports /i' tmp/androidtree/git-annex.cabal
# Cabal cannot cross compile with custom build type, so workaround.
sed -i 's/Build-type: Custom/Build-type: Simple/' tmp/androidtree/git-annex.cabal
+# Build just once, but link twice, for 2 different versions of Android.
+ mkdir -p tmp/androidtree/dist/build/git-annex/4.0 tmp/androidtree/dist/build/git-annex/4.3
if [ ! -e tmp/androidtree/dist/setup/setup ]; then \
- cd tmp/androidtree && $$HOME/.ghc/android-14/arm-linux-androideabi-4.7/arm-linux-androideabi/bin/cabal configure -f"Android $(ANDROID_FLAGS)"; \
+ cd tmp/androidtree && $$HOME/.ghc/$(shell cat standalone/android/abiversion)/arm-linux-androideabi/bin/cabal configure -fAndroid $(ANDROID_FLAGS); \
fi
- cd tmp/androidtree && $(CABAL) build
-
-adb:
- ANDROID_FLAGS="-Production" $(MAKE) android
- adb push tmp/androidtree/dist/build/git-annex/git-annex /data/data/ga.androidterm/bin/git-annex
+ cd tmp/androidtree && $$HOME/.ghc/$(shell cat standalone/android/abiversion)/arm-linux-androideabi/bin/cabal build \
+ && mv dist/build/git-annex/git-annex dist/build/git-annex/4.0/git-annex
+ cd tmp/androidtree && $$HOME/.ghc/$(shell cat standalone/android/abiversion)/arm-linux-androideabi/bin/cabal build \
+ --ghc-options=-optl-z --ghc-options=-optlnocopyreloc \
+ && mv dist/build/git-annex/git-annex dist/build/git-annex/4.3/git-annex
androidapp:
$(MAKE) android
@@ -213,4 +223,4 @@ hdevtools:
hdevtools --stop-server || true
hdevtools check git-annex.hs -g -cpp -g -i -g -idist/build/git-annex/git-annex-tmp -g -i. -g -idist/build/autogen -g -Idist/build/autogen -g -Idist/build/git-annex/git-annex-tmp -g -IUtility -g -DWITH_TESTSUITE -g -DWITH_S3 -g -DWITH_ASSISTANT -g -DWITH_INOTIFY -g -DWITH_DBUS -g -DWITH_PAIRING -g -DWITH_XMPP -g -optP-include -g -optPdist/build/autogen/cabal_macros.h -g -odir -g dist/build/git-annex/git-annex-tmp -g -hidir -g dist/build/git-annex/git-annex-tmp -g -stubdir -g dist/build/git-annex/git-annex-tmp -g -threaded -g -Wall -g -XHaskell98 -g -XPackageImports
-.PHONY: git-annex tags build-stamp
+.PHONY: git-annex git-union-merge git-recover-repository tags build-stamp
diff --git a/Remote.hs b/Remote.hs
index ea9317282..e355b0975 100644
--- a/Remote.hs
+++ b/Remote.hs
@@ -16,13 +16,15 @@ module Remote (
hasKey,
hasKeyCheap,
whereisKey,
+ remoteFsck,
remoteTypes,
remoteList,
- specialRemote,
+ syncableRemote,
remoteMap,
uuidDescriptions,
byName,
+ byNameOnly,
byNameWithUUID,
byCost,
prettyPrintUUIDs,
@@ -38,7 +40,8 @@ module Remote (
showTriedRemotes,
showLocations,
forceTrust,
- logStatus
+ logStatus,
+ checkAvailable
) where
import qualified Data.Map as M
@@ -55,6 +58,8 @@ import Logs.UUID
import Logs.Trust
import Logs.Location hiding (logStatus)
import Remote.List
+import Config
+import Git.Types (RemoteName)
{- Map from UUIDs of Remotes to a calculated value. -}
remoteMap :: (Remote -> a) -> Annex (M.Map UUID a)
@@ -67,7 +72,7 @@ remoteMap c = M.fromList . map (\r -> (uuid r, c r)) .
uuidDescriptions :: Annex (M.Map UUID String)
uuidDescriptions = M.unionWith addName <$> uuidMap <*> remoteMap name
-addName :: String -> String -> String
+addName :: String -> RemoteName -> String
addName desc n
| desc == n = desc
| null desc = n
@@ -75,21 +80,25 @@ addName desc n
{- When a name is specified, looks up the remote matching that name.
- (Or it can be a UUID.) -}
-byName :: Maybe String -> Annex (Maybe Remote)
+byName :: Maybe RemoteName -> Annex (Maybe Remote)
byName Nothing = return Nothing
byName (Just n) = either error Just <$> byName' n
{- Like byName, but the remote must have a configured UUID. -}
-byNameWithUUID :: Maybe String -> Annex (Maybe Remote)
-byNameWithUUID n = do
- v <- byName n
- return $ checkuuid <$> v
+byNameWithUUID :: Maybe RemoteName -> Annex (Maybe Remote)
+byNameWithUUID = checkuuid <=< byName
where
- checkuuid r
- | uuid r == NoUUID = error $ "cannot determine uuid for " ++ name r
- | otherwise = r
+ checkuuid Nothing = return Nothing
+ checkuuid (Just r)
+ | uuid r == NoUUID =
+ if remoteAnnexIgnore (gitconfig r)
+ then error $ noRemoteUUIDMsg r ++
+ " (" ++ show (remoteConfig (repo r) "ignore") ++
+ " is set)"
+ else error $ noRemoteUUIDMsg r
+ | otherwise = return $ Just r
-byName' :: String -> Annex (Either String Remote)
+byName' :: RemoteName -> Annex (Either String Remote)
byName' "" = return $ Left "no remote specified"
byName' n = handle . filter matching <$> remoteList
where
@@ -97,16 +106,27 @@ byName' n = handle . filter matching <$> remoteList
handle (match:_) = Right match
matching r = n == name r || toUUID n == uuid r
+{- Only matches remote name, not UUID -}
+byNameOnly :: RemoteName -> Annex (Maybe Remote)
+byNameOnly n = headMaybe . filter matching <$> remoteList
+ where
+ matching r = n == name r
+
+noRemoteUUIDMsg :: Remote -> String
+noRemoteUUIDMsg r = "cannot determine uuid for " ++ name r
+
{- Looks up a remote by name (or by UUID, or even by description),
- - and returns its UUID. Finds even remotes that are not configured in
- - .git/config. -}
-nameToUUID :: String -> Annex UUID
+ - 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
where
- go (Right r) = return $ uuid r
+ go (Right r) = case uuid r of
+ NoUUID -> error $ noRemoteUUIDMsg r
+ u -> return u
go (Left e) = fromMaybe (error e) <$> bydescription
bydescription = do
m <- uuidMap
@@ -163,13 +183,19 @@ prettyListUUIDs uuids = do
prettyUUID :: UUID -> Annex String
prettyUUID u = concat <$> prettyListUUIDs [u]
-{- Gets the remote associated with a UUID.
- - There's no associated remote when this is the UUID of the local repo. -}
+{- Gets the remote associated with a UUID. -}
remoteFromUUID :: UUID -> Annex (Maybe Remote)
remoteFromUUID u = ifM ((==) u <$> getUUID)
( return Nothing
- , Just . fromMaybe (error "Unknown UUID") . M.lookup u <$> remoteMap id
+ , do
+ maybe tryharder (return . Just) =<< findinmap
)
+ where
+ findinmap = M.lookup u <$> remoteMap id
+ {- Re-read remote list in case a new remote has popped up. -}
+ tryharder = do
+ void remoteListRefresh
+ findinmap
{- Filters a list of remotes to ones that have the listed uuids. -}
remotesWithUUID :: [Remote] -> [UUID] -> [Remote]
@@ -227,6 +253,9 @@ showLocations key exclude nolocmsg = do
ppuuidswanted <- Remote.prettyPrintUUIDs "wanted" uuidswanted
ppuuidsskipped <- Remote.prettyPrintUUIDs "skipped" uuidsskipped
showLongNote $ message ppuuidswanted ppuuidsskipped
+ ignored <- filter (remoteAnnexIgnore . gitconfig) <$> remoteList
+ unless (null ignored) $
+ showLongNote $ "(Note that these git remotes have annex-ignore set: " ++ unwords (map name ignored) ++ ")"
where
filteruuids l x = filter (`notElem` x) l
message [] [] = nolocmsg
@@ -259,3 +288,7 @@ byCost = map snd . sortBy (comparing fst) . M.toList . costmap
where
costmap = M.fromListWith (++) . map costpair
costpair r = (cost r, [r])
+
+checkAvailable :: Bool -> Remote -> IO Bool
+checkAvailable assumenetworkavailable =
+ maybe (return assumenetworkavailable) doesDirectoryExist . localpath
diff --git a/Remote/Bup.hs b/Remote/Bup.hs
index 9b3675cfa..4e89dcff2 100644
--- a/Remote/Bup.hs
+++ b/Remote/Bup.hs
@@ -10,6 +10,7 @@ module Remote.Bup (remote) where
import qualified Data.ByteString.Lazy as L
import qualified Data.Map as M
import System.Process
+import Data.ByteString.Lazy.UTF8 (fromString)
import Common.Annex
import Types.Remote
@@ -21,14 +22,15 @@ import qualified Git.Construct
import qualified Git.Ref
import Config
import Config.Cost
-import Remote.Helper.Ssh
+import qualified Remote.Helper.Ssh as Ssh
import Remote.Helper.Special
import Remote.Helper.Encryptable
+import Remote.Helper.Messages
import Crypto
-import Data.ByteString.Lazy.UTF8 (fromString)
-import Data.Digest.Pure.SHA
+import Utility.Hash
import Utility.UserInfo
import Annex.Content
+import Annex.UUID
import Utility.Metered
type BupRepo = String
@@ -41,7 +43,7 @@ remote = RemoteType {
setup = bupSetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = do
bupr <- liftIO $ bup2GitRemote buprepo
cst <- remoteCost gc $
@@ -61,6 +63,8 @@ gen r u c gc = do
, hasKey = checkPresent r bupr'
, hasKeyCheap = bupLocal buprepo
, whereisKey = Nothing
+ , remoteFsck = Nothing
+ , repairRepo = Nothing
, config = c
, repo = r
, gitconfig = gc
@@ -71,15 +75,17 @@ gen r u c gc = do
, globallyAvailable = not $ bupLocal buprepo
, readonly = False
}
- return $ encryptableRemote c
+ return $ Just $ encryptableRemote c
(storeEncrypted new buprepo)
(retrieveEncrypted buprepo)
new
where
buprepo = fromMaybe (error "missing buprepo") $ remoteAnnexBupRepo gc
-bupSetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-bupSetup u c = do
+bupSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+bupSetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
+
-- verify configuration is sane
let buprepo = fromMaybe (error "Specify buprepo=") $
M.lookup "buprepo" c
@@ -96,7 +102,7 @@ bupSetup u c = do
-- persistant state, so it can vary between hosts.
gitConfigSpecialRemote u c' "buprepo" buprepo
- return c'
+ return (c', u)
bupParams :: String -> BupRepo -> [CommandParam] -> [CommandParam]
bupParams command buprepo params =
@@ -133,7 +139,7 @@ storeEncrypted r buprepo (cipher, enck) k _p =
sendAnnex k (rollback enck buprepo) $ \src -> do
params <- bupSplitParams r buprepo enck []
liftIO $ catchBoolIO $
- encrypt (getGpgOpts r) cipher (feedFile src) $ \h ->
+ encrypt (getGpgEncParams r) cipher (feedFile src) $ \h ->
pipeBup params (Just h) Nothing
retrieve :: BupRepo -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> Annex Bool
@@ -182,7 +188,7 @@ rollback k bupr = go =<< liftIO (bup2GitRemote bupr)
checkPresent :: Git.Repo -> Git.Repo -> Key -> Annex (Either String Bool)
checkPresent r bupr k
| Git.repoIsUrl bupr = do
- showAction $ "checking " ++ Git.repoDescribe r
+ showChecking r
ok <- onBupRemote bupr boolSystem "git" params
return $ Right ok
| otherwise = liftIO $ catchMsgIO $
@@ -217,7 +223,7 @@ storeBupUUID u buprepo = do
onBupRemote :: Git.Repo -> (FilePath -> [CommandParam] -> IO a) -> FilePath -> [CommandParam] -> Annex a
onBupRemote r a command params = do
- sshparams <- sshToRepo r [Param $
+ sshparams <- Ssh.toRepo r [Param $
"cd " ++ dir ++ " && " ++ unwords (command : toCommand params)]
liftIO $ a "ssh" sshparams
where
@@ -274,7 +280,7 @@ bup2GitRemote r
bupRef :: Key -> String
bupRef k
| Git.Ref.legal True shown = shown
- | otherwise = "git-annex-" ++ showDigest (sha256 (fromString shown))
+ | otherwise = "git-annex-" ++ show (sha256 (fromString shown))
where
shown = key2file k
diff --git a/Remote/Directory.hs b/Remote/Directory.hs
index 6cc75d2f1..e6deee4bf 100644
--- a/Remote/Directory.hs
+++ b/Remote/Directory.hs
@@ -12,7 +12,6 @@ module Remote.Directory (remote) where
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as S
import qualified Data.Map as M
-import qualified Control.Exception as E
import Data.Int
import Common.Annex
@@ -26,6 +25,7 @@ import Remote.Helper.Encryptable
import Remote.Helper.Chunked
import Crypto
import Annex.Content
+import Annex.UUID
import Utility.Metered
remote :: RemoteType
@@ -36,12 +36,12 @@ remote = RemoteType {
setup = directorySetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = do
cst <- remoteCost gc cheapRemoteCost
let chunksize = chunkSize c
- return $ encryptableRemote c
- (storeEncrypted dir (getGpgOpts gc) chunksize)
+ return $ Just $ encryptableRemote c
+ (storeEncrypted dir (getGpgEncParams (c,gc)) chunksize)
(retrieveEncrypted dir chunksize)
Remote {
uuid = u,
@@ -54,7 +54,9 @@ gen r u c gc = do
hasKey = checkPresent dir chunksize,
hasKeyCheap = True,
whereisKey = Nothing,
- config = M.empty,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
+ config = c,
repo = r,
gitconfig = gc,
localpath = Just dir,
@@ -65,8 +67,9 @@ gen r u c gc = do
where
dir = fromMaybe (error "missing directory") $ remoteAnnexDirectory gc
-directorySetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-directorySetup u c = do
+directorySetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+directorySetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let dir = fromMaybe (error "Specify directory=") $
M.lookup "directory" c
@@ -78,7 +81,7 @@ directorySetup u c = do
-- The directory is stored in git config, not in this remote's
-- persistant state, so it can vary between hosts.
gitConfigSpecialRemote u c' "directory" absdir
- return $ M.delete "directory" c'
+ return (M.delete "directory" c', u)
{- Locations to try to access a given Key in the Directory.
- We try more than since we used to write to different hash directories. -}
@@ -107,9 +110,13 @@ withCheckedFiles check (Just _) d k a = go $ locations d k
ifM (check chunkcount)
( do
chunks <- listChunks f <$> readFile chunkcount
- ifM (all id <$> mapM check chunks)
+ ifM (allM check chunks)
( a chunks , return False )
- , go fs
+ , do
+ chunks <- probeChunks f check
+ if null chunks
+ then go fs
+ else a chunks
)
withStoredFiles :: ChunkSize -> FilePath -> Key -> ([FilePath] -> IO Bool) -> IO Bool
@@ -129,7 +136,7 @@ store d chunksize k _f p = sendAnnex k (void $ remove d k) $ \src ->
storeSplit meterupdate chunksize dests
=<< L.readFile src
-storeEncrypted :: FilePath -> GpgOpts -> ChunkSize -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
+storeEncrypted :: FilePath -> [CommandParam] -> ChunkSize -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
storeEncrypted d gpgOpts chunksize (cipher, enck) k p = sendAnnex k (void $ remove d enck) $ \src ->
metered (Just p) k $ \meterupdate ->
storeHelper d chunksize enck k $ \dests ->
@@ -157,7 +164,7 @@ storeSplit' :: MeterUpdate -> Int64 -> [FilePath] -> [S.ByteString] -> [FilePath
storeSplit' _ _ [] _ _ = error "ran out of dests"
storeSplit' _ _ _ [] c = return $ reverse c
storeSplit' meterupdate chunksize (d:dests) bs c = do
- bs' <- E.bracket (openFile d WriteMode) hClose $
+ bs' <- withFile d WriteMode $
feed zeroBytesProcessed chunksize bs
storeSplit' meterupdate chunksize dests bs' (d:c)
where
@@ -204,7 +211,7 @@ retrieve :: FilePath -> ChunkSize -> Key -> AssociatedFile -> FilePath -> MeterU
retrieve d chunksize k _ f p = metered (Just p) k $ \meterupdate ->
liftIO $ withStoredFiles chunksize d k $ \files ->
catchBoolIO $ do
- meteredWriteFileChunks meterupdate f files $ L.readFile
+ meteredWriteFileChunks meterupdate f files L.readFile
return True
retrieveEncrypted :: FilePath -> ChunkSize -> (Cipher, Key) -> Key -> FilePath -> MeterUpdate -> Annex Bool
@@ -215,7 +222,7 @@ retrieveEncrypted d chunksize (cipher, enck) k f p = metered (Just p) k $ \meter
readBytes $ meteredWriteFile meterupdate f
return True
where
- feeder files h = forM_ files $ \file -> L.hPut h =<< L.readFile file
+ feeder files h = forM_ files $ L.hPut h <=< L.readFile
retrieveCheap :: FilePath -> ChunkSize -> Key -> FilePath -> Annex Bool
retrieveCheap _ (Just _) _ _ = return False -- no cheap retrieval for chunks
diff --git a/Remote/GCrypt.hs b/Remote/GCrypt.hs
new file mode 100644
index 000000000..e1b6811c7
--- /dev/null
+++ b/Remote/GCrypt.hs
@@ -0,0 +1,402 @@
+{- git remotes encrypted using git-remote-gcrypt
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Remote.GCrypt (
+ remote,
+ gen,
+ getGCryptUUID,
+ coreGCryptId,
+ setupRepo
+) where
+
+import qualified Data.Map as M
+import qualified Data.ByteString.Lazy as L
+import Control.Exception.Extensible
+
+import Common.Annex
+import Types.Remote
+import Types.GitConfig
+import Types.Crypto
+import qualified Git
+import qualified Git.Command
+import qualified Git.Config
+import qualified Git.GCrypt
+import qualified Git.Construct
+import qualified Git.Types as Git ()
+import qualified Annex.Branch
+import qualified Annex.Content
+import Config
+import Config.Cost
+import Remote.Helper.Git
+import Remote.Helper.Encryptable
+import Remote.Helper.Special
+import Remote.Helper.Messages
+import qualified Remote.Helper.Ssh as Ssh
+import Utility.Metered
+import Crypto
+import Annex.UUID
+import Annex.Ssh
+import qualified Remote.Rsync
+import Utility.Rsync
+import Utility.Tmp
+import Logs.Remote
+import Logs.Transfer
+import Utility.Gpg
+import Annex.Content
+
+remote :: RemoteType
+remote = RemoteType {
+ typename = "gcrypt",
+ -- Remote.Git takes care of enumerating gcrypt remotes too,
+ -- and will call our gen on them.
+ enumerate = return [],
+ generate = gen,
+ setup = gCryptSetup
+}
+
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
+gen gcryptr u c gc = do
+ g <- gitRepo
+ -- get underlying git repo with real path, not gcrypt path
+ r <- liftIO $ Git.GCrypt.encryptedRemote g gcryptr
+ let r' = r { Git.remoteName = Git.remoteName gcryptr }
+ -- doublecheck that cache matches underlying repo's gcrypt-id
+ -- (which might not be set), only for local repos
+ (mgcryptid, r'') <- getGCryptId True r'
+ case (mgcryptid, Git.GCrypt.remoteRepoId g (Git.remoteName gcryptr)) of
+ (Just gcryptid, Just cachedgcryptid)
+ | gcryptid /= cachedgcryptid -> resetup gcryptid r''
+ _ -> gen' r'' u c gc
+ where
+ -- A different drive may have been mounted, making a different
+ -- gcrypt remote available. So need to set the cached
+ -- gcrypt-id and annex-uuid of the remote to match the remote
+ -- that is now available. Also need to set the gcrypt particiants
+ -- correctly.
+ resetup gcryptid r = do
+ let u' = genUUIDInNameSpace gCryptNameSpace gcryptid
+ v <- M.lookup u' <$> readRemoteLog
+ case (Git.remoteName gcryptr, v) of
+ (Just remotename, Just c') -> do
+ setGcryptEncryption c' remotename
+ setConfig (remoteConfig gcryptr "uuid") (fromUUID u')
+ setConfig (ConfigKey $ Git.GCrypt.remoteConfigKey "gcrypt-id" remotename) gcryptid
+ gen' r u' c' gc
+ _ -> do
+ warning $ "not using unknown gcrypt repository pointed to by remote " ++ Git.repoDescribe r
+ return Nothing
+
+gen' :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
+gen' r u c gc = do
+ cst <- remoteCost gc $
+ if repoCheap r then nearlyCheapRemoteCost else expensiveRemoteCost
+ (rsynctransport, rsyncurl) <- rsyncTransportToObjects r
+ let rsyncopts = Remote.Rsync.genRsyncOpts c gc rsynctransport rsyncurl
+ let this = Remote
+ { uuid = u
+ , cost = cst
+ , name = Git.repoDescribe r
+ , storeKey = \_ _ _ -> noCrypto
+ , retrieveKeyFile = \_ _ _ _ -> noCrypto
+ , retrieveKeyFileCheap = \_ _ -> return False
+ , removeKey = remove this rsyncopts
+ , hasKey = checkPresent this rsyncopts
+ , hasKeyCheap = repoCheap r
+ , whereisKey = Nothing
+ , remoteFsck = Nothing
+ , repairRepo = Nothing
+ , config = c
+ , localpath = localpathCalc r
+ , repo = r
+ , gitconfig = gc { remoteGitConfig = Just $ extractGitConfig r }
+ , readonly = Git.repoIsHttp r
+ , globallyAvailable = globallyAvailableCalc r
+ , remotetype = remote
+ }
+ return $ Just $ encryptableRemote c
+ (store this rsyncopts)
+ (retrieve this rsyncopts)
+ this
+
+rsyncTransportToObjects :: Git.Repo -> Annex ([CommandParam], String)
+rsyncTransportToObjects r = do
+ (rsynctransport, rsyncurl, _) <- rsyncTransport r
+ return (rsynctransport, rsyncurl ++ "/annex/objects")
+
+rsyncTransport :: Git.Repo -> Annex ([CommandParam], String, AccessMethod)
+rsyncTransport r
+ | "ssh://" `isPrefixOf` loc = sshtransport $ break (== '/') $ drop (length "ssh://") loc
+ | "//:" `isInfixOf` loc = othertransport
+ | ":" `isInfixOf` loc = sshtransport $ separate (== ':') loc
+ | otherwise = othertransport
+ where
+ loc = Git.repoLocation r
+ sshtransport (host, path) = do
+ let rsyncpath = if "/~/" `isPrefixOf` path
+ then drop 3 path
+ else path
+ opts <- sshCachingOptions (host, Nothing) []
+ return (rsyncShell $ Param "ssh" : opts, host ++ ":" ++ rsyncpath, AccessShell)
+ othertransport = return ([], loc, AccessDirect)
+
+noCrypto :: Annex a
+noCrypto = error "cannot use gcrypt remote without encryption enabled"
+
+unsupportedUrl :: Annex a
+unsupportedUrl = error "using non-ssh remote repo url with gcrypt is not supported"
+
+gCryptSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+gCryptSetup mu c = go $ M.lookup "gitrepo" c
+ where
+ remotename = fromJust (M.lookup "name" c)
+ go Nothing = error "Specify gitrepo="
+ go (Just gitrepo) = do
+ c' <- encryptionSetup c
+ inRepo $ Git.Command.run
+ [ Params "remote add"
+ , Param remotename
+ , Param $ Git.GCrypt.urlPrefix ++ gitrepo
+ ]
+
+ setGcryptEncryption c' remotename
+
+ {- Run a git fetch and a push to the git repo in order to get
+ - its gcrypt-id set up, so that later git annex commands
+ - will use the remote as a gcrypt remote. The fetch is
+ - needed if the repo already exists; the push is needed
+ - if the repo has not yet been initialized by gcrypt. -}
+ void $ inRepo $ Git.Command.runBool
+ [ Param "fetch"
+ , Param remotename
+ ]
+ void $ inRepo $ Git.Command.runBool
+ [ Param "push"
+ , Param remotename
+ , Param $ show Annex.Branch.fullname
+ ]
+ g <- inRepo Git.Config.reRead
+ case Git.GCrypt.remoteRepoId g (Just remotename) of
+ Nothing -> error "unable to determine gcrypt-id of remote"
+ Just gcryptid -> do
+ let u = genUUIDInNameSpace gCryptNameSpace gcryptid
+ if Just u == mu || isNothing mu
+ then do
+ method <- setupRepo gcryptid =<< inRepo (Git.Construct.fromRemoteLocation gitrepo)
+ gitConfigSpecialRemote u c' "gcrypt" (fromAccessMethod method)
+ return (c', u)
+ else error $ "uuid mismatch " ++ show (u, mu, gcryptid)
+
+{- Sets up the gcrypt repository. The repository is either a local
+ - repo, or it is accessed via rsync directly, or it is accessed over ssh
+ - and git-annex-shell is available to manage it.
+ -
+ - The GCryptID is recorded in the repository's git config for later use.
+ - Also, if the git config has receive.denyNonFastForwards set, disable
+ - it; gcrypt relies on being able to fast-forward branches.
+ -}
+setupRepo :: Git.GCrypt.GCryptId -> Git.Repo -> Annex AccessMethod
+setupRepo gcryptid r
+ | Git.repoIsUrl r = do
+ (_, _, accessmethod) <- rsyncTransport r
+ case accessmethod of
+ AccessDirect -> rsyncsetup
+ AccessShell -> ifM gitannexshellsetup
+ ( return AccessShell
+ , rsyncsetup
+ )
+ | Git.repoIsLocalUnknown r = localsetup =<< liftIO (Git.Config.read r)
+ | otherwise = localsetup r
+ where
+ localsetup r' = do
+ let setconfig k v = liftIO $ Git.Command.run [Param "config", Param k, Param v] r'
+ setconfig coreGCryptId gcryptid
+ setconfig denyNonFastForwards (Git.Config.boolConfig False)
+ return AccessDirect
+
+ {- As well as modifying the remote's git config,
+ - create the objectDir on the remote,
+ - which is needed for direct rsync of objects to work.
+ -}
+ rsyncsetup = Remote.Rsync.withRsyncScratchDir $ \tmp -> do
+ liftIO $ createDirectoryIfMissing True $ tmp </> objectDir
+ (rsynctransport, rsyncurl, _) <- rsyncTransport r
+ let tmpconfig = tmp </> "config"
+ void $ liftIO $ rsync $ rsynctransport ++
+ [ Param $ rsyncurl ++ "/config"
+ , Param tmpconfig
+ ]
+ liftIO $ do
+ void $ Git.Config.changeFile tmpconfig coreGCryptId gcryptid
+ void $ Git.Config.changeFile tmpconfig denyNonFastForwards (Git.Config.boolConfig False)
+ ok <- liftIO $ rsync $ rsynctransport ++
+ [ Params "--recursive"
+ , Param $ tmp ++ "/"
+ , Param rsyncurl
+ ]
+ unless ok $
+ error "Failed to connect to remote to set it up."
+ return AccessDirect
+
+ {- Ask git-annex-shell to configure the repository as a gcrypt
+ - repository. May fail if it is too old. -}
+ gitannexshellsetup = Ssh.onRemote r (boolSystem, False)
+ "gcryptsetup" [ Param gcryptid ] []
+
+ denyNonFastForwards = "receive.denyNonFastForwards"
+
+shellOrRsync :: Remote -> Annex a -> Annex a -> Annex a
+shellOrRsync r ashell arsync = case method of
+ AccessShell -> ashell
+ _ -> arsync
+ where
+ method = toAccessMethod $ fromMaybe "" $
+ remoteAnnexGCrypt $ gitconfig r
+
+{- Configure gcrypt to use the same list of keyids that
+ - were passed to initremote as its participants.
+ - Also, configure it to use a signing key that is in the list of
+ - participants, which gcrypt requires is the case, and may not be
+ - depending on system configuration.
+ -
+ - (For shared encryption, gcrypt's default behavior is used.) -}
+setGcryptEncryption :: RemoteConfig -> String -> Annex ()
+setGcryptEncryption c remotename = do
+ let participants = ConfigKey $ Git.GCrypt.remoteParticipantConfigKey remotename
+ case extractCipher c of
+ Nothing -> noCrypto
+ Just (EncryptedCipher _ _ (KeyIds { keyIds = ks})) -> do
+ setConfig participants (unwords ks)
+ let signingkey = ConfigKey $ Git.GCrypt.remoteSigningKey remotename
+ skeys <- M.keys <$> liftIO secretKeys
+ case filter (`elem` ks) skeys of
+ [] -> noop
+ (k:_) -> setConfig signingkey k
+ Just (SharedCipher _) ->
+ unsetConfig participants
+
+store :: Remote -> Remote.Rsync.RsyncOpts -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
+store r rsyncopts (cipher, enck) k p
+ | not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $
+ metered (Just p) k $ \meterupdate -> spoolencrypted $ \h -> do
+ let dest = gCryptLocation r enck
+ createDirectoryIfMissing True $ parentDir dest
+ readBytes (meteredWriteFile meterupdate dest) h
+ return True
+ | Git.repoIsSsh (repo r) = shellOrRsync r storeshell storersync
+ | otherwise = unsupportedUrl
+ where
+ gpgopts = getGpgEncParams r
+ storersync = Remote.Rsync.storeEncrypted rsyncopts gpgopts (cipher, enck) k p
+ storeshell = withTmp enck $ \tmp ->
+ ifM (spoolencrypted $ readBytes $ \b -> catchBoolIO $ L.writeFile tmp b >> return True)
+ ( Ssh.rsyncHelper (Just p)
+ =<< Ssh.rsyncParamsRemote False r Upload enck tmp Nothing
+ , return False
+ )
+ spoolencrypted a = Annex.Content.sendAnnex k noop $ \src ->
+ liftIO $ catchBoolIO $
+ encrypt gpgopts cipher (feedFile src) a
+
+retrieve :: Remote -> Remote.Rsync.RsyncOpts -> (Cipher, Key) -> Key -> FilePath -> MeterUpdate -> Annex Bool
+retrieve r rsyncopts (cipher, enck) k d p
+ | not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $ do
+ retrievewith $ L.readFile src
+ return True
+ | Git.repoIsSsh (repo r) = shellOrRsync r retrieveshell retrieversync
+ | otherwise = unsupportedUrl
+ where
+ src = gCryptLocation r enck
+ retrievewith a = metered (Just p) k $ \meterupdate -> liftIO $
+ a >>= \b ->
+ decrypt cipher (feedBytes b)
+ (readBytes $ meteredWriteFile meterupdate d)
+ retrieversync = Remote.Rsync.retrieveEncrypted rsyncopts (cipher, enck) k d p
+ retrieveshell = withTmp enck $ \tmp ->
+ ifM (Ssh.rsyncHelper (Just p) =<< Ssh.rsyncParamsRemote False r Download enck tmp Nothing)
+ ( liftIO $ catchBoolIO $ do
+ decrypt cipher (feedFile tmp) $
+ readBytes $ L.writeFile d
+ return True
+ , return False
+ )
+
+remove :: Remote -> Remote.Rsync.RsyncOpts -> Key -> Annex Bool
+remove r rsyncopts k
+ | not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $ do
+ liftIO $ removeDirectoryRecursive $ parentDir $ gCryptLocation r k
+ return True
+ | Git.repoIsSsh (repo r) = shellOrRsync r removeshell removersync
+ | otherwise = unsupportedUrl
+ where
+ removersync = Remote.Rsync.remove rsyncopts k
+ removeshell = Ssh.dropKey (repo r) k
+
+checkPresent :: Remote -> Remote.Rsync.RsyncOpts -> Key -> Annex (Either String Bool)
+checkPresent r rsyncopts k
+ | not $ Git.repoIsUrl (repo r) =
+ guardUsable (repo r) (cantCheck $ repo r) $
+ liftIO $ catchDefaultIO (cantCheck $ repo r) $
+ Right <$> doesFileExist (gCryptLocation r k)
+ | Git.repoIsSsh (repo r) = shellOrRsync r checkshell checkrsync
+ | otherwise = unsupportedUrl
+ where
+ checkrsync = Remote.Rsync.checkPresent (repo r) rsyncopts k
+ checkshell = Ssh.inAnnex (repo r) k
+
+{- Annexed objects are hashed using lower-case directories for max
+ - portability. -}
+gCryptLocation :: Remote -> Key -> FilePath
+gCryptLocation r key = Git.repoLocation (repo r) </> objectDir </> keyPath key hashDirLower
+
+data AccessMethod = AccessDirect | AccessShell
+
+fromAccessMethod :: AccessMethod -> String
+fromAccessMethod AccessShell = "shell"
+fromAccessMethod AccessDirect = "true"
+
+toAccessMethod :: String -> AccessMethod
+toAccessMethod "shell" = AccessShell
+toAccessMethod _ = AccessDirect
+
+getGCryptUUID :: Bool -> Git.Repo -> Annex (Maybe UUID)
+getGCryptUUID fast r = (genUUIDInNameSpace gCryptNameSpace <$>) . fst
+ <$> getGCryptId fast r
+
+coreGCryptId :: String
+coreGCryptId = "core.gcrypt-id"
+
+{- gcrypt repos set up by git-annex as special remotes have a
+ - core.gcrypt-id setting in their config, which can be mapped back to
+ - the remote's UUID.
+ -
+ - In fast mode, only checks local repos. To check a remote repo,
+ - tries git-annex-shell and direct rsync of the git config file.
+ -
+ - (Also returns a version of input repo with its config read.) -}
+getGCryptId :: Bool -> Git.Repo -> Annex (Maybe Git.GCrypt.GCryptId, Git.Repo)
+getGCryptId fast r
+ | Git.repoIsLocal r || Git.repoIsLocalUnknown r = extract <$>
+ liftIO (catchMaybeIO $ Git.Config.read r)
+ | not fast = extract . liftM fst <$> getM (eitherToMaybe <$>)
+ [ Ssh.onRemote r (Git.Config.fromPipe r, Left undefined) "configlist" [] []
+ , getConfigViaRsync r
+ ]
+ | otherwise = return (Nothing, r)
+ where
+ extract Nothing = (Nothing, r)
+ extract (Just r') = (Git.Config.getMaybe coreGCryptId r', r')
+
+getConfigViaRsync :: Git.Repo -> Annex (Either SomeException (Git.Repo, String))
+getConfigViaRsync r = do
+ (rsynctransport, rsyncurl, _) <- rsyncTransport r
+ liftIO $ do
+ withTmpFile "tmpconfig" $ \tmpconfig _ -> do
+ void $ rsync $ rsynctransport ++
+ [ Param $ rsyncurl ++ "/config"
+ , Param tmpconfig
+ ]
+ Git.Config.fromFile r tmpconfig
diff --git a/Remote/Git.hs b/Remote/Git.hs
index e269b9ad8..d4e5987dc 100644
--- a/Remote/Git.hs
+++ b/Remote/Git.hs
@@ -13,12 +13,7 @@ module Remote.Git (
repoAvail,
) where
-import qualified Data.Map as M
-import Control.Exception.Extensible
-
import Common.Annex
-import Utility.Rsync
-import Remote.Helper.Ssh
import Annex.Ssh
import Types.Remote
import Types.GitConfig
@@ -26,6 +21,7 @@ import qualified Git
import qualified Git.Config
import qualified Git.Construct
import qualified Git.Command
+import qualified Git.GCrypt
import qualified Annex
import Logs.Presence
import Logs.Transfer
@@ -34,7 +30,7 @@ import Annex.Exception
import qualified Annex.Content
import qualified Annex.BranchState
import qualified Annex.Branch
-import qualified Utility.Url as Url
+import qualified Annex.Url as Url
import Utility.Tmp
import Config
import Config.Cost
@@ -46,10 +42,19 @@ import Utility.Metered
#ifndef mingw32_HOST_OS
import Utility.CopyFile
#endif
+import Utility.Env
+import Utility.Batch
+import Remote.Helper.Git
+import Remote.Helper.Messages
+import qualified Remote.Helper.Ssh as Ssh
+import qualified Remote.GCrypt
+import Config.Files
import Control.Concurrent
import Control.Concurrent.MSampleVar
import System.Process (std_in, std_err)
+import qualified Data.Map as M
+import Control.Exception.Extensible
remote :: RemoteType
remote = RemoteType {
@@ -90,14 +95,13 @@ configRead r = do
(False, _, NoUUID) -> tryGitConfigRead r
_ -> return r
-repoCheap :: Git.Repo -> Bool
-repoCheap = not . Git.repoIsUrl
-
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
-gen r u _ gc = go <$> remoteCost gc defcst
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
+gen r u c gc
+ | Git.GCrypt.isEncrypted r = Remote.GCrypt.gen r u c gc
+ | otherwise = go <$> remoteCost gc defcst
where
defcst = if repoCheap r then cheapRemoteCost else expensiveRemoteCost
- go cst = new
+ go cst = Just new
where
new = Remote
{ uuid = u
@@ -110,15 +114,19 @@ gen r u _ gc = go <$> remoteCost gc defcst
, hasKey = inAnnex r
, hasKeyCheap = repoCheap r
, whereisKey = Nothing
- , config = M.empty
- , localpath = if Git.repoIsLocal r || Git.repoIsLocalUnknown r
- then Just $ Git.repoPath r
- else Nothing
+ , remoteFsck = if Git.repoIsUrl r
+ then Nothing
+ else Just $ fsckOnRemote r
+ , repairRepo = if Git.repoIsUrl r
+ then Nothing
+ else Just $ repairRemote r
+ , config = c
+ , localpath = localpathCalc r
, repo = r
, gitconfig = gc
{ remoteGitConfig = Just $ extractGitConfig r }
, readonly = Git.repoIsHttp r
- , globallyAvailable = not $ Git.repoIsLocal r || Git.repoIsLocalUnknown r
+ , globallyAvailable = globallyAvailableCalc r
, remotetype = remote
}
@@ -126,24 +134,25 @@ gen r u _ gc = go <$> remoteCost gc defcst
repoAvail :: Git.Repo -> Annex Bool
repoAvail r
| Git.repoIsHttp r = return True
+ | Git.GCrypt.isEncrypted r = do
+ g <- gitRepo
+ liftIO $ do
+ er <- Git.GCrypt.encryptedRemote g r
+ if Git.repoIsLocal er || Git.repoIsLocalUnknown er
+ then catchBoolIO $
+ void (Git.Config.read er) >> return True
+ else return True
| Git.repoIsUrl r = return True
| Git.repoIsLocalUnknown r = return False
| otherwise = liftIO $ catchBoolIO $ onLocal r $ return True
-{- Avoids performing an action on a local repository that's not usable.
- - Does not check that the repository is still available on disk. -}
-guardUsable :: Git.Repo -> a -> Annex a -> Annex a
-guardUsable r onerr a
- | Git.repoIsLocalUnknown r = return onerr
- | otherwise = a
-
{- Tries to read the config for a specified remote, updates state, and
- returns the updated repo. -}
tryGitConfigRead :: Git.Repo -> Annex Git.Repo
tryGitConfigRead r
| haveconfig r = return r -- already read
| Git.repoIsSsh r = store $ do
- v <- onRemote r (pipedconfig, Left undefined) "configlist" [] []
+ v <- Ssh.onRemote r (pipedconfig, Left undefined) "configlist" [] []
case v of
Right r'
| haveconfig r' -> return r'
@@ -152,6 +161,7 @@ tryGitConfigRead r
| Git.repoIsHttp r = do
headers <- getHttpHeaders
store $ geturlconfig headers
+ | Git.GCrypt.isEncrypted r = handlegcrypt =<< getConfigMaybe (remoteConfig r "uuid")
| Git.repoIsUrl r = return r
| otherwise = store $ safely $ onLocal r $ do
ensureInitialized
@@ -164,23 +174,22 @@ tryGitConfigRead r
safely a = either (const $ return r) return
=<< liftIO (try a :: IO (Either SomeException Git.Repo))
- pipedconfig cmd params = try run :: IO (Either SomeException Git.Repo)
- where
- run = withHandle StdoutHandle createProcessSuccess p $ \h -> do
- fileEncoding h
- val <- hGetContentsStrict h
- r' <- Git.Config.store val r
- when (getUncachedUUID r' == NoUUID && not (null val)) $ do
- warningIO $ "Failed to get annex.uuid configuration of repository " ++ Git.repoDescribe r
- warningIO $ "Instead, got: " ++ show val
- warningIO $ "This is unexpected; please check the network transport!"
- return r'
- p = proc cmd $ toCommand params
+ pipedconfig cmd params = do
+ v <- Git.Config.fromPipe r cmd params
+ case v of
+ Right (r', val) -> do
+ when (getUncachedUUID r' == NoUUID && not (null val)) $ do
+ warningIO $ "Failed to get annex.uuid configuration of repository " ++ Git.repoDescribe r
+ warningIO $ "Instead, got: " ++ show val
+ warningIO $ "This is unexpected; please check the network transport!"
+ return $ Right r'
+ Left l -> return $ Left l
geturlconfig headers = do
+ ua <- Url.getUserAgent
v <- liftIO $ withTmpFile "git-annex.tmp" $ \tmpfile h -> do
hClose h
- ifM (Url.downloadQuiet (Git.repoLocation r ++ "/config") headers [] tmpfile)
+ ifM (Url.downloadQuiet (Git.repoLocation r ++ "/config") headers [] tmpfile ua)
( pipedconfig "git" [Param "config", Param "--null", Param "--list", Param "--file", File tmpfile]
, return $ Left undefined
)
@@ -210,7 +219,7 @@ tryGitConfigRead r
Nothing -> return r
Just n -> do
whenM (inRepo $ Git.Command.runBool [Param "fetch", Param "--quiet", Param n]) $
- set_ignore $ "does not have git-annex installed"
+ set_ignore "does not have git-annex installed"
return r
set_ignore msg = case Git.remoteName r of
@@ -219,6 +228,15 @@ tryGitConfigRead r
let k = "remote." ++ n ++ ".annex-ignore"
warning $ "Remote " ++ n ++ " " ++ msg ++ "; setting " ++ k
inRepo $ Git.Command.run [Param "config", Param k, Param "true"]
+
+ handlegcrypt Nothing = return r
+ handlegcrypt (Just _cacheduuid) = do
+ -- Generate UUID from the gcrypt-id
+ g <- gitRepo
+ case Git.GCrypt.remoteRepoId g (Git.remoteName r) of
+ Nothing -> return r
+ Just v -> store $ liftIO $ setUUID r $
+ genUUIDInNameSpace gCryptNameSpace v
{- Checks if a given remote has the content for a key inAnnex.
- If the remote cannot be accessed, or if it cannot determine
@@ -231,39 +249,19 @@ inAnnex r key
| otherwise = checklocal
where
checkhttp headers = do
- showchecking
- liftIO $ ifM (anyM (\u -> Url.check u headers (keySize key)) (keyUrls r key))
+ showChecking r
+ ifM (anyM (\u -> Url.withUserAgent $ Url.checkBoth u headers (keySize key)) (keyUrls r key))
( return $ Right True
, return $ Left "not found"
)
- checkremote = do
- showchecking
- onRemote r (check, unknown) "inannex" [Param (key2file key)] []
- where
- check c p = dispatch <$> safeSystem c p
- dispatch ExitSuccess = Right True
- dispatch (ExitFailure 1) = Right False
- dispatch _ = unknown
- checklocal = guardUsable r unknown $ dispatch <$> check
+ checkremote = Ssh.inAnnex r key
+ checklocal = guardUsable r (cantCheck r) $ dispatch <$> check
where
check = liftIO $ catchMsgIO $ onLocal r $
Annex.Content.inAnnexSafe key
dispatch (Left e) = Left e
dispatch (Right (Just b)) = Right b
- dispatch (Right Nothing) = unknown
- unknown = Left $ "unable to check " ++ Git.repoDescribe r
- showchecking = showAction $ "checking " ++ Git.repoDescribe r
-
-{- Runs an action on a local repository inexpensively, by making an annex
- - monad using that repository. -}
-onLocal :: Git.Repo -> Annex a -> IO a
-onLocal r a = do
- s <- Annex.new r
- Annex.eval s $ do
- -- No need to update the branch; its data is not used
- -- for anything onLocal is used to do.
- Annex.BranchState.disableUpdate
- a
+ dispatch (Right Nothing) = cantCheck r
keyUrls :: Git.Repo -> Key -> [String]
keyUrls r key = map tourl locs
@@ -286,12 +284,8 @@ dropKey r key
logStatus key InfoMissing
Annex.Content.saveState True
return True
- | Git.repoIsHttp (repo r) = error "dropping from http repo not supported"
- | otherwise = commitOnCleanup r $ onRemote (repo r) (boolSystem, False) "dropkey"
- [ Params "--quiet --force"
- , Param $ key2file key
- ]
- []
+ | Git.repoIsHttp (repo r) = error "dropping from http remote not supported"
+ | otherwise = commitOnCleanup r $ Ssh.dropKey (repo r) key
{- Tries to copy a key's content from a remote's annex to a file. -}
copyFromRemote :: Remote -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> Annex Bool
@@ -299,7 +293,7 @@ copyFromRemote r key file dest _p = copyFromRemote' r key file dest
copyFromRemote' :: Remote -> Key -> AssociatedFile -> FilePath -> Annex Bool
copyFromRemote' r key file dest
| not $ Git.repoIsUrl (repo r) = guardUsable (repo r) False $ do
- let params = rsyncParams r
+ let params = Ssh.rsyncParams r
u <- getUUID
-- run copy from perspective of remote
liftIO $ onLocal (repo r) $ do
@@ -311,11 +305,12 @@ copyFromRemote' r key file dest
upload u key file noRetry
(rsyncOrCopyFile params object dest)
<&&> checksuccess
- | Git.repoIsSsh (repo r) = feedprogressback $ \feeder ->
- rsyncHelper (Just feeder)
- =<< rsyncParamsRemote r Download key dest file
+ | Git.repoIsSsh (repo r) = feedprogressback $ \feeder -> do
+ direct <- isDirect
+ Ssh.rsyncHelper (Just feeder)
+ =<< Ssh.rsyncParamsRemote direct r Download key dest file
| Git.repoIsHttp (repo r) = Annex.Content.downloadUrl (keyUrls (repo r) key) dest
- | otherwise = error "copying from non-ssh, non-http repo not supported"
+ | otherwise = error "copying from non-ssh, non-http remote not supported"
where
{- Feed local rsync's progress info back to the remote,
- by forking a feeder thread that runs
@@ -340,9 +335,9 @@ copyFromRemote' r key file dest
u <- getUUID
let fields = (Fields.remoteUUID, fromUUID u)
: maybe [] (\f -> [(Fields.associatedFile, f)]) file
- Just (cmd, params) <- git_annex_shell (repo r) "transferinfo"
+ Just (cmd, params) <- Ssh.git_annex_shell (repo r) "transferinfo"
[Param $ key2file key] fields
- v <- liftIO $ (newEmptySV :: IO (MSampleVar Integer))
+ v <- liftIO (newEmptySV :: IO (MSampleVar Integer))
tid <- liftIO $ forkIO $ void $ tryIO $ do
bytes <- readSV v
p <- createProcess $
@@ -353,7 +348,7 @@ copyFromRemote' r key file dest
hClose $ stderrHandle p
let h = stdinHandle p
let send b = do
- hPutStrLn h $ show b
+ hPrint h b
hFlush h
send bytes
forever $
@@ -385,8 +380,10 @@ copyToRemote r key file p
guardUsable (repo r) False $ commitOnCleanup r $
copylocal =<< Annex.Content.prepSendAnnex key
| Git.repoIsSsh (repo r) = commitOnCleanup r $
- Annex.Content.sendAnnex key noop $ \object ->
- rsyncHelper (Just p) =<< rsyncParamsRemote r Upload key object file
+ Annex.Content.sendAnnex key noop $ \object -> do
+ direct <- isDirect
+ Ssh.rsyncHelper (Just p)
+ =<< Ssh.rsyncParamsRemote direct r Upload key object file
| otherwise = error "copying to non-ssh repo not supported"
where
copylocal Nothing = return False
@@ -395,7 +392,7 @@ copyToRemote r key file p
-- the remote's Annex, but it needs access to the current
-- Annex monad's state.
checksuccessio <- Annex.withCurrentState checksuccess
- let params = rsyncParams r
+ let params = Ssh.rsyncParams r
u <- getUUID
-- run copy from perspective of remote
liftIO $ onLocal (repo r) $ ifM (Annex.Content.inAnnex key)
@@ -408,15 +405,37 @@ copyToRemote r key file p
(\d -> rsyncOrCopyFile params object d p)
)
-rsyncHelper :: Maybe MeterUpdate -> [CommandParam] -> Annex Bool
-rsyncHelper callback params = do
- showOutput -- make way for progress bar
- ifM (liftIO $ (maybe rsync rsyncProgress callback) params)
- ( return True
- , do
- showLongNote "rsync failed -- run git annex again to resume file transfer"
- return False
- )
+fsckOnRemote :: Git.Repo -> [CommandParam] -> Annex (IO Bool)
+fsckOnRemote r params
+ | Git.repoIsUrl r = do
+ s <- Ssh.git_annex_shell r "fsck" params []
+ return $ case s of
+ Nothing -> return False
+ Just (c, ps) -> batchCommand c ps
+ | otherwise = return $ do
+ program <- readProgramFile
+ env <- getEnvironment
+ r' <- Git.Config.read r
+ let env' =
+ [ ("GIT_WORK_TREE", Git.repoPath r')
+ , ("GIT_DIR", Git.localGitDir r')
+ ] ++ env
+ batchCommandEnv program (Param "fsck" : params) (Just env')
+
+{- The passed repair action is run in the Annex monad of the remote. -}
+repairRemote :: Git.Repo -> Annex Bool -> Annex (IO Bool)
+repairRemote r a = return $ Remote.Git.onLocal r a
+
+{- Runs an action on a local repository inexpensively, by making an annex
+ - monad using that repository. -}
+onLocal :: Git.Repo -> Annex a -> IO a
+onLocal r a = do
+ s <- Annex.new r
+ Annex.eval s $ do
+ -- No need to update the branch; its data is not used
+ -- for anything onLocal is used to do.
+ Annex.BranchState.disableUpdate
+ a
{- Copys a file with rsync unless both locations are on the same
- filesystem. Then cp could be faster. -}
@@ -428,7 +447,7 @@ rsyncOrCopyFile rsyncparams src dest p =
#else
ifM (sameDeviceIds src dest) (docopy, dorsync)
where
- sameDeviceIds a b = (==) <$> (getDeviceId a) <*> (getDeviceId b)
+ sameDeviceIds a b = (==) <$> getDeviceId a <*> getDeviceId b
getDeviceId f = deviceID <$> liftIO (getFileStatus $ parentDir f)
docopy = liftIO $ bracket
(forkIO $ watchfilesize zeroBytesProcessed)
@@ -446,46 +465,9 @@ rsyncOrCopyFile rsyncparams src dest p =
watchfilesize sz
_ -> watchfilesize oldsz
#endif
- dorsync = rsyncHelper (Just p) $
+ dorsync = Ssh.rsyncHelper (Just p) $
rsyncparams ++ [File src, File dest]
-{- Generates rsync parameters that ssh to the remote and asks it
- - to either receive or send the key's content. -}
-rsyncParamsRemote :: Remote -> Direction -> Key -> FilePath -> AssociatedFile -> Annex [CommandParam]
-rsyncParamsRemote r direction key file afile = do
- u <- getUUID
- direct <- isDirect
- let fields = (Fields.remoteUUID, fromUUID u)
- : (Fields.direct, if direct then "1" else "")
- : maybe [] (\f -> [(Fields.associatedFile, f)]) afile
- Just (shellcmd, shellparams) <- git_annex_shell (repo r)
- (if direction == Download then "sendkey" else "recvkey")
- [ Param $ key2file key ]
- fields
- -- Convert the ssh command into rsync command line.
- let eparam = rsyncShell (Param shellcmd:shellparams)
- let o = rsyncParams r
- if direction == Download
- then return $ o ++ rsyncopts eparam dummy (File file)
- else return $ o ++ rsyncopts eparam (File file) dummy
- where
- rsyncopts ps source dest
- | end ps == [dashdash] = ps ++ [source, dest]
- | otherwise = ps ++ [dashdash, source, dest]
- dashdash = Param "--"
- {- The rsync shell parameter controls where rsync
- - goes, so the source/dest parameter can be a dummy value,
- - that just enables remote rsync mode.
- - For maximum compatability with some patched rsyncs,
- - the dummy value needs to still contain a hostname,
- - even though this hostname will never be used. -}
- dummy = Param "dummy:"
-
--- --inplace to resume partial files
-rsyncParams :: Remote -> [CommandParam]
-rsyncParams r = [Params "--progress --inplace"] ++
- map Param (remoteAnnexRsyncOptions $ gitconfig r)
-
commitOnCleanup :: Remote -> Annex a -> Annex a
commitOnCleanup r a = go `after` a
where
@@ -496,12 +478,12 @@ commitOnCleanup r a = go `after` a
Annex.Branch.commit "update"
| otherwise = void $ do
Just (shellcmd, shellparams) <-
- git_annex_shell (repo r) "commit" [] []
+ Ssh.git_annex_shell (repo r) "commit" [] []
-- Throw away stderr, since the remote may not
-- have a new enough git-annex shell to
-- support committing.
- liftIO $ catchMaybeIO $ do
+ liftIO $ catchMaybeIO $
withQuietOutput createProcessSuccess $
proc shellcmd $
toCommand shellparams
diff --git a/Remote/Glacier.hs b/Remote/Glacier.hs
index c1a53347d..300e682a7 100644
--- a/Remote/Glacier.hs
+++ b/Remote/Glacier.hs
@@ -25,6 +25,7 @@ import Creds
import Utility.Metered
import qualified Annex
import Annex.Content
+import Annex.UUID
import System.Process
@@ -39,10 +40,10 @@ remote = RemoteType {
setup = glacierSetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = new <$> remoteCost gc veryExpensiveRemoteCost
where
- new cst = encryptableRemote c
+ new cst = Just $ encryptableRemote c
(storeEncrypted this)
(retrieveEncrypted this)
this
@@ -58,6 +59,8 @@ gen r u c gc = new <$> remoteCost gc veryExpensiveRemoteCost
hasKey = checkPresent this,
hasKeyCheap = False,
whereisKey = Nothing,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
config = c,
repo = r,
gitconfig = gc,
@@ -67,13 +70,18 @@ gen r u c gc = new <$> remoteCost gc veryExpensiveRemoteCost
remotetype = remote
}
-glacierSetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-glacierSetup u c = do
+glacierSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+glacierSetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
+ glacierSetup' u c
+glacierSetup' :: UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+glacierSetup' u c = do
c' <- encryptionSetup c
let fullconfig = c' `M.union` defaults
genVault fullconfig u
gitConfigSpecialRemote u fullconfig "glacier" "true"
- setRemoteCredPair fullconfig (AWS.creds u)
+ c'' <- setRemoteCredPair fullconfig (AWS.creds u)
+ return (c'', u)
where
remotename = fromJust (M.lookup "name" c)
defvault = remotename ++ "-" ++ fromUUID u
@@ -92,10 +100,10 @@ store r k _f p
storeHelper r k $ streamMeteredFile src meterupdate
storeEncrypted :: Remote -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
-storeEncrypted r (cipher, enck) k p = sendAnnex k (void $ remove r enck) $ \src -> do
+storeEncrypted r (cipher, enck) k p = sendAnnex k (void $ remove r enck) $ \src ->
metered (Just p) k $ \meterupdate ->
storeHelper r enck $ \h ->
- encrypt (getGpgOpts r) cipher (feedFile src)
+ encrypt (getGpgEncParams r) cipher (feedFile src)
(readBytes $ meteredWrite meterupdate h)
retrieve :: Remote -> Key -> AssociatedFile -> FilePath -> MeterUpdate -> Annex Bool
@@ -203,7 +211,7 @@ checkPresent r k = do
]
glacierAction :: Remote -> [CommandParam] -> Annex Bool
-glacierAction r params = runGlacier (config r) (uuid r) params
+glacierAction r = runGlacier (config r) (uuid r)
runGlacier :: RemoteConfig -> UUID -> [CommandParam] -> Annex Bool
runGlacier c u params = go =<< glacierEnv c u
@@ -216,7 +224,7 @@ glacierParams :: RemoteConfig -> [CommandParam] -> [CommandParam]
glacierParams c params = datacenter:params
where
datacenter = Param $ "--region=" ++
- (fromJust $ M.lookup "datacenter" c)
+ fromJust (M.lookup "datacenter" c)
glacierEnv :: RemoteConfig -> UUID -> Annex (Maybe [(String, String)])
glacierEnv c u = go =<< getRemoteCredPairFor "glacier" c creds
@@ -276,7 +284,7 @@ jobList r keys = go =<< glacierEnv (config r) (uuid r)
enckeys <- forM keys $ \k ->
maybe k snd <$> cipherKey (config r) k
let keymap = M.fromList $ zip enckeys keys
- let convert = catMaybes . map (`M.lookup` keymap)
+ let convert = mapMaybe (`M.lookup` keymap)
return (convert succeeded, convert failed)
parse c [] = c
diff --git a/Remote/Helper/Chunked.hs b/Remote/Helper/Chunked.hs
index 46678de70..ad3b04d49 100644
--- a/Remote/Helper/Chunked.hs
+++ b/Remote/Helper/Chunked.hs
@@ -43,6 +43,10 @@ type ChunkExt = String
chunkCount :: ChunkExt
chunkCount = ".chunkcount"
+{- An infinite stream of extensions to use for chunks. -}
+chunkStream :: [ChunkExt]
+chunkStream = map (\n -> ".chunk" ++ show n) [1 :: Integer ..]
+
{- Parses the String from the chunkCount file, and returns the files that
- are used to store the chunks. -}
listChunks :: FilePath -> String -> [FilePath]
@@ -50,15 +54,28 @@ listChunks basedest chunkcount = take count $ map (basedest ++) chunkStream
where
count = fromMaybe 0 $ readish chunkcount
-{- An infinite stream of extensions to use for chunks. -}
-chunkStream :: [ChunkExt]
-chunkStream = map (\n -> ".chunk" ++ show n) [1 :: Integer ..]
+{- For use when there is no chunkCount file; uses the action to find
+ - chunks, and returns them, or Nothing if none found. Relies on
+ - storeChunks's finalizer atomically moving the chunks into place once all
+ - are written.
+ -
+ - This is only needed to work around a bug that caused the chunkCount file
+ - not to be written.
+ -}
+probeChunks :: FilePath -> (FilePath -> IO Bool) -> IO [FilePath]
+probeChunks basedest check = go [] $ map (basedest ++) chunkStream
+ where
+ go l [] = return (reverse l)
+ go l (c:cs) = ifM (check c)
+ ( go (c:l) cs
+ , go l []
+ )
{- Given the base destination to use to store a value,
- generates a stream of temporary destinations (just one when not chunking)
- and passes it to an action, which should chunk and store the data,
- and return the destinations it stored to, or [] on error. Then
- - calls the storer to write the chunk count (if chunking). Finally, the
+ - calls the recorder to write the chunk count (if chunking). Finally, the
- finalizer is called to rename the tmp into the dest
- (and do any other cleanup).
-}
@@ -68,7 +85,7 @@ storeChunks key tmp dest chunksize storer recorder finalizer = either onerr retu
where
go = do
stored <- storer tmpdests
- when (chunksize /= Nothing) $ do
+ when (isJust chunksize) $ do
let chunkcount = basef ++ chunkCount
recorder chunkcount (show $ length stored)
finalizer tmp dest
@@ -79,7 +96,7 @@ storeChunks key tmp dest chunksize storer recorder finalizer = either onerr retu
basef = tmp ++ keyFile key
tmpdests
- | chunksize == Nothing = [basef]
+ | isNothing chunksize = [basef]
| otherwise = map (basef ++ ) chunkStream
{- Given a list of destinations to use, chunks the data according to the
@@ -123,5 +140,5 @@ storeChunked chunksize dests storer content = either onerr return
meteredWriteFileChunks :: MeterUpdate -> FilePath -> [v] -> (v -> IO L.ByteString) -> IO ()
meteredWriteFileChunks meterupdate dest chunks feeder =
withBinaryFile dest WriteMode $ \h ->
- forM_ chunks $ \c ->
- meteredWrite meterupdate h =<< feeder c
+ forM_ chunks $
+ meteredWrite meterupdate h <=< feeder
diff --git a/Remote/Helper/Encryptable.hs b/Remote/Helper/Encryptable.hs
index 22e1c9fc0..a6e79ddc4 100644
--- a/Remote/Helper/Encryptable.hs
+++ b/Remote/Helper/Encryptable.hs
@@ -23,30 +23,52 @@ import Utility.Metered
- updated to be accessible to an additional encryption key. Or the user
- could opt to use a shared cipher, which is stored unencrypted. -}
encryptionSetup :: RemoteConfig -> Annex RemoteConfig
-encryptionSetup c = case (M.lookup "encryption" c, extractCipher c) of
- (Nothing, Nothing) -> error "Specify encryption=key or encryption=none or encryption=shared"
- (Just "none", Nothing) -> return c
- (Nothing, Just _) -> return c
- (Just "shared", Just (SharedCipher _)) -> return c
- (Just "none", Just _) -> cannotchange
- (Just "shared", Just (EncryptedCipher _ _)) -> cannotchange
- (Just _, Just (SharedCipher _)) -> cannotchange
- (Just "shared", Nothing) -> use "encryption setup" . genSharedCipher
- =<< highRandomQuality
- (Just keyid, Nothing) -> use "encryption setup" . genEncryptedCipher keyid
- =<< highRandomQuality
- (Just keyid, Just v) -> use "encryption update" $ updateEncryptedCipher keyid v
+encryptionSetup c = maybe genCipher updateCipher $ extractCipher c
where
- cannotchange = error "Cannot change encryption type of existing remote."
+ -- The type of encryption
+ encryption = M.lookup "encryption" c
+ -- Generate a new cipher, depending on the chosen encryption scheme
+ genCipher = case encryption of
+ _ | M.member "cipher" c || M.member "cipherkeys" c -> cannotchange
+ Just "none" -> return c
+ Just "shared" -> use "encryption setup" . genSharedCipher
+ =<< highRandomQuality
+ -- hybrid encryption is the default when a keyid is
+ -- specified but no encryption
+ _ | maybe (M.member "keyid" c) (== "hybrid") encryption ->
+ use "encryption setup" . genEncryptedCipher key Hybrid
+ =<< highRandomQuality
+ Just "pubkey" -> use "encryption setup" . genEncryptedCipher key PubKey
+ =<< highRandomQuality
+ _ -> error $ "Specify " ++ intercalate " or "
+ (map ("encryption=" ++)
+ ["none","shared","hybrid","pubkey"])
+ ++ "."
+ key = fromMaybe (error "Specifiy keyid=...") $ M.lookup "keyid" c
+ newkeys = maybe [] (\k -> [(True,k)]) (M.lookup "keyid+" c) ++
+ maybe [] (\k -> [(False,k)]) (M.lookup "keyid-" c)
+ cannotchange = error "Cannot set encryption type of existing remotes."
+ -- Update an existing cipher if possible.
+ updateCipher v = case v of
+ SharedCipher _ | maybe True (== "shared") encryption -> return c'
+ EncryptedCipher _ variant _
+ | maybe True (== if variant == Hybrid then "hybrid" else "pubkey") encryption ->
+ use "encryption update" $ updateEncryptedCipher newkeys v
+ _ -> cannotchange
use m a = do
showNote m
cipher <- liftIO a
showNote $ describeCipher cipher
- return $ M.delete "encryption" $ M.delete "highRandomQuality" $
- storeCipher c cipher
+ return $ storeCipher c' cipher
highRandomQuality =
(&&) (maybe True ( /= "false") $ M.lookup "highRandomQuality" c)
<$> fmap not (Annex.getState Annex.fast)
+ c' = foldr M.delete c
+ -- git-annex used to remove 'encryption' as well, since
+ -- it was redundant; we now need to keep it for
+ -- public-key incryption, hence we leave it on newer
+ -- remotes (while being backward-compatible).
+ [ "keyid", "keyid+", "keyid-", "highRandomQuality" ]
{- Modifies a Remote to support encryption.
-
@@ -113,25 +135,30 @@ embedCreds c
{- Gets encryption Cipher, and encrypted version of Key. -}
cipherKey :: RemoteConfig -> Key -> Annex (Maybe (Cipher, Key))
-cipherKey c k = maybe Nothing make <$> remoteCipher c
+cipherKey c k = fmap make <$> remoteCipher c
where
- make ciphertext = Just (ciphertext, encryptKey mac ciphertext k)
+ make ciphertext = (ciphertext, encryptKey mac ciphertext k)
mac = fromMaybe defaultMac $ M.lookup "mac" c >>= readMac
{- Stores an StorableCipher in a remote's configuration. -}
storeCipher :: RemoteConfig -> StorableCipher -> RemoteConfig
storeCipher c (SharedCipher t) = M.insert "cipher" (toB64 t) c
-storeCipher c (EncryptedCipher t ks) =
+storeCipher c (EncryptedCipher t _ ks) =
M.insert "cipher" (toB64 t) $ M.insert "cipherkeys" (showkeys ks) c
where
showkeys (KeyIds l) = intercalate "," l
{- Extracts an StorableCipher from a remote's configuration. -}
extractCipher :: RemoteConfig -> Maybe StorableCipher
-extractCipher c =
- case (M.lookup "cipher" c, M.lookup "cipherkeys" c) of
- (Just t, Just ks) -> Just $ EncryptedCipher (fromB64 t) (readkeys ks)
- (Just t, Nothing) -> Just $ SharedCipher (fromB64 t)
- _ -> Nothing
+extractCipher c = case (M.lookup "cipher" c,
+ M.lookup "cipherkeys" c,
+ M.lookup "encryption" c) of
+ (Just t, Just ks, encryption) | maybe True (== "hybrid") encryption ->
+ Just $ EncryptedCipher (fromB64 t) Hybrid (readkeys ks)
+ (Just t, Just ks, Just "pubkey") ->
+ Just $ EncryptedCipher (fromB64 t) PubKey (readkeys ks)
+ (Just t, Nothing, encryption) | maybe True (== "shared") encryption ->
+ Just $ SharedCipher (fromB64 t)
+ _ -> Nothing
where
readkeys = KeyIds . split ","
diff --git a/Remote/Helper/Git.hs b/Remote/Helper/Git.hs
new file mode 100644
index 000000000..7c24ff2e7
--- /dev/null
+++ b/Remote/Helper/Git.hs
@@ -0,0 +1,30 @@
+{- Utilities for git remotes.
+ -
+ - Copyright 2011-2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Remote.Helper.Git where
+
+import Common.Annex
+import qualified Git
+
+repoCheap :: Git.Repo -> Bool
+repoCheap = not . Git.repoIsUrl
+
+localpathCalc :: Git.Repo -> Maybe FilePath
+localpathCalc r = if globallyAvailableCalc r
+ then Nothing
+ else Just $ Git.repoPath r
+
+globallyAvailableCalc :: Git.Repo -> Bool
+globallyAvailableCalc r = not $
+ Git.repoIsLocal r || Git.repoIsLocalUnknown r
+
+{- Avoids performing an action on a local repository that's not usable.
+ - Does not check that the repository is still available on disk. -}
+guardUsable :: Git.Repo -> a -> Annex a -> Annex a
+guardUsable r onerr a
+ | Git.repoIsLocalUnknown r = return onerr
+ | otherwise = a
diff --git a/Remote/Helper/Hooks.hs b/Remote/Helper/Hooks.hs
index 7c2bf68ca..91c6318bf 100644
--- a/Remote/Helper/Hooks.hs
+++ b/Remote/Helper/Hooks.hs
@@ -35,8 +35,8 @@ addHooks' r starthook stophook = r'
{ storeKey = \k f p -> wrapper $ storeKey r k f p
, retrieveKeyFile = \k f d p -> wrapper $ retrieveKeyFile r k f d p
, retrieveKeyFileCheap = \k f -> wrapper $ retrieveKeyFileCheap r k f
- , removeKey = \k -> wrapper $ removeKey r k
- , hasKey = \k -> wrapper $ hasKey r k
+ , removeKey = wrapper . removeKey r
+ , hasKey = wrapper . hasKey r
}
where
wrapper = runHooks r' starthook stophook
@@ -45,7 +45,7 @@ runHooks :: Remote -> Maybe String -> Maybe String -> Annex a -> Annex a
runHooks r starthook stophook a = do
dir <- fromRepo gitAnnexRemotesDir
let lck = dir </> remoteid ++ ".lck"
- whenM (not . any (== lck) . M.keys <$> getPool) $ do
+ whenM (notElem lck . M.keys <$> getPool) $ do
liftIO $ createDirectoryIfMissing True dir
firstrun lck
a
@@ -73,7 +73,7 @@ runHooks r starthook stophook a = do
run starthook
Annex.addCleanup (remoteid ++ "-stop-command") $ runstop lck
-#ifndef __WINDOWS__
+#ifndef mingw32_HOST_OS
runstop lck = do
-- Drop any shared lock we have, and take an
-- exclusive lock, without blocking. If the lock
diff --git a/Remote/Helper/Messages.hs b/Remote/Helper/Messages.hs
new file mode 100644
index 000000000..c4b1966dc
--- /dev/null
+++ b/Remote/Helper/Messages.hs
@@ -0,0 +1,17 @@
+{- git-annex remote messages
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Remote.Helper.Messages where
+
+import Common.Annex
+import qualified Git
+
+showChecking :: Git.Repo -> Annex ()
+showChecking r = showAction $ "checking " ++ Git.repoDescribe r
+
+cantCheck :: Git.Repo -> Either String Bool
+cantCheck r = Left $ "unable to check " ++ Git.repoDescribe r
diff --git a/Remote/Helper/Ssh.hs b/Remote/Helper/Ssh.hs
index f8e9353b7..8cf9275a0 100644
--- a/Remote/Helper/Ssh.hs
+++ b/Remote/Helper/Ssh.hs
@@ -1,6 +1,6 @@
-{- git-annex remote access with ssh
+{- git-annex remote access with ssh and git-annex-shell
-
- - Copyright 2011,2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2011-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -12,19 +12,26 @@ import qualified Git
import qualified Git.Url
import Annex.UUID
import Annex.Ssh
-import Fields
+import Fields (Field, fieldName)
+import qualified Fields
import Types.GitConfig
+import Types.Key
+import Remote.Helper.Messages
+import Utility.Metered
+import Utility.Rsync
+import Types.Remote
+import Logs.Transfer
{- Generates parameters to ssh to a repository's host and run a command.
- Caller is responsible for doing any neccessary shellEscaping of the
- passed command. -}
-sshToRepo :: Git.Repo -> [CommandParam] -> Annex [CommandParam]
-sshToRepo repo sshcmd = do
+toRepo :: Git.Repo -> [CommandParam] -> Annex [CommandParam]
+toRepo r sshcmd = do
g <- fromRepo id
- let c = extractRemoteGitConfig g (Git.repoDescribe repo)
+ let c = extractRemoteGitConfig g (Git.repoDescribe r)
let opts = map Param $ remoteAnnexSshOptions c
- let host = Git.Url.hostuser repo
- params <- sshCachingOptions (host, Git.Url.port repo) opts
+ let host = fromMaybe (error "bad ssh url") $ Git.Url.hostuser r
+ params <- sshCachingOptions (host, Git.Url.port r) opts
return $ params ++ Param host : sshcmd
{- Generates parameters to run a git-annex-shell command on a remote
@@ -33,17 +40,17 @@ git_annex_shell :: Git.Repo -> String -> [CommandParam] -> [(Field, String)] ->
git_annex_shell r command params fields
| not $ Git.repoIsUrl r = return $ Just (shellcmd, shellopts ++ fieldopts)
| Git.repoIsSsh r = do
- uuid <- getRepoUUID r
- sshparams <- sshToRepo r [Param $ sshcmd uuid ]
+ u <- getRepoUUID r
+ sshparams <- toRepo r [Param $ sshcmd u ]
return $ Just ("ssh", sshparams)
| otherwise = return Nothing
where
dir = Git.repoPath r
shellcmd = "git-annex-shell"
shellopts = Param command : File dir : params
- sshcmd uuid = unwords $
+ sshcmd u = unwords $
shellcmd : map shellEscape (toCommand shellopts) ++
- uuidcheck uuid ++
+ uuidcheck u ++
map shellEscape (toCommand fieldopts)
uuidcheck NoUUID = []
uuidcheck (UUID u) = ["--uuid", u]
@@ -71,3 +78,69 @@ onRemote r (with, errorval) command params fields = do
case s of
Just (c, ps) -> liftIO $ with c ps
Nothing -> return errorval
+
+{- Checks if a remote contains a key. -}
+inAnnex :: Git.Repo -> Key -> Annex (Either String Bool)
+inAnnex r k = do
+ showChecking r
+ onRemote r (check, cantCheck r) "inannex" [Param $ key2file k] []
+ where
+ check c p = dispatch <$> safeSystem c p
+ dispatch ExitSuccess = Right True
+ dispatch (ExitFailure 1) = Right False
+ dispatch _ = cantCheck r
+
+{- Removes a key from a remote. -}
+dropKey :: Git.Repo -> Key -> Annex Bool
+dropKey r key = onRemote r (boolSystem, False) "dropkey"
+ [ Params "--quiet --force"
+ , Param $ key2file key
+ ]
+ []
+
+rsyncHelper :: Maybe MeterUpdate -> [CommandParam] -> Annex Bool
+rsyncHelper callback params = do
+ showOutput -- make way for progress bar
+ ifM (liftIO $ (maybe rsync rsyncProgress callback) params)
+ ( return True
+ , do
+ showLongNote "rsync failed -- run git annex again to resume file transfer"
+ return False
+ )
+
+{- Generates rsync parameters that ssh to the remote and asks it
+ - to either receive or send the key's content. -}
+rsyncParamsRemote :: Bool -> Remote -> Direction -> Key -> FilePath -> AssociatedFile -> Annex [CommandParam]
+rsyncParamsRemote direct r direction key file afile = do
+ u <- getUUID
+ let fields = (Fields.remoteUUID, fromUUID u)
+ : (Fields.direct, if direct then "1" else "")
+ : maybe [] (\f -> [(Fields.associatedFile, f)]) afile
+ Just (shellcmd, shellparams) <- git_annex_shell (repo r)
+ (if direction == Download then "sendkey" else "recvkey")
+ [ Param $ key2file key ]
+ fields
+ -- Convert the ssh command into rsync command line.
+ let eparam = rsyncShell (Param shellcmd:shellparams)
+ let o = rsyncParams r
+ return $ if direction == Download
+ then o ++ rsyncopts eparam dummy (File file)
+ else o ++ rsyncopts eparam (File file) dummy
+ where
+ rsyncopts ps source dest
+ | end ps == [dashdash] = ps ++ [source, dest]
+ | otherwise = ps ++ [dashdash, source, dest]
+ dashdash = Param "--"
+ {- The rsync shell parameter controls where rsync
+ - goes, so the source/dest parameter can be a dummy value,
+ - that just enables remote rsync mode.
+ - For maximum compatability with some patched rsyncs,
+ - the dummy value needs to still contain a hostname,
+ - even though this hostname will never be used. -}
+ dummy = Param "dummy:"
+
+-- --inplace to resume partial files
+rsyncParams :: Remote -> [CommandParam]
+rsyncParams r = Params "--progress --inplace" :
+ map Param (remoteAnnexRsyncOptions $ gitconfig r)
+
diff --git a/Remote/Hook.hs b/Remote/Hook.hs
index 03f182a16..55ff78514 100644
--- a/Remote/Hook.hs
+++ b/Remote/Hook.hs
@@ -18,6 +18,7 @@ import qualified Git
import Config
import Config.Cost
import Annex.Content
+import Annex.UUID
import Remote.Helper.Special
import Remote.Helper.Encryptable
import Crypto
@@ -34,11 +35,11 @@ remote = RemoteType {
setup = hookSetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = do
cst <- remoteCost gc expensiveRemoteCost
- return $ encryptableRemote c
- (storeEncrypted hooktype $ getGpgOpts gc)
+ return $ Just $ encryptableRemote c
+ (storeEncrypted hooktype $ getGpgEncParams (c,gc))
(retrieveEncrypted hooktype)
Remote {
uuid = u,
@@ -51,7 +52,9 @@ gen r u c gc = do
hasKey = checkPresent r hooktype,
hasKeyCheap = False,
whereisKey = Nothing,
- config = M.empty,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
+ config = c,
localpath = Nothing,
repo = r,
gitconfig = gc,
@@ -62,13 +65,14 @@ gen r u c gc = do
where
hooktype = fromMaybe (error "missing hooktype") $ remoteAnnexHookType gc
-hookSetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-hookSetup u c = do
+hookSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+hookSetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
let hooktype = fromMaybe (error "Specify hooktype=") $
M.lookup "hooktype" c
c' <- encryptionSetup c
gitConfigSpecialRemote u c' "hooktype" hooktype
- return c'
+ return (c', u)
hookEnv :: Action -> Key -> Maybe FilePath -> IO (Maybe [(String, String)])
hookEnv action k f = Just <$> mergeenv (fileenv f ++ keyenv)
@@ -91,7 +95,7 @@ lookupHook hookname action = do
command <- getConfig (annexConfig hook) ""
if null command
then do
- fallback <- getConfig (annexConfig $ hookfallback) ""
+ fallback <- getConfig (annexConfig hookfallback) ""
if null fallback
then do
warning $ "missing configuration for " ++ hook ++ " or " ++ hookfallback
@@ -118,7 +122,7 @@ store :: HookName -> Key -> AssociatedFile -> MeterUpdate -> Annex Bool
store h k _f _p = sendAnnex k (void $ remove h k) $ \src ->
runHook h "store" k (Just src) $ return True
-storeEncrypted :: HookName -> GpgOpts -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
+storeEncrypted :: HookName -> [CommandParam] -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
storeEncrypted h gpgOpts (cipher, enck) k _p = withTmp enck $ \tmp ->
sendAnnex k (void $ remove h enck) $ \src -> do
liftIO $ encrypt gpgOpts cipher (feedFile src) $
diff --git a/Remote/List.hs b/Remote/List.hs
index 0651d83aa..d53b92912 100644
--- a/Remote/List.hs
+++ b/Remote/List.hs
@@ -22,6 +22,7 @@ import qualified Git
import qualified Git.Config
import qualified Remote.Git
+import qualified Remote.GCrypt
#ifdef WITH_S3
import qualified Remote.S3
#endif
@@ -38,6 +39,7 @@ import qualified Remote.Hook
remoteTypes :: [RemoteType]
remoteTypes =
[ Remote.Git.remote
+ , Remote.GCrypt.remote
#ifdef WITH_S3
, Remote.S3.remote
#endif
@@ -65,7 +67,7 @@ remoteList = do
return rs'
else return rs
where
- process m t = enumerate t >>= mapM (remoteGen m t)
+ process m t = enumerate t >>= mapM (remoteGen m t) >>= return . catMaybes
{- Forces the remoteList to be re-generated, re-reading the git config. -}
remoteListRefresh :: Annex [Remote]
@@ -78,16 +80,17 @@ remoteListRefresh = do
remoteList
{- Generates a Remote. -}
-remoteGen :: (M.Map UUID RemoteConfig) -> RemoteType -> Git.Repo -> Annex Remote
+remoteGen :: M.Map UUID RemoteConfig -> RemoteType -> Git.Repo -> Annex (Maybe Remote)
remoteGen m t r = do
u <- getRepoUUID r
g <- fromRepo id
let gc = extractRemoteGitConfig g (Git.repoDescribe r)
let c = fromMaybe M.empty $ M.lookup u m
- addHooks <$> generate t r u c gc
+ mrmt <- generate t r u c gc
+ return $ addHooks <$> mrmt
{- Updates a local git Remote, re-reading its git config. -}
-updateRemote :: Remote -> Annex Remote
+updateRemote :: Remote -> Annex (Maybe Remote)
updateRemote remote = do
m <- readRemoteLog
remote' <- updaterepo $ repo remote
@@ -98,6 +101,7 @@ updateRemote remote = do
Remote.Git.configRead r
| otherwise = return r
-{- Checks if a remote is a special remote -}
-specialRemote :: Remote -> Bool
-specialRemote r = remotetype r /= Remote.Git.remote
+{- Checks if a remote is syncable using git. -}
+syncableRemote :: Remote -> Bool
+syncableRemote r = remotetype r `elem`
+ [ Remote.Git.remote, Remote.GCrypt.remote ]
diff --git a/Remote/Rsync.hs b/Remote/Rsync.hs
index a8efd84e7..91638de98 100644
--- a/Remote/Rsync.hs
+++ b/Remote/Rsync.hs
@@ -7,7 +7,16 @@
{-# LANGUAGE CPP #-}
-module Remote.Rsync (remote) where
+module Remote.Rsync (
+ remote,
+ storeEncrypted,
+ retrieveEncrypted,
+ remove,
+ checkPresent,
+ withRsyncScratchDir,
+ genRsyncOpts,
+ RsyncOpts
+) where
import qualified Data.ByteString.Lazy as L
import qualified Data.Map as M
@@ -23,6 +32,7 @@ import qualified Git
import Config
import Config.Cost
import Annex.Content
+import Annex.UUID
import Annex.Ssh
import Remote.Helper.Special
import Remote.Helper.Encryptable
@@ -48,14 +58,15 @@ remote = RemoteType {
setup = rsyncSetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = do
cst <- remoteCost gc expensiveRemoteCost
- (transport, url) <- rsyncTransport
- let o = RsyncOpts url (transport ++ opts) escape
- islocal = rsyncUrlIsPath $ rsyncUrl o
- return $ encryptableRemote c
- (storeEncrypted o $ getGpgOpts gc)
+ (transport, url) <- rsyncTransport gc $
+ fromMaybe (error "missing rsyncurl") $ remoteAnnexRsyncUrl gc
+ let o = genRsyncOpts c gc transport url
+ let islocal = rsyncUrlIsPath $ rsyncUrl o
+ return $ Just $ encryptableRemote c
+ (storeEncrypted o $ getGpgEncParams (c,gc))
(retrieveEncrypted o)
Remote
{ uuid = u
@@ -68,16 +79,21 @@ gen r u c gc = do
, hasKey = checkPresent r o
, hasKeyCheap = False
, whereisKey = Nothing
- , config = M.empty
+ , remoteFsck = Nothing
+ , repairRepo = Nothing
+ , config = c
, repo = r
, gitconfig = gc
, localpath = if islocal
then Just $ rsyncUrl o
else Nothing
, readonly = False
- , globallyAvailable = not $ islocal
+ , globallyAvailable = not islocal
, remotetype = remote
}
+
+genRsyncOpts :: RemoteConfig -> RemoteGitConfig -> [CommandParam] -> RsyncUrl -> RsyncOpts
+genRsyncOpts c gc transport url = RsyncOpts url (transport ++ opts) escape
where
opts = map Param $ filter safe $ remoteAnnexRsyncOptions gc
escape = M.lookup "shellescape" c /= Just "no"
@@ -88,31 +104,34 @@ gen r u c gc = do
| opt == "--delete" = False
| opt == "--delete-excluded" = False
| otherwise = True
- rawurl = fromMaybe (error "missing rsyncurl") $ remoteAnnexRsyncUrl gc
+
+rsyncTransport :: RemoteGitConfig -> RsyncUrl -> Annex ([CommandParam], RsyncUrl)
+rsyncTransport gc rawurl
+ | rsyncUrlIsShell rawurl =
+ (\rsh -> return (rsyncShell rsh, resturl)) =<<
+ case fromNull ["ssh"] (remoteAnnexRsyncTransport gc) of
+ "ssh":sshopts -> do
+ let (port, sshopts') = sshReadPort sshopts
+ host = takeWhile (/=':') resturl
+ -- Connection caching
+ (Param "ssh":) <$> sshCachingOptions
+ (host, port)
+ (map Param $ loginopt ++ sshopts')
+ "rsh":rshopts -> return $ map Param $ "rsh" :
+ loginopt ++ rshopts
+ rsh -> error $ "Unknown Rsync transport: "
+ ++ unwords rsh
+ | otherwise = return ([], rawurl)
+ where
(login,resturl) = case separate (=='@') rawurl of
- (h, "") -> (Nothing, h)
- (l, h) -> (Just l, h)
+ (h, "") -> (Nothing, h)
+ (l, h) -> (Just l, h)
loginopt = maybe [] (\l -> ["-l",l]) login
- fromNull as xs | null xs = as
- | otherwise = xs
- rsyncTransport = if rsyncUrlIsShell rawurl
- then (\rsh -> return (rsyncShell rsh, resturl)) =<<
- case fromNull ["ssh"] (remoteAnnexRsyncTransport gc) of
- "ssh":sshopts -> do
- let (port, sshopts') = sshReadPort sshopts
- host = takeWhile (/=':') resturl
- -- Connection caching
- (Param "ssh":) <$> sshCachingOptions
- (host, port)
- (map Param $ loginopt ++ sshopts')
- "rsh":rshopts -> return $ map Param $ "rsh" :
- loginopt ++ rshopts
- rsh -> error $ "Unknown Rsync transport: "
- ++ unwords rsh
- else return ([], rawurl)
+ fromNull as xs = if null xs then as else xs
-rsyncSetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-rsyncSetup u c = do
+rsyncSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+rsyncSetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let url = fromMaybe (error "Specify rsyncurl=") $
M.lookup "rsyncurl" c
@@ -121,7 +140,7 @@ rsyncSetup u c = do
-- The rsyncurl is stored in git config, not only in this remote's
-- persistant state, so it can vary between hosts.
gitConfigSpecialRemote u c' "rsyncurl" url
- return c'
+ return (c', u)
rsyncEscape :: RsyncOpts -> String -> String
rsyncEscape o s
@@ -137,7 +156,7 @@ rsyncUrls o k = map use annexHashes
store :: RsyncOpts -> Key -> AssociatedFile -> MeterUpdate -> Annex Bool
store o k _f p = sendAnnex k (void $ remove o k) $ rsyncSend o p k False
-storeEncrypted :: RsyncOpts -> GpgOpts -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
+storeEncrypted :: RsyncOpts -> [CommandParam] -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
storeEncrypted o gpgOpts (cipher, enck) k p = withTmp enck $ \tmp ->
sendAnnex k (void $ remove o enck) $ \src -> do
liftIO $ encrypt gpgOpts cipher (feedFile src) $
@@ -219,7 +238,7 @@ sendParams = ifM crippledFileSystem
{- Runs an action in an empty scratch directory that can be used to build
- up trees for rsync. -}
-withRsyncScratchDir :: (FilePath -> Annex Bool) -> Annex Bool
+withRsyncScratchDir :: (FilePath -> Annex a) -> Annex a
withRsyncScratchDir a = do
#ifndef mingw32_HOST_OS
v <- liftIO getProcessID
@@ -245,7 +264,7 @@ rsyncRetrieve o k dest callback =
, File dest
]
-rsyncRemote :: RsyncOpts -> (Maybe MeterUpdate) -> [CommandParam] -> Annex Bool
+rsyncRemote :: RsyncOpts -> Maybe MeterUpdate -> [CommandParam] -> Annex Bool
rsyncRemote o callback params = do
showOutput -- make way for progress bar
ifM (liftIO $ (maybe rsync rsyncProgress callback) ps)
diff --git a/Remote/S3.hs b/Remote/S3.hs
index 582bc2fda..0933f30de 100644
--- a/Remote/S3.hs
+++ b/Remote/S3.hs
@@ -30,6 +30,7 @@ import Crypto
import Creds
import Utility.Metered
import Annex.Content
+import Annex.UUID
import Logs.Web
type Bucket = String
@@ -42,10 +43,10 @@ remote = RemoteType {
setup = s3Setup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
where
- new cst = encryptableRemote c
+ new cst = Just $ encryptableRemote c
(storeEncrypted this)
(retrieveEncrypted this)
this
@@ -61,6 +62,8 @@ gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
hasKey = checkPresent this,
hasKeyCheap = False,
whereisKey = Nothing,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
config = c,
repo = r,
gitconfig = gc,
@@ -70,8 +73,12 @@ gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
remotetype = remote
}
-s3Setup :: UUID -> RemoteConfig -> Annex RemoteConfig
-s3Setup u c = if isIA c then archiveorg else defaulthost
+s3Setup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+s3Setup mu c = do
+ u <- maybe (liftIO genUUID) return mu
+ s3Setup' u c
+s3Setup' :: UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+s3Setup' u c = if isIA c then archiveorg else defaulthost
where
remotename = fromJust (M.lookup "name" c)
defbucket = remotename ++ "-" ++ fromUUID u
@@ -85,7 +92,8 @@ s3Setup u c = if isIA c then archiveorg else defaulthost
use fullconfig = do
gitConfigSpecialRemote u fullconfig "s3" "true"
- setRemoteCredPair fullconfig (AWS.creds u)
+ c' <- setRemoteCredPair fullconfig (AWS.creds u)
+ return (c', u)
defaulthost = do
c' <- encryptionSetup c
@@ -95,23 +103,24 @@ s3Setup u c = if isIA c then archiveorg else defaulthost
archiveorg = do
showNote "Internet Archive mode"
- maybe (error "specify bucket=") (const noop) $
- getBucket archiveconfig
- writeUUIDFile archiveconfig u
- use archiveconfig
- where
- archiveconfig =
+ -- Ensure user enters a valid bucket name, since
+ -- this determines the name of the archive.org item.
+ let bucket = replace " " "-" $ map toLower $
+ fromMaybe (error "specify bucket=") $
+ getBucket c
+ let archiveconfig =
-- hS3 does not pass through x-archive-* headers
M.mapKeys (replace "x-archive-" "x-amz-") $
-- encryption does not make sense here
M.insert "encryption" "none" $
+ M.insert "bucket" bucket $
M.union c $
-- special constraints on key names
M.insert "mungekeys" "ia" $
-- bucket created only when files are uploaded
- M.insert "x-amz-auto-make-bucket" "1" $
- -- no default bucket name; should be human-readable
- M.delete "bucket" defaults
+ M.insert "x-amz-auto-make-bucket" "1" defaults
+ writeUUIDFile archiveconfig u
+ use archiveconfig
store :: Remote -> Key -> AssociatedFile -> MeterUpdate -> Annex Bool
store r k _f p = s3Action r False $ \(conn, bucket) ->
@@ -129,7 +138,7 @@ storeEncrypted r (cipher, enck) k p = s3Action r False $ \(conn, bucket) ->
-- To get file size of the encrypted content, have to use a temp file.
-- (An alternative would be chunking to to a constant size.)
withTmp enck $ \tmp -> sendAnnex k (void $ remove' r enck) $ \src -> do
- liftIO $ encrypt (getGpgOpts r) cipher (feedFile src) $
+ liftIO $ encrypt (getGpgEncParams r) cipher (feedFile src) $
readBytes $ L.writeFile tmp
s3Bool =<< storeHelper (conn, bucket) r enck p tmp
diff --git a/Remote/Web.hs b/Remote/Web.hs
index 2c59528ef..0a8df35d5 100644
--- a/Remote/Web.hs
+++ b/Remote/Web.hs
@@ -5,6 +5,8 @@
- Licensed under the GNU GPL version 3 or higher.
-}
+{-# LANGUAGE CPP #-}
+
module Remote.Web (remote) where
import Common.Annex
@@ -15,11 +17,13 @@ import Annex.Content
import Config
import Config.Cost
import Logs.Web
-import qualified Utility.Url as Url
import Types.Key
import Utility.Metered
-
-import qualified Data.Map as M
+import qualified Annex.Url as Url
+#ifdef WITH_QUVI
+import Annex.Quvi
+import qualified Utility.Quvi as Quvi
+#endif
remote :: RemoteType
remote = RemoteType {
@@ -37,9 +41,9 @@ list = do
r <- liftIO $ Git.Construct.remoteNamed "web" Git.Construct.fromUnknown
return [r]
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
-gen r _ _ gc =
- return Remote {
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
+gen r _ c gc =
+ return $ Just Remote {
uuid = webUUID,
cost = expensiveRemoteCost,
name = Git.repoDescribe r,
@@ -50,7 +54,9 @@ gen r _ _ gc =
hasKey = checkKey,
hasKeyCheap = False,
whereisKey = Just getUrls,
- config = M.empty,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
+ config = c,
gitconfig = gc,
localpath = Nothing,
repo = r,
@@ -67,7 +73,18 @@ downloadKey key _file dest _p = get =<< getUrls key
return False
get urls = do
showOutput -- make way for download progress bar
- downloadUrl urls dest
+ untilTrue urls $ \u -> do
+ let (u', downloader) = getDownloader u
+ case downloader of
+ QuviDownloader -> do
+#ifdef WITH_QUVI
+ flip downloadUrl dest
+ =<< withQuviOptions Quvi.queryLinks [Quvi.httponly, Quvi.quiet] u'
+#else
+ warning "quvi support needed for this url"
+ return False
+#endif
+ DefaultDownloader -> downloadUrl [u'] dest
downloadKeyCheap :: Key -> FilePath -> Annex Bool
downloadKeyCheap _ _ = return False
@@ -87,9 +104,25 @@ checkKey key = do
us <- getUrls key
if null us
then return $ Right False
- else return . Right =<< checkKey' key us
-checkKey' :: Key -> [URLString] -> Annex Bool
-checkKey' key us = untilTrue us $ \u -> do
- showAction $ "checking " ++ u
- headers <- getHttpHeaders
- liftIO $ Url.check u headers (keySize key)
+ else return =<< checkKey' key us
+checkKey' :: Key -> [URLString] -> Annex (Either String Bool)
+checkKey' key us = firsthit us (Right False) $ \u -> do
+ let (u', downloader) = getDownloader u
+ showAction $ "checking " ++ u'
+ case downloader of
+ QuviDownloader ->
+#ifdef WITH_QUVI
+ Right <$> withQuviOptions Quvi.check [Quvi.httponly, Quvi.quiet] u'
+#else
+ return $ Left "quvi support needed for this url"
+#endif
+ DefaultDownloader -> do
+ headers <- getHttpHeaders
+ Right <$> Url.withUserAgent (Url.checkBoth u' headers $ keySize key)
+ where
+ firsthit [] miss _ = return miss
+ firsthit (u:rest) _ a = do
+ r <- a u
+ case r of
+ Right _ -> return r
+ Left _ -> firsthit rest r a
diff --git a/Remote/WebDAV.hs b/Remote/WebDAV.hs
index 52fc32b3a..738dbde3f 100644
--- a/Remote/WebDAV.hs
+++ b/Remote/WebDAV.hs
@@ -32,6 +32,7 @@ import Crypto
import Creds
import Utility.Metered
import Annex.Content
+import Annex.UUID
type DavUrl = String
type DavUser = B8.ByteString
@@ -45,10 +46,10 @@ remote = RemoteType {
setup = webdavSetup
}
-gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex Remote
+gen :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> Annex (Maybe Remote)
gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
where
- new cst = encryptableRemote c
+ new cst = Just $ encryptableRemote c
(storeEncrypted this)
(retrieveEncrypted this)
this
@@ -64,6 +65,8 @@ gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
hasKey = checkPresent this,
hasKeyCheap = False,
whereisKey = Nothing,
+ remoteFsck = Nothing,
+ repairRepo = Nothing,
config = c,
repo = r,
gitconfig = gc,
@@ -73,15 +76,17 @@ gen r u c gc = new <$> remoteCost gc expensiveRemoteCost
remotetype = remote
}
-webdavSetup :: UUID -> RemoteConfig -> Annex RemoteConfig
-webdavSetup u c = do
+webdavSetup :: Maybe UUID -> RemoteConfig -> Annex (RemoteConfig, UUID)
+webdavSetup mu c = do
+ u <- maybe (liftIO genUUID) return mu
let url = fromMaybe (error "Specify url=") $
M.lookup "url" c
c' <- encryptionSetup c
creds <- getCreds c' u
testDav url creds
gitConfigSpecialRemote u c' "webdav" "true"
- setRemoteCredPair c' (davCreds u)
+ c'' <- setRemoteCredPair c' (davCreds u)
+ return (c'', u)
store :: Remote -> Key -> AssociatedFile -> MeterUpdate -> Annex Bool
store r k _f p = metered (Just p) k $ \meterupdate ->
@@ -94,7 +99,7 @@ storeEncrypted :: Remote -> (Cipher, Key) -> Key -> MeterUpdate -> Annex Bool
storeEncrypted r (cipher, enck) k p = metered (Just p) k $ \meterupdate ->
davAction r False $ \(baseurl, user, pass) ->
sendAnnex k (void $ remove r enck) $ \src ->
- liftIO $ encrypt (getGpgOpts r) cipher
+ liftIO $ encrypt (getGpgEncParams r) cipher
(streamMeteredFile src meterupdate) $
readBytes $ storeHelper r enck baseurl user pass
@@ -178,9 +183,9 @@ checkPresent r k = davAction r noconn go
- or perhaps this was an intermittent error. -}
onerr url = do
v <- davUrlExists url user pass
- if v == Right True
- then return $ Left $ "failed to read " ++ url
- else return v
+ return $ if v == Right True
+ then Left $ "failed to read " ++ url
+ else v
withStoredFiles
:: Remote
@@ -194,8 +199,14 @@ withStoredFiles
withStoredFiles r k baseurl user pass onerr a
| isJust $ chunkSize $ config r = do
let chunkcount = keyurl ++ chunkCount
- maybe (onerr chunkcount) (a . listChunks keyurl . L8.toString)
- =<< davGetUrlContent chunkcount user pass
+ v <- davGetUrlContent chunkcount user pass
+ case v of
+ Just s -> a $ listChunks keyurl $ L8.toString s
+ Nothing -> do
+ chunks <- probeChunks keyurl $ \u -> (== Right True) <$> davUrlExists u user pass
+ if null chunks
+ then onerr chunkcount
+ else a chunks
| otherwise = a [keyurl]
where
keyurl = davLocation baseurl k ++ keyFile k
diff --git a/Seek.hs b/Seek.hs
index 817687b45..7f74f6728 100644
--- a/Seek.hs
+++ b/Seek.hs
@@ -26,6 +26,7 @@ import qualified Option
import Config
import Logs.Location
import Logs.Unused
+import Annex.CatFile
seekHelper :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> [FilePath] -> Annex [FilePath]
seekHelper a params = do
@@ -59,7 +60,8 @@ withPathContents :: ((FilePath, FilePath) -> CommandStart) -> CommandSeek
withPathContents a params = map a . concat <$> liftIO (mapM get params)
where
get p = ifM (isDirectory <$> getFileStatus p)
- ( map (\f -> (f, makeRelative p f)) <$> dirContentsRecursive p
+ ( map (\f -> (f, makeRelative (parentDir p) f))
+ <$> dirContentsRecursiveSkipping (".git" `isSuffixOf`) p
, return [(p, takeFileName p)]
)
@@ -86,12 +88,17 @@ withFilesUnlocked = withFilesUnlocked' LsFiles.typeChanged
withFilesUnlockedToBeCommitted :: (FilePath -> CommandStart) -> CommandSeek
withFilesUnlockedToBeCommitted = withFilesUnlocked' LsFiles.typeChangedStaged
+{- Unlocked files have changed type from a symlink to a regular file.
+ -
+ - Furthermore, unlocked files used to be a git-annex symlink,
+ - not some other sort of symlink.
+ -}
withFilesUnlocked' :: ([FilePath] -> Git.Repo -> IO ([FilePath], IO Bool)) -> (FilePath -> CommandStart) -> CommandSeek
-withFilesUnlocked' typechanged a params = do
- -- unlocked files have changed type from a symlink to a regular file
- typechangedfiles <- seekHelper typechanged params
- let unlockedfiles = liftIO $ filterM notSymlink typechangedfiles
- prepFiltered a unlockedfiles
+withFilesUnlocked' typechanged a params = prepFiltered a unlockedfiles
+ where
+ check f = liftIO (notSymlink f) <&&>
+ (isJust <$> catKeyFile f <||> isJust <$> catKeyFileHEAD f)
+ unlockedfiles = filterM check =<< seekHelper typechanged params
{- Finds files that may be modified. -}
withFilesMaybeModified :: (FilePath -> CommandStart) -> CommandSeek
diff --git a/Types/Crypto.hs b/Types/Crypto.hs
index e97d02ba8..1a9a7774a 100644
--- a/Types/Crypto.hs
+++ b/Types/Crypto.hs
@@ -8,6 +8,7 @@
module Types.Crypto (
Cipher(..),
StorableCipher(..),
+ EncryptedCipherVariant(..),
KeyIds(..),
Mac(..),
readMac,
@@ -22,9 +23,12 @@ import Data.Digest.Pure.SHA
import Utility.Gpg (KeyIds(..))
-- XXX ideally, this would be a locked memory region
-newtype Cipher = Cipher String
+data Cipher = Cipher String | MacOnlyCipher String
-data StorableCipher = EncryptedCipher String KeyIds | SharedCipher String
+data StorableCipher = EncryptedCipher String EncryptedCipherVariant KeyIds
+ | SharedCipher String
+ deriving (Ord, Eq)
+data EncryptedCipherVariant = Hybrid | PubKey
deriving (Ord, Eq)
{- File names are (client-side) MAC'ed on special remotes.
@@ -66,4 +70,4 @@ calcMac mac = case mac of
HmacSha384 -> showDigest $* hmacSha384
HmacSha512 -> showDigest $* hmacSha512
where
- ($*) g f x y = g $ f x y
+ ($*) g f x y = g $ f x y
diff --git a/Types/GitConfig.hs b/Types/GitConfig.hs
index d5d234ca9..b573a9a25 100644
--- a/Types/GitConfig.hs
+++ b/Types/GitConfig.hs
@@ -37,10 +37,13 @@ data GitConfig = GitConfig
, annexAutoCommit :: Bool
, annexDebug :: Bool
, annexWebOptions :: [String]
+ , annexQuviOptions :: [String]
, annexWebDownloadCommand :: Maybe String
, annexCrippledFileSystem :: Bool
, annexLargeFiles :: Maybe String
+ , annexFsckNudge :: Bool
, coreSymlinks :: Bool
+ , gcryptId :: Maybe String
}
extractGitConfig :: Git.Repo -> GitConfig
@@ -62,10 +65,13 @@ extractGitConfig r = GitConfig
, annexAutoCommit = getbool (annex "autocommit") True
, annexDebug = getbool (annex "debug") False
, annexWebOptions = getwords (annex "web-options")
+ , annexQuviOptions = getwords (annex "quvi-options")
, annexWebDownloadCommand = getmaybe (annex "web-download-command")
, annexCrippledFileSystem = getbool (annex "crippledfilesystem") False
, annexLargeFiles = getmaybe (annex "largefiles")
+ , annexFsckNudge = getbool (annex "fscknudge") True
, coreSymlinks = getbool "core.symlinks" True
+ , gcryptId = getmaybe "core.gcrypt-id"
}
where
get k def = fromMaybe def $ getmayberead k
@@ -102,6 +108,7 @@ data RemoteGitConfig = RemoteGitConfig
, remoteAnnexBupRepo :: Maybe String
, remoteAnnexBupSplitOptions :: [String]
, remoteAnnexDirectory :: Maybe FilePath
+ , remoteAnnexGCrypt :: Maybe String
, remoteAnnexHookType :: Maybe String
{- A regular git remote's git repository config. -}
, remoteGitConfig :: Maybe GitConfig
@@ -125,6 +132,7 @@ extractRemoteGitConfig r remotename = RemoteGitConfig
, remoteAnnexBupRepo = getmaybe "buprepo"
, remoteAnnexBupSplitOptions = getoptions "bup-split-options"
, remoteAnnexDirectory = notempty $ getmaybe "directory"
+ , remoteAnnexGCrypt = notempty $ getmaybe "gcrypt"
, remoteAnnexHookType = notempty $ getmaybe "hooktype"
, remoteGitConfig = Nothing
}
diff --git a/Types/Key.hs b/Types/Key.hs
index a0c6d83bc..598d5ed20 100644
--- a/Types/Key.hs
+++ b/Types/Key.hs
@@ -14,7 +14,8 @@ module Types.Key (
key2file,
file2key,
- prop_idempotent_key_encode
+ prop_idempotent_key_encode,
+ prop_idempotent_key_decode
) where
import System.Posix.Types
@@ -59,7 +60,9 @@ key2file Key { keyBackendName = b, keySize = s, keyMtime = m, keyName = n } =
_ ?: _ = ""
file2key :: FilePath -> Maybe Key
-file2key s = if key == Just stubKey then Nothing else key
+file2key s
+ | key == Just stubKey || (keyName <$> key) == Just "" || (keyBackendName <$> key) == Just "" = Nothing
+ | otherwise = key
where
key = startbackend stubKey s
@@ -81,10 +84,13 @@ file2key s = if key == Just stubKey then Nothing else key
instance Arbitrary Key where
arbitrary = Key
- <$> arbitrary
+ <$> (listOf1 $ elements $ ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "-_\r\n \t")
<*> (listOf1 $ elements ['A'..'Z']) -- BACKEND
<*> ((abs <$>) <$> arbitrary) -- size cannot be negative
<*> arbitrary
prop_idempotent_key_encode :: Key -> Bool
prop_idempotent_key_encode k = Just k == (file2key . key2file) k
+
+prop_idempotent_key_decode :: FilePath -> Bool
+prop_idempotent_key_decode f = maybe True (\k -> key2file k == f) (file2key f)
diff --git a/Types/Limit.hs b/Types/Limit.hs
new file mode 100644
index 000000000..4436f6953
--- /dev/null
+++ b/Types/Limit.hs
@@ -0,0 +1,20 @@
+{- 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 -> FileInfo -> Annex Bool
diff --git a/Types/Remote.hs b/Types/Remote.hs
index 8492be06d..8a94dcc05 100644
--- a/Types/Remote.hs
+++ b/Types/Remote.hs
@@ -18,6 +18,8 @@ import Types.UUID
import Types.GitConfig
import Config.Cost
import Utility.Metered
+import Git.Types
+import Utility.SafeCommand
type RemoteConfigKey = String
type RemoteConfig = M.Map RemoteConfigKey String
@@ -29,9 +31,9 @@ data RemoteTypeA a = RemoteType {
-- enumerates remotes of this type
enumerate :: a [Git.Repo],
-- generates a remote of this type
- generate :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> a (RemoteA a),
+ generate :: Git.Repo -> UUID -> RemoteConfig -> RemoteGitConfig -> a (Maybe (RemoteA a)),
-- initializes or changes a remote
- setup :: UUID -> RemoteConfig -> a RemoteConfig
+ setup :: Maybe UUID -> RemoteConfig -> a (RemoteConfig, UUID)
}
instance Eq (RemoteTypeA a) where
@@ -42,7 +44,7 @@ data RemoteA a = Remote {
-- each Remote has a unique uuid
uuid :: UUID,
-- each Remote has a human visible name
- name :: String,
+ name :: RemoteName,
-- Remotes have a use cost; higher is more expensive
cost :: Cost,
-- Transfers a key to the remote.
@@ -63,6 +65,12 @@ data RemoteA a = Remote {
hasKeyCheap :: Bool,
-- Some remotes can provide additional details for whereis.
whereisKey :: Maybe (Key -> a [String]),
+ -- Some remotes can run a fsck operation on the remote,
+ -- without transferring all the data to the local repo
+ -- The parameters are passed to the fsck command on the remote.
+ remoteFsck :: Maybe ([CommandParam] -> a (IO Bool)),
+ -- Runs an action to repair the remote's git repository.
+ repairRepo :: Maybe (a Bool -> a (IO Bool)),
-- a Remote has a persistent configuration store
config :: RemoteConfig,
-- git repo for the Remote
diff --git a/Types/ScheduledActivity.hs b/Types/ScheduledActivity.hs
new file mode 100644
index 000000000..b683409ce
--- /dev/null
+++ b/Types/ScheduledActivity.hs
@@ -0,0 +1,69 @@
+{- git-annex scheduled activities
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Types.ScheduledActivity where
+
+import Common
+import Utility.Scheduled
+import Utility.HumanTime
+import Types.UUID
+
+import Data.Either
+
+data ScheduledActivity
+ = ScheduledSelfFsck Schedule Duration
+ | ScheduledRemoteFsck UUID Schedule Duration
+ deriving (Eq, Read, Show, Ord)
+
+{- Activities that run on a remote, within a time window, so
+ - should be run when the remote gets connected. -}
+connectActivityUUID :: ScheduledActivity -> Maybe UUID
+connectActivityUUID (ScheduledRemoteFsck u (Schedule _ AnyTime) _) = Just u
+connectActivityUUID _ = Nothing
+
+getSchedule :: ScheduledActivity -> Schedule
+getSchedule (ScheduledSelfFsck s _) = s
+getSchedule (ScheduledRemoteFsck _ s _) = s
+
+getDuration :: ScheduledActivity -> Duration
+getDuration (ScheduledSelfFsck _ d) = d
+getDuration (ScheduledRemoteFsck _ _ d) = d
+
+fromScheduledActivity :: ScheduledActivity -> String
+fromScheduledActivity (ScheduledSelfFsck s d) = unwords
+ [ "fsck self", fromDuration d, fromSchedule s ]
+fromScheduledActivity (ScheduledRemoteFsck u s d) = unwords
+ [ "fsck", fromUUID u, fromDuration d, fromSchedule s ]
+
+toScheduledActivity :: String -> Maybe ScheduledActivity
+toScheduledActivity = eitherToMaybe . parseScheduledActivity
+
+parseScheduledActivity :: String -> Either String ScheduledActivity
+parseScheduledActivity s = case words s of
+ ("fsck":"self":d:rest) -> qualified $ ScheduledSelfFsck
+ <$> parseSchedule (unwords rest)
+ <*> getduration d
+ ("fsck":u:d:rest) -> qualified $ ScheduledRemoteFsck
+ <$> pure (toUUID u)
+ <*> parseSchedule (unwords rest)
+ <*> getduration d
+ _ -> qualified $ Left "unknown activity"
+ where
+ qualified (Left e) = Left $ e ++ " in \"" ++ s ++ "\""
+ qualified v = v
+ getduration d = maybe (Left $ "failed to parse duration \""++d++"\"") Right (parseDuration d)
+
+fromScheduledActivities :: [ScheduledActivity] -> String
+fromScheduledActivities = intercalate "; " . map fromScheduledActivity
+
+parseScheduledActivities :: String -> Either String [ScheduledActivity]
+parseScheduledActivities s
+ | null bad = Right good
+ | otherwise = Left $ intercalate "; " bad
+ where
+ (bad, good) = partitionEithers $
+ map parseScheduledActivity $ split "; " s
diff --git a/Types/StandardGroups.hs b/Types/StandardGroups.hs
index 30b882282..2d977a357 100644
--- a/Types/StandardGroups.hs
+++ b/Types/StandardGroups.hs
@@ -77,7 +77,7 @@ preferredContent ClientGroup = lastResort $
preferredContent TransferGroup = lastResort $
"not (inallgroup=client and copies=client:2) and (" ++ preferredContent ClientGroup ++ ")"
preferredContent BackupGroup = "include=*"
-preferredContent IncrementalBackupGroup = lastResort $
+preferredContent IncrementalBackupGroup = lastResort
"include=* and (not copies=incrementalbackup:1)"
preferredContent SmallArchiveGroup = lastResort $
"(include=*/archive/* or include=archive/*) and (" ++ preferredContent FullArchiveGroup ++ ")"
diff --git a/Types/TrustLevel.hs b/Types/TrustLevel.hs
index 27325cd2b..a72dbb8c6 100644
--- a/Types/TrustLevel.hs
+++ b/Types/TrustLevel.hs
@@ -17,6 +17,8 @@ import qualified Data.Map as M
import Types.UUID
+-- This order may seem backwards, but we generally want to list dead
+-- remotes last and trusted ones first.
data TrustLevel = Trusted | SemiTrusted | UnTrusted | DeadTrusted
deriving (Eq, Enum, Ord, Bounded)
diff --git a/Upgrade.hs b/Upgrade.hs
index f0166bf8e..59cca3fe4 100644
--- a/Upgrade.hs
+++ b/Upgrade.hs
@@ -16,9 +16,21 @@ import qualified Upgrade.V0
import qualified Upgrade.V1
#endif
import qualified Upgrade.V2
+import qualified Upgrade.V4
-upgrade :: Annex Bool
-upgrade = go =<< getVersion
+checkUpgrade :: Version -> Annex ()
+checkUpgrade v
+ | v `elem` supportedVersions = noop
+ | v `elem` autoUpgradeableVersions = unlessM (upgrade True) $
+ err "Automatic upgrade failed!"
+ | v `elem` upgradableVersions = err "Upgrade this repository: git-annex upgrade"
+ | otherwise = err "Upgrade git-annex."
+ where
+ err msg = error $ "Repository version " ++ v ++
+ " is not supported. " ++ msg
+
+upgrade :: Bool -> Annex Bool
+upgrade automatic = go =<< getVersion
where
#ifndef mingw32_HOST_OS
go (Just "0") = Upgrade.V0.upgrade
@@ -28,4 +40,5 @@ upgrade = go =<< getVersion
go (Just "1") = error "upgrade from v1 on Windows not supported"
#endif
go (Just "2") = Upgrade.V2.upgrade
+ go (Just "4") = Upgrade.V4.upgrade automatic
go _ = return True
diff --git a/Upgrade/V1.hs b/Upgrade/V1.hs
index 9793f04e8..688f4c571 100644
--- a/Upgrade/V1.hs
+++ b/Upgrade/V1.hs
@@ -107,7 +107,7 @@ moveLocationLogs = do
dir <- fromRepo Upgrade.V2.gitStateDir
ifM (liftIO $ doesDirectoryExist dir)
( mapMaybe oldlog2key
- <$> (liftIO $ getDirectoryContents dir)
+ <$> liftIO (getDirectoryContents dir)
, return []
)
move (l, k) = do
diff --git a/Upgrade/V2.hs b/Upgrade/V2.hs
index b5de6c8c0..42419b8ab 100644
--- a/Upgrade/V2.hs
+++ b/Upgrade/V2.hs
@@ -12,9 +12,9 @@ import qualified Git
import qualified Git.Command
import qualified Git.Ref
import qualified Annex.Branch
-import Logs.Location
import Annex.Content
import Utility.Tmp
+import Logs
olddir :: Git.Repo -> FilePath
olddir g
@@ -47,7 +47,7 @@ upgrade = do
e <- liftIO $ doesDirectoryExist old
when e $ do
- mapM_ (\(k, f) -> inject f $ logFile k) =<< locationLogs
+ mapM_ (\(k, f) -> inject f $ locationLogFile k) =<< locationLogs
mapM_ (\f -> inject f f) =<< logFiles old
saveState False
@@ -73,7 +73,7 @@ locationLogs = do
where
tryDirContents d = catchDefaultIO [] $ dirContents d
islogfile f = maybe Nothing (\k -> Just (k, f)) $
- logFileKey $ takeFileName f
+ locationLogFileKey f
inject :: FilePath -> FilePath -> Annex ()
inject source dest = do
diff --git a/Upgrade/V4.hs b/Upgrade/V4.hs
new file mode 100644
index 000000000..147ace559
--- /dev/null
+++ b/Upgrade/V4.hs
@@ -0,0 +1,23 @@
+{- git-annex v4 -> v5 uppgrade support
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Upgrade.V4 where
+
+import Common.Annex
+import Config
+import Annex.Direct
+
+{- Direct mode only upgrade. -}
+upgrade :: Bool -> Annex Bool
+upgrade automatic = ifM isDirect
+ ( do
+ unless automatic $
+ showAction "v4 to v5"
+ setDirect True
+ return True
+ , return False
+ )
diff --git a/Utility/Base64.hs b/Utility/Base64.hs
index ec660108a..0c6c8677a 100644
--- a/Utility/Base64.hs
+++ b/Utility/Base64.hs
@@ -7,7 +7,7 @@
module Utility.Base64 (toB64, fromB64Maybe, fromB64) where
-import Codec.Binary.Base64
+import "dataenc" Codec.Binary.Base64
import Data.Bits.Utils
import Control.Applicative
import Data.Maybe
diff --git a/Utility/Batch.hs b/Utility/Batch.hs
index c3c34bf27..035a2eb04 100644
--- a/Utility/Batch.hs
+++ b/Utility/Batch.hs
@@ -9,10 +9,17 @@
module Utility.Batch where
+import Common
+#ifndef mingw32_HOST_OS
+import qualified Build.SysConfig
+#endif
+
#if defined(linux_HOST_OS) || defined(__ANDROID__)
import Control.Concurrent.Async
import System.Posix.Process
#endif
+import qualified Control.Exception as E
+import System.Process (env)
{- Runs an operation, at batch priority.
-
@@ -38,3 +45,47 @@ batch a = a
maxNice :: Int
maxNice = 19
+
+{- Converts a command to run niced. -}
+toBatchCommand :: (String, [CommandParam]) -> (String, [CommandParam])
+toBatchCommand (command, params) = (command', params')
+ where
+#ifndef mingw32_HOST_OS
+ commandline = unwords $ map shellEscape $ command : toCommand params
+ nicedcommand
+ | Build.SysConfig.nice = "nice " ++ commandline
+ | otherwise = commandline
+ command' = "sh"
+ params' =
+ [ Param "-c"
+ , Param $ "exec " ++ nicedcommand
+ ]
+#else
+ command' = command
+ params' = params
+#endif
+
+{- Runs a command in a way that's suitable for batch jobs that can be
+ - interrupted.
+ -
+ - The command is run niced. If the calling thread receives an async
+ - exception, it sends the command a SIGTERM, and after the command
+ - finishes shuttting down, it re-raises the async exception. -}
+batchCommand :: String -> [CommandParam] -> IO Bool
+batchCommand command params = batchCommandEnv command params Nothing
+
+batchCommandEnv :: String -> [CommandParam] -> Maybe [(String, String)] -> IO Bool
+batchCommandEnv command params environ = do
+ (_, _, _, pid) <- createProcess $ p { env = environ }
+ r <- E.try (waitForProcess pid) :: IO (Either E.SomeException ExitCode)
+ case r of
+ Right ExitSuccess -> return True
+ Right _ -> return False
+ Left asyncexception -> do
+ terminateProcess pid
+ void $ waitForProcess pid
+ E.throwIO asyncexception
+ where
+ (command', params') = toBatchCommand (command, params)
+ p = proc command' $ toCommand params'
+
diff --git a/Utility/Daemon.hs b/Utility/Daemon.hs
index 2f942769a..12beb235a 100644
--- a/Utility/Daemon.hs
+++ b/Utility/Daemon.hs
@@ -16,6 +16,7 @@ import Utility.LogFile
#ifndef mingw32_HOST_OS
import System.Posix
+import Control.Concurrent.Async
#else
import System.PosixCompat
#endif
@@ -46,7 +47,9 @@ daemonize logfd pidfile changedirectory a = do
nullfd <- openFd "/dev/null" ReadOnly Nothing defaultFileFlags
redir nullfd stdInput
redirLog logfd
- a
+ {- forkProcess masks async exceptions; unmask them inside
+ - the action. -}
+ wait =<< asyncWithUnmask (\unmask -> unmask a)
out
out = exitImmediately ExitSuccess
#else
diff --git a/Utility/Data.hs b/Utility/Data.hs
new file mode 100644
index 000000000..359258296
--- /dev/null
+++ b/Utility/Data.hs
@@ -0,0 +1,17 @@
+{- utilities for simple data types
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Utility.Data where
+
+{- First item in the list that is not Nothing. -}
+firstJust :: Eq a => [Maybe a] -> Maybe a
+firstJust ms = case dropWhile (== Nothing) ms of
+ [] -> Nothing
+ (md:_) -> md
+
+eitherToMaybe :: Either a b -> Maybe b
+eitherToMaybe = either (const Nothing) Just
diff --git a/Utility/DirWatcher.hs b/Utility/DirWatcher.hs
index d28381fae..5231286fc 100644
--- a/Utility/DirWatcher.hs
+++ b/Utility/DirWatcher.hs
@@ -1,10 +1,10 @@
{- generic directory watching interface
-
- - Uses inotify, or kqueue, or fsevents to watch a directory
+ - Uses inotify, or kqueue, or fsevents, or win32-notify to watch a directory
- (and subdirectories) for changes, and runs hooks for different
- sorts of events as they occur.
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
@@ -27,11 +27,15 @@ import Control.Concurrent
import qualified Utility.FSEvents as FSEvents
import qualified System.OSX.FSEvents as FSEvents
#endif
+#if WITH_WIN32NOTIFY
+import qualified Utility.Win32Notify as Win32Notify
+import qualified System.Win32.Notify as Win32Notify
+#endif
type Pruner = FilePath -> Bool
canWatch :: Bool
-#if (WITH_INOTIFY || WITH_KQUEUE || WITH_FSEVENTS)
+#if (WITH_INOTIFY || WITH_KQUEUE || WITH_FSEVENTS || WITH_WIN32NOTIFY)
canWatch = True
#else
#if defined linux_HOST_OS
@@ -47,7 +51,7 @@ canWatch = False
- OTOH, with kqueue, often only one event is received, indicating the most
- recent state of the file. -}
eventsCoalesce :: Bool
-#if WITH_INOTIFY
+#if (WITH_INOTIFY || WITH_WIN32NOTIFY)
eventsCoalesce = False
#else
#if (WITH_KQUEUE || WITH_FSEVENTS)
@@ -68,7 +72,7 @@ eventsCoalesce = undefined
- still being written to, and then no add event will be received once the
- writer closes it. -}
closingTracked :: Bool
-#if (WITH_INOTIFY || WITH_FSEVENTS)
+#if (WITH_INOTIFY || WITH_FSEVENTS || WITH_WIN32NOTIFY)
closingTracked = True
#else
#if WITH_KQUEUE
@@ -83,7 +87,7 @@ closingTracked = undefined
- Fsevents generates events when an existing file is reopened and rewritten,
- but not necessarily when it's opened once and modified repeatedly. -}
modifyTracked :: Bool
-#if (WITH_INOTIFY || WITH_FSEVENTS)
+#if (WITH_INOTIFY || WITH_FSEVENTS || WITH_WIN32NOTIFY)
modifyTracked = True
#else
#if WITH_KQUEUE
@@ -119,27 +123,35 @@ watchDir :: FilePath -> Pruner -> WatchHooks -> (IO FSEvents.EventStream -> IO F
watchDir dir prune hooks runstartup =
runstartup $ FSEvents.watchDir dir prune hooks
#else
+#if WITH_WIN32NOTIFY
+type DirWatcherHandle = Win32Notify.WatchManager
+watchDir :: FilePath -> Pruner -> WatchHooks -> (IO Win32Notify.WatchManager -> IO Win32Notify.WatchManager) -> IO DirWatcherHandle
+watchDir dir prune hooks runstartup =
+ runstartup $ Win32Notify.watchDir dir prune hooks
+#else
type DirWatcherHandle = ()
watchDir :: FilePath -> Pruner -> WatchHooks -> (IO () -> IO ()) -> IO DirWatcherHandle
watchDir = undefined
#endif
#endif
#endif
+#endif
-#if WITH_INOTIFY
stopWatchDir :: DirWatcherHandle -> IO ()
+#if WITH_INOTIFY
stopWatchDir = INotify.killINotify
#else
#if WITH_KQUEUE
-stopWatchDir :: DirWatcherHandle -> IO ()
stopWatchDir = killThread
#else
#if WITH_FSEVENTS
-stopWatchDir :: DirWatcherHandle -> IO ()
stopWatchDir = FSEvents.eventStreamDestroy
#else
-stopWatchDir :: DirWatcherHandle -> IO ()
+#if WITH_WIN32NOTIFY
+stopWatchDir = Win32Notify.killWatchManager
+#else
stopWatchDir = undefined
#endif
#endif
#endif
+#endif
diff --git a/Utility/Directory.hs b/Utility/Directory.hs
index 13e6168cb..4918d20be 100644
--- a/Utility/Directory.hs
+++ b/Utility/Directory.hs
@@ -38,15 +38,20 @@ dirContents d = map (d </>) . filter (not . dirCruft) <$> getDirectoryContents d
- and lazily. If the directory does not exist, no exception is thrown,
- instead, [] is returned. -}
dirContentsRecursive :: FilePath -> IO [FilePath]
-dirContentsRecursive topdir = dirContentsRecursive' [topdir]
+dirContentsRecursive topdir = dirContentsRecursiveSkipping (const False) topdir
-dirContentsRecursive' :: [FilePath] -> IO [FilePath]
-dirContentsRecursive' [] = return []
-dirContentsRecursive' (dir:dirs) = unsafeInterleaveIO $ do
- (files, dirs') <- collect [] [] =<< catchDefaultIO [] (dirContents dir)
- files' <- dirContentsRecursive' (dirs' ++ dirs)
- return (files ++ files')
+{- Skips directories whose basenames match the skipdir. -}
+dirContentsRecursiveSkipping :: (FilePath -> Bool) -> FilePath -> IO [FilePath]
+dirContentsRecursiveSkipping skipdir topdir = go [topdir]
where
+ go [] = return []
+ go (dir:dirs)
+ | skipdir (takeFileName dir) = go dirs
+ | otherwise = unsafeInterleaveIO $ do
+ (files, dirs') <- collect [] []
+ =<< catchDefaultIO [] (dirContents dir)
+ files' <- go (dirs' ++ dirs)
+ return (files ++ files')
collect files dirs' [] = return (reverse files, reverse dirs')
collect files dirs' (entry:entries)
| dirCruft entry = collect files dirs' entries
diff --git a/Utility/Exception.hs b/Utility/Exception.hs
index 3835d741d..cf2c615c7 100644
--- a/Utility/Exception.hs
+++ b/Utility/Exception.hs
@@ -14,6 +14,7 @@ import qualified Control.Exception as E
import Control.Applicative
import Control.Monad
import System.IO.Error (isDoesNotExistError)
+import Utility.Data
{- Catches IO errors and returns a Bool -}
catchBoolIO :: IO Bool -> IO Bool
@@ -54,5 +55,5 @@ tryNonAsync a = (Right <$> a) `catchNonAsync` (return . Left)
{- Catches only DoesNotExist exceptions, and lets all others through. -}
tryWhenExists :: IO a -> IO (Maybe a)
-tryWhenExists a = either (const Nothing) Just <$>
+tryWhenExists a = eitherToMaybe <$>
tryJust (guard . isDoesNotExistError) a
diff --git a/Utility/ExternalSHA.hs b/Utility/ExternalSHA.hs
index 21241d302..adbde795a 100644
--- a/Utility/ExternalSHA.hs
+++ b/Utility/ExternalSHA.hs
@@ -1,6 +1,7 @@
{- Calculating a SHA checksum with an external command.
-
- - This is often faster than using Haskell libraries.
+ - This is typically a bit faster than using Haskell libraries,
+ - by around 1% to 10%. Worth it for really big files.
-
- Copyright 2011-2013 Joey Hess <joey@kitenet.net>
-
diff --git a/Utility/Format.hs b/Utility/Format.hs
index 97a966ac1..e7a27515e 100644
--- a/Utility/Format.hs
+++ b/Utility/Format.hs
@@ -15,7 +15,7 @@ module Utility.Format (
) where
import Text.Printf (printf)
-import Data.Char (isAlphaNum, isOctDigit, isSpace, chr, ord)
+import Data.Char (isAlphaNum, isOctDigit, isHexDigit, isSpace, chr, ord)
import Data.Maybe (fromMaybe)
import Data.Word (Word8)
import Data.List (isPrefixOf)
@@ -101,7 +101,7 @@ empty (Const "") = True
empty _ = False
{- Decodes a C-style encoding, where \n is a newline, \NNN is an octal
- - encoded character, etc.
+ - encoded character, and \xNN is a hex encoded character.
-}
decode_c :: FormatString -> FormatString
decode_c [] = []
@@ -114,7 +114,12 @@ decode_c s = unescape ("", s)
where
pair = span (/= e) v
isescape x = x == e
- -- \NNN is an octal encoded character
+ handle (x:'x':n1:n2:rest)
+ | isescape x && allhex = (fromhex, rest)
+ where
+ allhex = isHexDigit n1 && isHexDigit n2
+ fromhex = [chr $ readhex [n1, n2]]
+ readhex h = Prelude.read $ "0x" ++ h :: Int
handle (x:n1:n2:n3:rest)
| isescape x && alloctal = (fromoctal, rest)
where
diff --git a/Utility/Gpg.hs b/Utility/Gpg.hs
index 81180148e..a2baa74dc 100644
--- a/Utility/Gpg.hs
+++ b/Utility/Gpg.hs
@@ -11,6 +11,7 @@ module Utility.Gpg where
import Control.Applicative
import Control.Concurrent
+import qualified Data.Map as M
import Common
import qualified Build.SysConfig as SysConfig
@@ -23,8 +24,11 @@ import Utility.Env
#else
import Utility.Tmp
#endif
+import Utility.Format (decode_c)
-newtype KeyIds = KeyIds [String]
+type KeyId = String
+
+newtype KeyIds = KeyIds { keyIds :: [KeyId] }
deriving (Ord, Eq)
{- If a specific gpg command was found at configure time, use it.
@@ -32,6 +36,10 @@ newtype KeyIds = KeyIds [String]
gpgcmd :: FilePath
gpgcmd = fromMaybe "gpg" SysConfig.gpg
+-- Generate an argument list to asymetrically encrypt to the given recipients.
+pkEncTo :: [String] -> [CommandParam]
+pkEncTo = concatMap (\r -> [Param "--recipient", Param r])
+
stdParams :: [CommandParam] -> IO [String]
stdParams params = do
#ifndef mingw32_HOST_OS
@@ -48,9 +56,23 @@ stdParams params = do
return $ defaults ++ toCommand params
#endif
where
- -- be quiet, even about checking the trustdb
+ -- Be quiet, even about checking the trustdb.
defaults = ["--quiet", "--trust-model", "always"]
+{- Usual options for symmetric / public-key encryption. -}
+stdEncryptionParams :: Bool -> [CommandParam]
+stdEncryptionParams symmetric =
+ [ enc symmetric
+ , Param "--force-mdc"
+ , Param "--no-textmode"
+ ]
+ where
+ enc True = Param "--symmetric"
+ -- Force gpg to only encrypt to the specified recipients, not
+ -- configured defaults. Recipients are assumed to be specified in
+ -- elsewhere.
+ enc False = Params "--encrypt --no-encrypt-to --no-default-recipient"
+
{- Runs gpg with some params and returns its stdout, strictly. -}
readStrict :: [CommandParam] -> IO String
readStrict params = do
@@ -71,10 +93,11 @@ pipeStrict params input = do
hClose to
hGetContentsStrict from
-{- Runs gpg with some parameters. First sends it a passphrase via
- - --passphrase-fd. Then runs a feeder action that is passed a handle and
- - should write to it all the data to input to gpg. Finally, runs
- - a reader action that is passed a handle to gpg's output.
+{- Runs gpg with some parameters. First sends it a passphrase (unless it
+ - is empty) via '--passphrase-fd'. Then runs a feeder action that is
+ - passed a handle and should write to it all the data to input to gpg.
+ - Finally, runs a reader action that is passed a handle to gpg's
+ - output.
-
- Runs gpg in batch mode; this is necessary to avoid gpg 2.x prompting for
- the passphrase.
@@ -92,20 +115,23 @@ feedRead params passphrase feeder reader = do
hClose toh
let Fd pfd = frompipe
let passphrasefd = [Param "--passphrase-fd", Param $ show pfd]
-
- params' <- stdParams $ [Param "--batch"] ++ passphrasefd ++ params
- closeFd frompipe `after` go params'
+ closeFd frompipe `after` go (passphrasefd ++ params)
#else
-- store the passphrase in a temp file for gpg
withTmpFile "gpg" $ \tmpfile h -> do
hPutStr h passphrase
hClose h
let passphrasefile = [Param "--passphrase-file", File tmpfile]
- params' <- stdParams $ [Param "--batch"] ++ passphrasefile ++ params
- go params'
+ go $ passphrasefile ++ params
#endif
where
- go params' = withBothHandles createProcessSuccess (proc gpgcmd params')
+ go params' = pipeLazy params' feeder reader
+
+{- Like feedRead, but without passphrase. -}
+pipeLazy :: [CommandParam] -> (Handle -> IO ()) -> (Handle -> IO a) -> IO a
+pipeLazy params feeder reader = do
+ params' <- stdParams $ Param "--batch" : params
+ withBothHandles createProcessSuccess (proc gpgcmd params')
$ \(to, from) -> do
void $ forkIO $ do
feeder to
@@ -116,17 +142,70 @@ feedRead params passphrase feeder reader = do
- a key id, or a name; See the section 'HOW TO SPECIFY A USER ID' of
- GnuPG's manpage.) -}
findPubKeys :: String -> IO KeyIds
-findPubKeys for = KeyIds . parse <$> readStrict params
+findPubKeys for = KeyIds . parse . lines <$> readStrict params
where
params = [Params "--with-colons --list-public-keys", Param for]
- parse = catMaybes . map (keyIdField . split ":") . lines
+ parse = catMaybes . map (keyIdField . split ":")
keyIdField ("pub":_:_:_:f:_) = Just f
keyIdField _ = Nothing
+type UserId = String
+
+{- All of the user's secret keys, with their UserIds.
+ - Note that the UserId may be empty. -}
+secretKeys :: IO (M.Map KeyId UserId)
+secretKeys = M.fromList . parse . lines <$> readStrict params
+ where
+ params = [Params "--with-colons --list-secret-keys --fixed-list-mode"]
+ parse = extract [] Nothing . map (split ":")
+ extract c (Just keyid) (("uid":_:_:_:_:_:_:_:_:userid:_):rest) =
+ extract ((keyid, decode_c userid):c) Nothing rest
+ extract c (Just keyid) rest =
+ extract ((keyid, ""):c) Nothing rest
+ extract c _ [] = c
+ extract c _ (("sec":_:_:_:keyid:_):rest) =
+ extract c (Just keyid) rest
+ extract c k (_:rest) =
+ extract c k rest
+
+type Passphrase = String
+type Size = Int
+data KeyType = Algo Int | DSA | RSA
+
+{- The maximum key size that gpg currently offers in its UI when
+ - making keys. -}
+maxRecommendedKeySize :: Size
+maxRecommendedKeySize = 4096
+
+{- Generates a secret key using the experimental batch mode.
+ - The key is added to the secret key ring.
+ - Can take a very long time, depending on system entropy levels.
+ -}
+genSecretKey :: KeyType -> Passphrase -> UserId -> Size -> IO ()
+genSecretKey keytype passphrase userid keysize =
+ withHandle StdinHandle createProcessSuccess (proc gpgcmd params) feeder
+ where
+ params = ["--batch", "--gen-key"]
+ feeder h = do
+ hPutStr h $ unlines $ catMaybes
+ [ Just $ "Key-Type: " ++
+ case keytype of
+ DSA -> "DSA"
+ RSA -> "RSA"
+ Algo n -> show n
+ , Just $ "Key-Length: " ++ show keysize
+ , Just $ "Name-Real: " ++ userid
+ , Just $ "Expire-Date: 0"
+ , if null passphrase
+ then Nothing
+ else Just $ "Passphrase: " ++ passphrase
+ ]
+ hClose h
+
{- Creates a block of high-quality random data suitable to use as a cipher.
- It is armored, to avoid newlines, since gpg only reads ciphers up to the
- first newline. -}
-genRandom :: Bool -> Int -> IO String
+genRandom :: Bool -> Size -> IO String
genRandom highQuality size = checksize <$> readStrict
[ Params params
, Param $ show randomquality
@@ -260,3 +339,41 @@ testTestHarness = do
keys <- testHarness $ findPubKeys testKeyId
return $ KeyIds [testKeyId] == keys
#endif
+
+#ifndef mingw32_HOST_OS
+checkEncryptionFile :: FilePath -> Maybe KeyIds -> IO Bool
+checkEncryptionFile filename keys =
+ checkGpgPackets keys =<< readStrict params
+ where
+ params = [Params "--list-packets --list-only", File filename]
+
+checkEncryptionStream :: String -> Maybe KeyIds -> IO Bool
+checkEncryptionStream stream keys =
+ checkGpgPackets keys =<< pipeStrict params stream
+ where
+ params = [Params "--list-packets --list-only"]
+
+{- Parses an OpenPGP packet list, and checks whether data is
+ - symmetrically encrypted (keys is Nothing), or encrypted to some
+ - public key(s).
+ - /!\ The key needs to be in the keyring! -}
+checkGpgPackets :: Maybe KeyIds -> String -> IO Bool
+checkGpgPackets keys str = do
+ let (asym,sym) = partition (pubkeyEncPacket `isPrefixOf`) $
+ filter (\l' -> pubkeyEncPacket `isPrefixOf` l' ||
+ symkeyEncPacket `isPrefixOf` l') $
+ takeWhile (/= ":encrypted data packet:") $
+ lines str
+ case (keys,asym,sym) of
+ (Nothing, [], [_]) -> return True
+ (Just (KeyIds ks), ls, []) -> do
+ -- Find the master key associated with the
+ -- encryption subkey.
+ ks' <- concat <$> mapM (keyIds <$$> findPubKeys)
+ [ k | k:"keyid":_ <- map (reverse . words) ls ]
+ return $ sort (nub ks) == sort (nub ks')
+ _ -> return False
+ where
+ pubkeyEncPacket = ":pubkey enc packet: "
+ symkeyEncPacket = ":symkey enc packet: "
+#endif
diff --git a/Utility/Gpg/Types.hs b/Utility/Gpg/Types.hs
deleted file mode 100644
index d45707207..000000000
--- a/Utility/Gpg/Types.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{- gpg data types
- -
- - Copyright 2013 guilhem <guilhem@fripost.org>
- -
- - Licensed under the GNU GPL version 3 or higher.
- -}
-
-module Utility.Gpg.Types where
-
-import Utility.SafeCommand
-import Types.GitConfig
-import Types.Remote
-
-{- GnuPG options. -}
-type GpgOpt = String
-newtype GpgOpts = GpgOpts [GpgOpt]
-
-toParams :: GpgOpts -> [CommandParam]
-toParams (GpgOpts opts) = map Param opts
-
-class LensGpgOpts a where
- getGpgOpts :: a -> GpgOpts
-
-{- Extract the GnuPG options from a Remote Git Config. -}
-instance LensGpgOpts RemoteGitConfig where
- getGpgOpts = GpgOpts . remoteAnnexGnupgOptions
-
-{- Extract the GnuPG options from a Remote. -}
-instance LensGpgOpts (RemoteA a) where
- getGpgOpts = getGpgOpts . gitconfig
diff --git a/Utility/Hash.hs b/Utility/Hash.hs
new file mode 100644
index 000000000..cecc6af3e
--- /dev/null
+++ b/Utility/Hash.hs
@@ -0,0 +1,69 @@
+{- Convenience wrapper around cryptohash.
+ - Falls back to SHA if it's not available.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Utility.Hash (
+ sha1,
+ sha224,
+ sha256,
+ sha384,
+ sha512,
+#ifdef WITH_CRYPTOHASH
+ skein256,
+ skein512,
+#endif
+ prop_hashes_stable
+) where
+
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString.Char8 as C8
+
+#ifndef WITH_CRYPTOHASH
+import Data.Digest.Pure.SHA
+#else
+import Crypto.Hash
+
+sha1 :: L.ByteString -> Digest SHA1
+sha1 = hashlazy
+
+sha224 :: L.ByteString -> Digest SHA224
+sha224 = hashlazy
+
+sha256 :: L.ByteString -> Digest SHA256
+sha256 = hashlazy
+
+sha384 :: L.ByteString -> Digest SHA384
+sha384 = hashlazy
+
+sha512 :: L.ByteString -> Digest SHA512
+sha512 = hashlazy
+
+-- sha3 is not yet fully standardized
+--sha3 :: L.ByteString -> Digest SHA3
+--sha3 = hashlazy
+
+skein256 :: L.ByteString -> Digest Skein256_256
+skein256 = hashlazy
+
+skein512 :: L.ByteString -> Digest Skein512_512
+skein512 = hashlazy
+
+#endif
+
+{- Check that all the hashes continue to hash the same. -}
+prop_hashes_stable :: Bool
+prop_hashes_stable = all (\(hasher, result) -> hasher foo == result)
+ [ (show . sha1, "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
+ , (show . sha224, "0808f64e60d58979fcb676c96ec938270dea42445aeefcd3a4e6f8db")
+ , (show . sha256, "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae")
+ , (show . sha384, "98c11ffdfdd540676b1a137cb1a22b2a70350c9a44171d6b1180c6be5cbb2ee3f79d532c8a1dd9ef2e8e08e752a3babb")
+ , (show . sha512, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7")
+#ifdef WITH_CRYPTOHASH
+ , (show . skein256, "a04efd9a0aeed6ede40fe5ce0d9361ae7b7d88b524aa19917b9315f1ecf00d33")
+ , (show . skein512, "fd8956898113510180aa4658e6c0ac85bd74fb47f4a4ba264a6b705d7a8e8526756e75aecda12cff4f1aca1a4c2830fbf57f458012a66b2b15a3dd7d251690a7")
+#endif
+ ]
+ where
+ foo = L.fromChunks [C8.pack "foo"]
diff --git a/Utility/HumanTime.hs b/Utility/HumanTime.hs
index 038d1228e..644e6fbab 100644
--- a/Utility/HumanTime.hs
+++ b/Utility/HumanTime.hs
@@ -1,26 +1,86 @@
{- Time for humans.
-
- - Copyright 2012 Joey Hess <joey@kitenet.net>
+ - Copyright 2012-2013 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
-module Utility.HumanTime where
+module Utility.HumanTime (
+ Duration(..),
+ durationToPOSIXTime,
+ parseDuration,
+ fromDuration,
+ prop_duration_roundtrips
+) where
import Utility.PartialPrelude
+import Utility.Applicative
+import Utility.QuickCheck
import Data.Time.Clock.POSIX (POSIXTime)
+import Data.Char
+import Control.Applicative
+import qualified Data.Map as M
-{- Parses a human-input time duration, of the form "5h" or "1m". -}
-parseDuration :: String -> Maybe POSIXTime
-parseDuration s = do
- num <- readish s :: Maybe Integer
- units <- findUnits =<< lastMaybe s
- return $ fromIntegral num * units
+newtype Duration = Duration { durationSeconds :: Integer }
+ deriving (Eq, Ord, Read, Show)
+
+durationToPOSIXTime :: Duration -> POSIXTime
+durationToPOSIXTime = fromIntegral . durationSeconds
+
+{- Parses a human-input time duration, of the form "5h", "1m", "5h1m", etc -}
+parseDuration :: String -> Maybe Duration
+parseDuration = Duration <$$> go 0
+ where
+ go n [] = return n
+ go n s = do
+ num <- readish s :: Maybe Integer
+ case dropWhile isDigit s of
+ (c:rest) -> do
+ u <- M.lookup c unitmap
+ go (n + num * u) rest
+ _ -> return $ n + num
+
+fromDuration :: Duration -> String
+fromDuration Duration { durationSeconds = d }
+ | d == 0 = "0s"
+ | otherwise = concat $ map showunit $ go [] units d
where
- findUnits 's' = Just 1
- findUnits 'm' = Just 60
- findUnits 'h' = Just $ 60 * 60
- findUnits 'd' = Just $ 60 * 60 * 24
- findUnits 'y' = Just $ 60 * 60 * 24 * 365
- findUnits _ = Nothing
+ showunit (u, n)
+ | n > 0 = show n ++ [u]
+ | otherwise = ""
+ go c [] _ = reverse c
+ go c ((u, n):us) v =
+ let (q,r) = v `quotRem` n
+ in go ((u, q):c) us r
+
+units :: [(Char, Integer)]
+units =
+ [ ('y', ysecs)
+ , ('d', dsecs)
+ , ('h', hsecs)
+ , ('m', msecs)
+ , ('s', 1)
+ ]
+
+unitmap :: M.Map Char Integer
+unitmap = M.fromList units
+
+ysecs :: Integer
+ysecs = dsecs * 365
+
+dsecs :: Integer
+dsecs = hsecs * 24
+
+hsecs :: Integer
+hsecs = msecs * 60
+
+msecs :: Integer
+msecs = 60
+
+-- Durations cannot be negative.
+instance Arbitrary Duration where
+ arbitrary = Duration <$> nonNegative arbitrary
+
+prop_duration_roundtrips :: Duration -> Bool
+prop_duration_roundtrips d = parseDuration (fromDuration d) == Just d
diff --git a/Utility/INotify.hs b/Utility/INotify.hs
index e9071d906..ffdad8be3 100644
--- a/Utility/INotify.hs
+++ b/Utility/INotify.hs
@@ -54,11 +54,12 @@ watchDir i dir ignored hooks
-- scan come before real inotify events.
lock <- newLock
let handler event = withLock lock (void $ go event)
- void (addWatch i watchevents dir handler)
- `catchIO` failedaddwatch
- withLock lock $
- mapM_ scan =<< filter (not . dirCruft) <$>
- getDirectoryContents dir
+ flip catchNonAsync failedwatch $ do
+ void (addWatch i watchevents dir handler)
+ `catchIO` failedaddwatch
+ withLock lock $
+ mapM_ scan =<< filter (not . dirCruft) <$>
+ getDirectoryContents dir
where
recurse d = watchDir i d ignored hooks
@@ -149,12 +150,14 @@ watchDir i dir ignored hooks
-- disk full error.
| isFullError e =
case errHook hooks of
- Nothing -> throw e
+ Nothing -> error $ "failed to add inotify watch on directory " ++ dir ++ " (" ++ show e ++ ")"
Just hook -> tooManyWatches hook dir
-- The directory could have been deleted.
| isDoesNotExistError e = return ()
| otherwise = throw e
+ failedwatch e = hPutStrLn stderr $ "failed to add watch on directory " ++ dir ++ " (" ++ show e ++ ")"
+
tooManyWatches :: (String -> Maybe FileStatus -> IO ()) -> FilePath -> IO ()
tooManyWatches hook dir = do
sysctlval <- querySysctl [Param maxwatches] :: IO (Maybe Integer)
diff --git a/Utility/InodeCache.hs b/Utility/InodeCache.hs
index 8037c61c8..46ca87bd9 100644
--- a/Utility/InodeCache.hs
+++ b/Utility/InodeCache.hs
@@ -49,6 +49,9 @@ instance Eq InodeCacheKey where
inodeCacheToKey :: InodeComparisonType -> InodeCache -> InodeCacheKey
inodeCacheToKey ct (InodeCache prim) = InodeCacheKey ct prim
+inodeCacheToMtime :: InodeCache -> EpochTime
+inodeCacheToMtime (InodeCache (InodeCachePrim _ _ mtime)) = mtime
+
showInodeCache :: InodeCache -> String
showInodeCache (InodeCache (InodeCachePrim inode size mtime)) = unwords
[ show inode
diff --git a/Utility/Lsof.hs b/Utility/Lsof.hs
index 6d6b353f2..63009f723 100644
--- a/Utility/Lsof.hs
+++ b/Utility/Lsof.hs
@@ -26,8 +26,8 @@ data ProcessInfo = ProcessInfo ProcessID CmdLine
{- lsof is not in PATH on all systems, so SysConfig may have the absolute
- path where the program was found. Make sure at runtime that lsof is
- available, and if it's not in PATH, adjust PATH to contain it. -}
-setupLsof :: IO ()
-setupLsof = do
+setup :: IO ()
+setup = do
let cmd = fromMaybe "lsof" SysConfig.lsof
when (isAbsolute cmd) $ do
path <- getSearchPath
diff --git a/Utility/Misc.hs b/Utility/Misc.hs
index 804a9e487..a2c9c8184 100644
--- a/Utility/Misc.hs
+++ b/Utility/Misc.hs
@@ -29,7 +29,7 @@ hGetContentsStrict = hGetContents >=> \s -> length s `seq` return s
readFileStrict :: FilePath -> IO String
readFileStrict = readFile >=> \s -> length s `seq` return s
-{- Like break, but the character matching the condition is not included
+{- Like break, but the item matching the condition is not included
- in the second result list.
-
- separate (== ':') "foo:bar" = ("foo", "bar")
diff --git a/Utility/Monad.hs b/Utility/Monad.hs
index b66419f76..1ba43c5f8 100644
--- a/Utility/Monad.hs
+++ b/Utility/Monad.hs
@@ -8,7 +8,7 @@
module Utility.Monad where
import Data.Maybe
-import Control.Monad (liftM)
+import Control.Monad
{- Return the first value from a list, if any, satisfying the given
- predicate -}
diff --git a/Utility/Path.hs b/Utility/Path.hs
index 79e8e8089..b6214b247 100644
--- a/Utility/Path.hs
+++ b/Utility/Path.hs
@@ -14,6 +14,7 @@ import System.FilePath
import System.Directory
import Data.List
import Data.Maybe
+import Data.Char
import Control.Applicative
#ifdef mingw32_HOST_OS
@@ -236,3 +237,18 @@ fileNameLengthLimit dir = do
else return $ minimum [l, 255]
where
#endif
+
+{- Given a string that we'd like to use as the basis for FilePath, but that
+ - was provided by a third party and is not to be trusted, returns the closest
+ - sane FilePath.
+ -
+ - All spaces and punctuation are replaced with '_', except for '.'
+ - "../" will thus turn into ".._", which is safe.
+ -}
+sanitizeFilePath :: String -> FilePath
+sanitizeFilePath = map sanitize
+ where
+ sanitize c
+ | c == '.' = c
+ | isSpace c || isPunctuation c || c == '/' = '_'
+ | otherwise = c
diff --git a/Utility/Process.hs b/Utility/Process.hs
index 8ea632120..398e8a352 100644
--- a/Utility/Process.hs
+++ b/Utility/Process.hs
@@ -44,8 +44,10 @@ import qualified Control.Exception as E
import Control.Monad
#ifndef mingw32_HOST_OS
import System.Posix.IO
-import Data.Maybe
+#else
+import Control.Applicative
#endif
+import Data.Maybe
import Utility.Misc
import Utility.Exception
@@ -72,17 +74,17 @@ readProcessEnv cmd args environ =
, env = environ
}
-{- Writes a string to a process on its stdin,
+{- Runs an action to write to a process on its stdin,
- returns its output, and also allows specifying the environment.
-}
writeReadProcessEnv
:: FilePath
-> [String]
-> Maybe [(String, String)]
- -> String
+ -> (Maybe (Handle -> IO ()))
-> (Maybe (Handle -> IO ()))
-> IO String
-writeReadProcessEnv cmd args environ input adjusthandle = do
+writeReadProcessEnv cmd args environ writestdin adjusthandle = do
(Just inh, Just outh, _, pid) <- createProcess p
maybe (return ()) (\a -> a inh) adjusthandle
@@ -94,7 +96,7 @@ writeReadProcessEnv cmd args environ input adjusthandle = do
_ <- forkIO $ E.evaluate (length output) >> putMVar outMVar ()
-- now write and flush any input
- when (not (null input)) $ do hPutStr inh input; hFlush inh
+ maybe (return ()) (\a -> a inh >> hFlush inh) writestdin
hClose inh -- done with stdin
-- wait on the output
@@ -161,6 +163,8 @@ createBackgroundProcess p a = a =<< createProcess p
- whether it succeeded or failed. -}
processTranscript :: String -> [String] -> (Maybe String) -> IO (String, Bool)
#ifndef mingw32_HOST_OS
+{- This implementation interleves stdout and stderr in exactly the order
+ - the process writes them. -}
processTranscript cmd opts input = do
(readf, writef) <- createPipe
readh <- fdToHandle readf
@@ -173,10 +177,7 @@ processTranscript cmd opts input = do
}
hClose writeh
- -- fork off a thread to start consuming the output
- transcript <- hGetContents readh
- outMVar <- newEmptyMVar
- _ <- forkIO $ E.evaluate (length transcript) >> putMVar outMVar ()
+ get <- mkreader readh
-- now write and flush any input
case input of
@@ -188,15 +189,46 @@ processTranscript cmd opts input = do
hClose inh
Nothing -> return ()
- -- wait on the output
- takeMVar outMVar
- hClose readh
+ transcript <- get
ok <- checkSuccessProcess pid
return (transcript, ok)
#else
-processTranscript = error "processTranscript TODO"
+{- This implementation for Windows puts stderr after stdout. -}
+processTranscript cmd opts input = do
+ p@(_, _, _, pid) <- createProcess $
+ (proc cmd opts)
+ { std_in = if isJust input then CreatePipe else Inherit
+ , std_out = CreatePipe
+ , std_err = CreatePipe
+ }
+
+ getout <- mkreader (stdoutHandle p)
+ geterr <- mkreader (stderrHandle p)
+
+ case input of
+ Just s -> do
+ let inh = stdinHandle p
+ unless (null s) $ do
+ hPutStr inh s
+ hFlush inh
+ hClose inh
+ Nothing -> return ()
+
+ transcript <- (++) <$> getout <*> geterr
+ ok <- checkSuccessProcess pid
+ return (transcript, ok)
#endif
+ where
+ mkreader h = do
+ s <- hGetContents h
+ v <- newEmptyMVar
+ void $ forkIO $ do
+ void $ E.evaluate (length s)
+ putMVar v ()
+ return $ do
+ takeMVar v
+ return s
{- Runs a CreateProcessRunner, on a CreateProcess structure, that
- is adjusted to pipe only from/to a single StdHandle, and passes
diff --git a/Utility/QuickCheck.hs b/Utility/QuickCheck.hs
index 078b10c8b..82af09f3d 100644
--- a/Utility/QuickCheck.hs
+++ b/Utility/QuickCheck.hs
@@ -43,3 +43,6 @@ instance Arbitrary FileOffset where
nonNegative :: (Num a, Ord a) => Gen a -> Gen a
nonNegative g = g `suchThat` (>= 0)
+
+positive :: (Num a, Ord a) => Gen a -> Gen a
+positive g = g `suchThat` (> 0)
diff --git a/Utility/Quvi.hs b/Utility/Quvi.hs
new file mode 100644
index 000000000..5df1a4da7
--- /dev/null
+++ b/Utility/Quvi.hs
@@ -0,0 +1,81 @@
+{- querying quvi (import qualified)
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Utility.Quvi where
+
+import Common
+import Utility.Url
+
+import Data.Aeson
+import Data.ByteString.Lazy.UTF8 (fromString)
+
+data Page = Page
+ { pageTitle :: String
+ , pageLinks :: [Link]
+ } deriving (Show)
+
+data Link = Link
+ { linkSuffix :: String
+ , linkUrl :: URLString
+ } deriving (Show)
+
+instance FromJSON Page where
+ parseJSON (Object v) = Page
+ <$> v .: "page_title"
+ <*> v .: "link"
+ parseJSON _ = mzero
+
+instance FromJSON Link where
+ parseJSON (Object v) = Link
+ <$> v .: "file_suffix"
+ <*> v .: "url"
+ parseJSON _ = mzero
+
+type Query a = [CommandParam] -> URLString -> IO a
+
+{- Throws an error when quvi is not installed. -}
+forceQuery :: Query (Maybe Page)
+forceQuery ps url = query' ps url `catchNonAsync` onerr
+ where
+ onerr _ = ifM (inPath "quvi")
+ ( error "quvi failed"
+ , error "quvi is not installed"
+ )
+
+{- Returns Nothing if the page is not a video page, or quvi is not
+ - installed. -}
+query :: Query (Maybe Page)
+query ps url = flip catchNonAsync (const $ return Nothing) (query' ps url)
+
+query' :: Query (Maybe Page)
+query' ps url = decode . fromString
+ <$> readProcess "quvi" (toCommand $ ps ++ [Param url])
+
+queryLinks :: Query [URLString]
+queryLinks ps url = maybe [] (map linkUrl . pageLinks) <$> query ps url
+
+{- Checks if quvi can still find a download link for an url.
+ - If quvi is not installed, returns False. -}
+check :: Query Bool
+check ps url = maybe False (not . null . pageLinks) <$> query ps url
+
+{- Checks if an url is supported by quvi, without hitting it, or outputting
+ - anything. Also returns False if quvi is not installed. -}
+supported :: URLString -> IO Bool
+supported url = boolSystem "quvi" [Params "-v mute --support", Param url]
+
+quiet :: CommandParam
+quiet = Params "-v quiet"
+
+noredir :: CommandParam
+noredir = Params "-e -resolve"
+
+{- Only return http results, not streaming protocols. -}
+httponly :: CommandParam
+httponly = Params "-c http"
diff --git a/Utility/SRV.hs b/Utility/SRV.hs
index 0a77191c4..a2ee704f7 100644
--- a/Utility/SRV.hs
+++ b/Utility/SRV.hs
@@ -67,8 +67,14 @@ lookupSRV (SRV srv) = initResolver [] $ \resolver -> do
lookupSRV (SRV srv) = do
seed <- makeResolvSeed defaultResolvConf
r <- withResolver seed $ flip DNS.lookupSRV $ B8.fromString srv
- return $ maybe [] (orderHosts . map tohosts) r
+ return $
+#if MIN_VERSION_dns(1,0,0)
+ either (const []) use r
+#else
+ maybe [] use r
+#endif
where
+ use = orderHosts . map tohosts
tohosts (priority, weight, port, hostname) =
( (priority, weight)
, (B8.toString hostname, PortNumber $ fromIntegral port)
diff --git a/Utility/Scheduled.hs b/Utility/Scheduled.hs
new file mode 100644
index 000000000..acbee70ff
--- /dev/null
+++ b/Utility/Scheduled.hs
@@ -0,0 +1,350 @@
+{- scheduled activities
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Utility.Scheduled (
+ Schedule(..),
+ Recurrance(..),
+ ScheduledTime(..),
+ NextTime(..),
+ nextTime,
+ fromSchedule,
+ fromScheduledTime,
+ toScheduledTime,
+ fromRecurrance,
+ toRecurrance,
+ toSchedule,
+ parseSchedule,
+ prop_schedule_roundtrips
+) where
+
+import Common
+import Utility.QuickCheck
+
+import Data.Time.Clock
+import Data.Time.LocalTime
+import Data.Time.Calendar
+import Data.Time.Calendar.WeekDate
+import Data.Time.Calendar.OrdinalDate
+import Data.Tuple.Utils
+import Data.Char
+
+{- Some sort of scheduled event. -}
+data Schedule = Schedule Recurrance ScheduledTime
+ deriving (Eq, Read, Show, Ord)
+
+data Recurrance
+ = Daily
+ | Weekly (Maybe WeekDay)
+ | Monthly (Maybe MonthDay)
+ | Yearly (Maybe YearDay)
+ -- Days, Weeks, or Months of the year evenly divisible by a number.
+ -- (Divisible Year is years evenly divisible by a number.)
+ | Divisible Int Recurrance
+ deriving (Eq, Read, Show, Ord)
+
+type WeekDay = Int
+type MonthDay = Int
+type YearDay = Int
+
+data ScheduledTime
+ = AnyTime
+ | SpecificTime Hour Minute
+ deriving (Eq, Read, Show, Ord)
+
+type Hour = Int
+type Minute = Int
+
+{- Next time a Schedule should take effect. The NextTimeWindow is used
+ - when a Schedule is allowed to start at some point within the window. -}
+data NextTime
+ = NextTimeExactly LocalTime
+ | NextTimeWindow LocalTime LocalTime
+ deriving (Eq, Read, Show)
+
+startTime :: NextTime -> LocalTime
+startTime (NextTimeExactly t) = t
+startTime (NextTimeWindow t _) = t
+
+nextTime :: Schedule -> Maybe LocalTime -> IO (Maybe NextTime)
+nextTime schedule lasttime = do
+ now <- getCurrentTime
+ tz <- getTimeZone now
+ return $ calcNextTime schedule lasttime $ utcToLocalTime tz now
+
+{- Calculate the next time that fits a Schedule, based on the
+ - last time it occurred, and the current time. -}
+calcNextTime :: Schedule -> Maybe LocalTime -> LocalTime -> Maybe NextTime
+calcNextTime (Schedule recurrance scheduledtime) lasttime currenttime
+ | scheduledtime == AnyTime = do
+ next <- findfromtoday True
+ return $ case next of
+ NextTimeWindow _ _ -> next
+ NextTimeExactly t -> window (localDay t) (localDay t)
+ | otherwise = NextTimeExactly . startTime <$> findfromtoday False
+ where
+ findfromtoday anytime = findfrom recurrance afterday today
+ where
+ today = localDay currenttime
+ afterday = sameaslastday || toolatetoday
+ toolatetoday = not anytime && localTimeOfDay currenttime >= nexttime
+ sameaslastday = lastday == Just today
+ lastday = localDay <$> lasttime
+ nexttime = case scheduledtime of
+ AnyTime -> TimeOfDay 0 0 0
+ SpecificTime h m -> TimeOfDay h m 0
+ exactly d = NextTimeExactly $ LocalTime d nexttime
+ window startd endd = NextTimeWindow
+ (LocalTime startd nexttime)
+ (LocalTime endd (TimeOfDay 23 59 0))
+ findfrom r afterday day = case r of
+ Daily
+ | afterday -> Just $ exactly $ addDays 1 day
+ | otherwise -> Just $ exactly day
+ Weekly Nothing
+ | afterday -> skip 1
+ | otherwise -> case (wday <$> lastday, wday day) of
+ (Nothing, _) -> Just $ window day (addDays 6 day)
+ (Just old, curr)
+ | old == curr -> Just $ window day (addDays 6 day)
+ | otherwise -> skip 1
+ Monthly Nothing
+ | afterday -> skip 1
+ | maybe True (\old -> mnum day > mday old && mday day >= (mday old `mod` minmday)) lastday ->
+ -- Window only covers current month,
+ -- in case there is a Divisible requirement.
+ Just $ window day (endOfMonth day)
+ | otherwise -> skip 1
+ Yearly Nothing
+ | afterday -> skip 1
+ | maybe True (\old -> ynum day > ynum old && yday day >= (yday old `mod` minyday)) lastday ->
+ Just $ window day (endOfYear day)
+ | otherwise -> skip 1
+ Weekly (Just w)
+ | w < 0 || w > maxwday -> Nothing
+ | w == wday day -> if afterday
+ then Just $ exactly $ addDays 7 day
+ else Just $ exactly day
+ | otherwise -> Just $ exactly $
+ addDays (fromIntegral $ (w - wday day) `mod` 7) day
+ Monthly (Just m)
+ | m < 0 || m > maxmday -> Nothing
+ -- TODO can be done more efficiently than recursing
+ | m == mday day -> if afterday
+ then skip 1
+ else Just $ exactly day
+ | otherwise -> skip 1
+ Yearly (Just y)
+ | y < 0 || y > maxyday -> Nothing
+ | y == yday day -> if afterday
+ then skip 365
+ else Just $ exactly day
+ | otherwise -> skip 1
+ Divisible n r'@Daily -> handlediv n r' yday (Just maxyday)
+ Divisible n r'@(Weekly _) -> handlediv n r' wnum (Just maxwnum)
+ Divisible n r'@(Monthly _) -> handlediv n r' mnum (Just maxmnum)
+ Divisible n r'@(Yearly _) -> handlediv n r' ynum Nothing
+ Divisible _ r'@(Divisible _ _) -> findfrom r' afterday day
+ where
+ skip n = findfrom r False (addDays n day)
+ handlediv n r' getval mmax
+ | n > 0 && maybe True (n <=) mmax =
+ findfromwhere r' (divisible n . getval) afterday day
+ | otherwise = Nothing
+ findfromwhere r p afterday day
+ | maybe True (p . getday) next = next
+ | otherwise = maybe Nothing (findfromwhere r p True . getday) next
+ where
+ next = findfrom r afterday day
+ getday = localDay . startTime
+ divisible n v = v `rem` n == 0
+
+endOfMonth :: Day -> Day
+endOfMonth day =
+ let (y,m,_d) = toGregorian day
+ in fromGregorian y m (gregorianMonthLength y m)
+
+endOfYear :: Day -> Day
+endOfYear day =
+ let (y,_m,_d) = toGregorian day
+ in endOfMonth (fromGregorian y maxmnum 1)
+
+-- extracting various quantities from a Day
+wday :: Day -> Int
+wday = thd3 . toWeekDate
+wnum :: Day -> Int
+wnum = snd3 . toWeekDate
+mday :: Day -> Int
+mday = thd3 . toGregorian
+mnum :: Day -> Int
+mnum = snd3 . toGregorian
+yday :: Day -> Int
+yday = snd . toOrdinalDate
+ynum :: Day -> Int
+ynum = fromIntegral . fst . toOrdinalDate
+
+{- Calendar max and mins. -}
+maxyday :: Int
+maxyday = 366 -- with leap days
+minyday :: Int
+minyday = 365
+maxwnum :: Int
+maxwnum = 53 -- some years have more than 52
+maxmday :: Int
+maxmday = 31
+minmday :: Int
+minmday = 28
+maxmnum :: Int
+maxmnum = 12
+maxwday :: Int
+maxwday = 7
+
+fromRecurrance :: Recurrance -> String
+fromRecurrance (Divisible n r) =
+ fromRecurrance' (++ "s divisible by " ++ show n) r
+fromRecurrance r = fromRecurrance' ("every " ++) r
+
+fromRecurrance' :: (String -> String) -> Recurrance -> String
+fromRecurrance' a Daily = a "day"
+fromRecurrance' a (Weekly n) = onday n (a "week")
+fromRecurrance' a (Monthly n) = onday n (a "month")
+fromRecurrance' a (Yearly n) = onday n (a "year")
+fromRecurrance' a (Divisible _n r) = fromRecurrance' a r -- not used
+
+onday :: Maybe Int -> String -> String
+onday (Just n) s = "on day " ++ show n ++ " of " ++ s
+onday Nothing s = s
+
+toRecurrance :: String -> Maybe Recurrance
+toRecurrance s = case words s of
+ ("every":"day":[]) -> Just Daily
+ ("on":"day":sd:"of":"every":something:[]) -> withday sd something
+ ("every":something:[]) -> noday something
+ ("days":"divisible":"by":sn:[]) ->
+ Divisible <$> getdivisor sn <*> pure Daily
+ ("on":"day":sd:"of":something:"divisible":"by":sn:[]) ->
+ Divisible
+ <$> getdivisor sn
+ <*> withday sd something
+ ("every":something:"divisible":"by":sn:[]) ->
+ Divisible
+ <$> getdivisor sn
+ <*> noday something
+ (something:"divisible":"by":sn:[]) ->
+ Divisible
+ <$> getdivisor sn
+ <*> noday something
+ _ -> Nothing
+ where
+ constructor "week" = Just Weekly
+ constructor "month" = Just Monthly
+ constructor "year" = Just Yearly
+ constructor u
+ | "s" `isSuffixOf` u = constructor $ reverse $ drop 1 $ reverse u
+ | otherwise = Nothing
+ withday sd u = do
+ c <- constructor u
+ d <- readish sd
+ Just $ c (Just d)
+ noday u = do
+ c <- constructor u
+ Just $ c Nothing
+ getdivisor sn = do
+ n <- readish sn
+ if n > 0
+ then Just n
+ else Nothing
+
+fromScheduledTime :: ScheduledTime -> String
+fromScheduledTime AnyTime = "any time"
+fromScheduledTime (SpecificTime h m) =
+ show h' ++ (if m > 0 then ":" ++ pad 2 (show m) else "") ++ " " ++ ampm
+ where
+ pad n s = take (n - length s) (repeat '0') ++ s
+ (h', ampm)
+ | h == 0 = (12, "AM")
+ | h < 12 = (h, "AM")
+ | h == 12 = (h, "PM")
+ | otherwise = (h - 12, "PM")
+
+toScheduledTime :: String -> Maybe ScheduledTime
+toScheduledTime "any time" = Just AnyTime
+toScheduledTime v = case words v of
+ (s:ampm:[])
+ | map toUpper ampm == "AM" ->
+ go s h0
+ | map toUpper ampm == "PM" ->
+ go s (\h -> (h0 h) + 12)
+ | otherwise -> Nothing
+ (s:[]) -> go s id
+ _ -> Nothing
+ where
+ h0 h
+ | h == 12 = 0
+ | otherwise = h
+ go :: String -> (Int -> Int) -> Maybe ScheduledTime
+ go s adjust =
+ let (h, m) = separate (== ':') s
+ in SpecificTime
+ <$> (adjust <$> readish h)
+ <*> if null m then Just 0 else readish m
+
+fromSchedule :: Schedule -> String
+fromSchedule (Schedule recurrance scheduledtime) = unwords
+ [ fromRecurrance recurrance
+ , "at"
+ , fromScheduledTime scheduledtime
+ ]
+
+toSchedule :: String -> Maybe Schedule
+toSchedule = eitherToMaybe . parseSchedule
+
+parseSchedule :: String -> Either String Schedule
+parseSchedule s = do
+ r <- maybe (Left $ "bad recurrance: " ++ recurrance) Right
+ (toRecurrance recurrance)
+ t <- maybe (Left $ "bad time of day: " ++ scheduledtime) Right
+ (toScheduledTime scheduledtime)
+ Right $ Schedule r t
+ where
+ (rws, tws) = separate (== "at") (words s)
+ recurrance = unwords rws
+ scheduledtime = unwords tws
+
+instance Arbitrary Schedule where
+ arbitrary = Schedule <$> arbitrary <*> arbitrary
+
+instance Arbitrary ScheduledTime where
+ arbitrary = oneof
+ [ pure AnyTime
+ , SpecificTime
+ <$> choose (0, 23)
+ <*> choose (1, 59)
+ ]
+
+instance Arbitrary Recurrance where
+ arbitrary = oneof
+ [ pure Daily
+ , Weekly <$> arbday
+ , Monthly <$> arbday
+ , Yearly <$> arbday
+ , Divisible
+ <$> positive arbitrary
+ <*> oneof -- no nested Divisibles
+ [ pure Daily
+ , Weekly <$> arbday
+ , Monthly <$> arbday
+ , Yearly <$> arbday
+ ]
+ ]
+ where
+ arbday = oneof
+ [ Just <$> nonNegative arbitrary
+ , pure Nothing
+ ]
+
+prop_schedule_roundtrips :: Schedule -> Bool
+prop_schedule_roundtrips s = toSchedule (fromSchedule s) == Just s
diff --git a/Utility/Url.hs b/Utility/Url.hs
index 508b9eeb4..97296c920 100644
--- a/Utility/Url.hs
+++ b/Utility/Url.hs
@@ -9,7 +9,9 @@
module Utility.Url (
URLString,
+ UserAgent,
check,
+ checkBoth,
exists,
download,
downloadQuiet
@@ -27,14 +29,22 @@ type URLString = String
type Headers = [String]
+type UserAgent = String
+
{- Checks that an url exists and could be successfully downloaded,
- also checking that its size, if available, matches a specified size. -}
-check :: URLString -> Headers -> Maybe Integer -> IO Bool
-check url headers expected_size = handle <$> exists url headers
+checkBoth :: URLString -> Headers -> Maybe Integer -> Maybe UserAgent -> IO Bool
+checkBoth url headers expected_size ua = do
+ v <- check url headers expected_size ua
+ return (fst v && snd v)
+check :: URLString -> Headers -> Maybe Integer -> Maybe UserAgent -> IO (Bool, Bool)
+check url headers expected_size = handle <$$> exists url headers
where
- handle (False, _) = False
- handle (True, Nothing) = True
- handle (True, s) = expected_size == s
+ handle (False, _) = (False, False)
+ handle (True, Nothing) = (True, True)
+ handle (True, s) = case expected_size of
+ Just _ -> (True, expected_size == s)
+ Nothing -> (True, True)
{- Checks that an url exists and could be successfully downloaded,
- also returning its size if available.
@@ -44,8 +54,8 @@ check url headers expected_size = handle <$> exists url headers
- Uses curl otherwise, when available, since curl handles https better
- than does Haskell's Network.Browser.
-}
-exists :: URLString -> Headers -> IO (Bool, Maybe Integer)
-exists url headers = case parseURIRelaxed url of
+exists :: URLString -> Headers -> Maybe UserAgent -> IO (Bool, Maybe Integer)
+exists url headers ua = case parseURIRelaxed url of
Just u
| uriScheme u == "file:" -> do
s <- catchMaybeIO $ getFileStatus (unEscapeString $ uriPath u)
@@ -54,12 +64,12 @@ exists url headers = case parseURIRelaxed url of
Nothing -> dne
| otherwise -> if Build.SysConfig.curl
then do
- output <- readProcess "curl" curlparams
+ output <- readProcess "curl" $ toCommand curlparams
case lastMaybe (lines output) of
Just ('2':_:_) -> return (True, extractsize output)
_ -> dne
else do
- r <- request u headers HEAD
+ r <- request u headers HEAD ua
case rspCode r of
(2,_,_) -> return (True, size r)
_ -> return (False, Nothing)
@@ -67,13 +77,12 @@ exists url headers = case parseURIRelaxed url of
where
dne = return (False, Nothing)
- curlparams =
- [ "-s"
- , "--head"
- , "-L"
- , url
- , "-w", "%{http_code}"
- ] ++ concatMap (\h -> ["-H", h]) headers
+ curlparams = addUserAgent ua $
+ [ Param "-s"
+ , Param "--head"
+ , Param "-L", Param url
+ , Param "-w", Param "%{http_code}"
+ ] ++ concatMap (\h -> [Param "-H", Param h]) headers
extractsize s = case lastMaybe $ filter ("Content-Length:" `isPrefixOf`) (lines s) of
Just l -> case lastMaybe $ words l of
@@ -83,6 +92,11 @@ exists url headers = case parseURIRelaxed url of
size = liftM Prelude.read . lookupHeader HdrContentLength . rspHeaders
+-- works for both wget and curl commands
+addUserAgent :: Maybe UserAgent -> [CommandParam] -> [CommandParam]
+addUserAgent Nothing ps = ps
+addUserAgent (Just ua) ps = ps ++ [Param "--user-agent", Param ua]
+
{- Used to download large files, such as the contents of keys.
-
- Uses wget or curl program for its progress bar. (Wget has a better one,
@@ -90,15 +104,15 @@ exists url headers = case parseURIRelaxed url of
- would not be appropriate to test at configure time and build support
- for only one in.
-}
-download :: URLString -> Headers -> [CommandParam] -> FilePath -> IO Bool
+download :: URLString -> Headers -> [CommandParam] -> FilePath -> Maybe UserAgent -> IO Bool
download = download' False
{- No output, even on error. -}
-downloadQuiet :: URLString -> Headers -> [CommandParam] -> FilePath -> IO Bool
+downloadQuiet :: URLString -> Headers -> [CommandParam] -> FilePath -> Maybe UserAgent -> IO Bool
downloadQuiet = download' True
-download' :: Bool -> URLString -> Headers -> [CommandParam] -> FilePath -> IO Bool
-download' quiet url headers options file =
+download' :: Bool -> URLString -> Headers -> [CommandParam] -> FilePath -> Maybe UserAgent -> IO Bool
+download' quiet url headers options file ua =
case parseURIRelaxed url of
Just u
| uriScheme u == "file:" -> do
@@ -110,7 +124,7 @@ download' quiet url headers options file =
_ -> return False
where
headerparams = map (\h -> Param $ "--header=" ++ h) headers
- wget = go "wget" $ headerparams ++ quietopt "-q" ++ [Params "-c -O"]
+ wget = go "wget" $ headerparams ++ quietopt "-q" ++ [Params "--clobber -c -O"]
{- Uses the -# progress display, because the normal
- one is very confusing when resuming, showing
- the remainder to download as the whole file,
@@ -119,7 +133,7 @@ download' quiet url headers options file =
curl = go "curl" $ headerparams ++ quietopt "-s" ++
[Params "-f -L -C - -# -o"]
go cmd opts = boolSystem cmd $
- options++opts++[File file, File url]
+ addUserAgent ua $ options++opts++[File file, File url]
quietopt s
| quiet = [Param s]
| otherwise = []
@@ -134,13 +148,14 @@ download' quiet url headers options file =
- Unfortunately, does not handle https, so should only be used
- when curl is not available.
-}
-request :: URI -> Headers -> RequestMethod -> IO (Response String)
-request url headers requesttype = go 5 url
+request :: URI -> Headers -> RequestMethod -> Maybe UserAgent -> IO (Response String)
+request url headers requesttype ua = go 5 url
where
go :: Int -> URI -> IO (Response String)
go 0 _ = error "Too many redirects "
go n u = do
rsp <- Browser.browse $ do
+ maybe noop Browser.setUserAgent ua
Browser.setErrHandler ignore
Browser.setOutHandler ignore
Browser.setAllowRedirects False
diff --git a/Utility/WebApp.hs b/Utility/WebApp.hs
index f3c0d3a6b..421dadb39 100644
--- a/Utility/WebApp.hs
+++ b/Utility/WebApp.hs
@@ -12,6 +12,7 @@ module Utility.WebApp where
import Common
import Utility.Tmp
import Utility.FileMode
+import Utility.Hash
import qualified Yesod
import qualified Network.Wai as Wai
@@ -23,8 +24,7 @@ import System.Log.Logger
import qualified Data.CaseInsensitive as CI
import Network.Socket
import Control.Exception
-import Crypto.Random
-import Data.Digest.Pure.SHA
+import "crypto-api" Crypto.Random
import qualified Web.ClientSession as CS
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.UTF8 as L8
@@ -214,7 +214,7 @@ genRandomToken = do
return $
case genBytes 512 g of
Left e -> error $ "failed to generate secret token: " ++ show e
- Right (s, _) -> showDigest $ sha512 $ L.fromChunks [s]
+ Right (s, _) -> show $ sha512 $ L.fromChunks [s]
{- A Yesod isAuthorized method, which checks the auth cgi parameter
- against a token extracted from the Yesod application.
diff --git a/Utility/Win32Notify.hs b/Utility/Win32Notify.hs
new file mode 100644
index 000000000..edde5309c
--- /dev/null
+++ b/Utility/Win32Notify.hs
@@ -0,0 +1,65 @@
+{- Win32-notify interface
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Utility.Win32Notify where
+
+import Common hiding (isDirectory)
+import Utility.DirWatcher.Types
+
+import System.Win32.Notify
+import qualified System.PosixCompat.Files as Files
+
+watchDir :: FilePath -> (FilePath -> Bool) -> WatchHooks -> IO WatchManager
+watchDir dir ignored hooks = do
+ scan dir
+ wm <- initWatchManager
+ void $ watchDirectory wm dir True [Create, Delete, Modify, Move] handle
+ return wm
+ where
+ handle evt
+ | ignoredPath ignored (filePath evt) = noop
+ | otherwise = case evt of
+ (Deleted _ _)
+ | isDirectory evt -> runhook delDirHook Nothing
+ | otherwise -> runhook delHook Nothing
+ (Created _ _)
+ | isDirectory evt -> noop
+ | otherwise -> runhook addHook Nothing
+ (Modified _ _)
+ | isDirectory evt -> noop
+ {- Add hooks are run when a file is modified for
+ - compatability with INotify, which calls the add
+ - hook when a file is closed, and so tends to call
+ - both add and modify for file modifications. -}
+ | otherwise -> do
+ runhook addHook Nothing
+ runhook modifyHook Nothing
+ where
+ runhook h s = maybe noop (\a -> a (filePath evt) s) (h hooks)
+
+ scan d = unless (ignoredPath ignored d) $
+ mapM_ go =<< dirContentsRecursive d
+ where
+ go f
+ | ignoredPath ignored f = noop
+ | otherwise = do
+ ms <- getstatus f
+ case ms of
+ Nothing -> noop
+ Just s
+ | Files.isRegularFile s ->
+ runhook addHook ms
+ | otherwise ->
+ noop
+ where
+ runhook h s = maybe noop (\a -> a f s) (h hooks)
+
+ getstatus = catchMaybeIO . getFileStatus
+
+{- Check each component of the path to see if it's ignored. -}
+ignoredPath :: (FilePath -> Bool) -> FilePath -> Bool
+ignoredPath ignored = any ignored . map dropTrailingPathSeparator . splitPath
diff --git a/debian/NEWS b/debian/NEWS
index 1c9514691..1266bae20 100644
--- a/debian/NEWS
+++ b/debian/NEWS
@@ -1,3 +1,11 @@
+git-annex (4.20131002) unstable; urgency=low
+
+ The layout of gcrypt repositories has changed, and
+ if you created one you must manually upgrade it.
+ See /usr/share/doc/git-annex/html/upgrades/gcrypt.html
+
+ -- Joey Hess <joeyh@debian.org> Tue, 24 Sep 2013 13:55:23 -0400
+
git-annex (3.20120123) unstable; urgency=low
There was a bug in the handling of directory special remotes that
diff --git a/debian/changelog b/debian/changelog
index 08a94dbc3..975818366 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,274 @@
-git-annex (4.20130803) UNRELEASED; urgency=low
+git-annex (5.20131102) UNRELEASED; urgency=low
+
+ * Direct mode repositories now have core.bare=true set, to prevent
+ accidentally running git commands that try to operate on the work tree,
+ and so do the wrong thing in direct mode.
+ * annex.version is now set to 5 for direct mode repositories.
+ This upgrade is handled fully automatically, no need to run
+ git annex upgrade
+ * The "status" command has been renamed to "info", to allow
+ "git annex status" to be used in direct mode repositories, now that
+ "git status" won't work in them.
+ * The -c option now not only modifies the git configuration seen by
+ git-annex, but it is passed along to every git command git-annex runs.
+ * watcher: Avoid loop when adding a file owned by someone else fails
+ in indirect mode because its permissions cannot be modified.
+ * webapp: Avoid encoding problems when displaying the daemon log file.
+ * webapp: Improve UI around remote that have no annex.uuid set,
+ either because setup of them is incomplete, or because the remote
+ git repository is not a git-annex repository.
+ * Include ssh-keygen in standalone bundle.
+ * Allow optionally configuring git-annex with -fEKG to enable awesome
+ remote monitoring interfaceat http://localhost:4242/
+ * Fix bug that caused bad information to be written to the git-annex branch
+ when running describe or other commands with a remote that has no uuid.
+ * Work around Android linker problem that had prevented git-annex from
+ running on Android 4.3 and 4.4.
+ * repair: Handle case where index file is corrupt, but all objects are ok.
+ * assistant: Notice on startup when the index file is corrupt, and
+ auto-repair.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 06 Nov 2013 16:14:14 -0400
+
+git-annex (4.20131106) unstable; urgency=low
+
+ * Improve local pairing behavior when two computers both try to start
+ the pairing process separately.
+ * sync: Work even when the local git repository is new and empty,
+ with no master branch.
+ * gcrypt, bup: Fix bug that prevented using these special remotes
+ with encryption=pubkey.
+ * Fix enabling of gcrypt repository accessed over ssh;
+ git-annex-shell gcryptsetup had a bug that caused it to fail
+ with permission denied.
+ * Fix zombie process that occurred when switching between repository
+ views in the webapp.
+ * map: Work when there are gcrypt remotes.
+ * Fix build w/o webapp.
+ * Fix exception handling bug that could cause .git/annex/index to be used
+ for git commits outside the git-annex branch. Known to affect git-annex
+ when used with the git shipped with Ubuntu 13.10.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 06 Nov 2013 11:17:47 -0400
+
+git-annex (4.20131101) unstable; urgency=low
+
+ * The "git annex content" command is renamed to "git annex wanted".
+ * New --want-get and --want-drop options which can be used to
+ test preferred content settings.
+ For example, "git annex find --in . --want-drop"
+ * assistant: When autostarted, wait 5 seconds before running the startup
+ scan, to avoid contending with the user's desktop login process.
+ * webapp: When setting up a bare shared repository, enable non-fast-forward
+ pushes.
+ * sync: Show a hint about receive.denyNonFastForwards when a push fails.
+ * directory, webdav: Fix bug introduced in version 4.20131002 that
+ caused the chunkcount file to not be written. Work around repositories
+ without such a file, so files can still be retreived from them.
+ * assistant: Automatically repair damanged git repository, if it can
+ be done without losing data.
+ * assistant: Support repairing git remotes that are locally accessible
+ (eg, on removable drives).
+ * add: Fix reversion in 4.20130827 when adding unlocked files that have
+ not yet been committed.
+ * unannex: New, much slower, but more safe behavior: Copies files out of
+ the annex. This avoids an unannex of one file breaking other files that
+ link to the same content. Also, it means that the content
+ remains in the annex using up space until cleaned up with
+ "git annex unused".
+ (The behavior of unannex --fast has not changed; it still hard links
+ to content in the annex. --fast was not made the default because it is
+ potentially unsafe; editing such a hard linked file can unexpectedly
+ change content stored in the annex.)
+
+ -- Joey Hess <joeyh@debian.org> Fri, 01 Nov 2013 11:34:27 -0400
+
+git-annex (4.20131024) unstable; urgency=low
+
+ * webapp: Fix bug when adding a remote and git-remote-gcrypt
+ is not installed.
+ * The assitant can now run scheduled incremental fsck jobs on the local
+ repository and remotes. These can be configured using vicfg or with the
+ webapp.
+ * repair: New command, which can repair damaged git repositories
+ (even ones not using git-annex).
+ * webapp: When git repository damange is detected, repairs can be
+ done using the webapp UI.
+ * Automatically and safely detect and recover from dangling
+ .git/annex/index.lock files, which would prevent git from
+ committing to the git-annex branch, eg after a crash.
+ * assistant: Detect stale git lock files at startup time, and remove them.
+ * addurl: Better sanitization of generated filenames.
+ * Better sanitization of problem characters when generating URL and WORM
+ keys.
+ * The control socket path passed to ssh needs to be 17 characters
+ shorter than the maximum unix domain socket length, because ssh
+ appends stuff to it to make a temporary filename. Closes: #725512
+ * status: Fix space leak in local mode, introduced in version 4.20130920.
+ * import: Skip .git directories.
+ * Remove bogus runshell loop check.
+ * addurl: Improve message when adding url with wrong size to existing file.
+ * Fixed handling of URL keys that have no recorded size.
+ * status: Fix a crash if a temp file went away while its size was
+ being checked for status.
+ * Deal with git check-attr -z output format change in git 1.8.5.
+ * Work around sed output difference that led to version containing a newline
+ on OSX.
+ * sync: Fix automatic resolution of merge conflicts where one side is an
+ annexed file, and the other side is a non-annexed file, or a directory.
+ * S3: Try to ensure bucket name is valid for archive.org.
+ * assistant: Bug fix: When run in a subdirectory, files from incoming merges
+ were wrongly added to that subdirectory, and removed from their original
+ locations.
+ * Windows: Deal with strange msysgit 1.8.4 behavior of not understanding
+ DOS formatted paths for --git-dir and --work-tree.
+ * Removed workaround for bug in git 1.8.4r0.
+ * Added git-recover-repository command to git-annex source
+ (not built by default; this needs to move to someplace else).
+ * webapp: Move sidebar to the right hand side of the screen.
+
+ -- Joey Hess <joeyh@debian.org> Thu, 24 Oct 2013 12:59:55 -0400
+
+git-annex (4.20131002) unstable; urgency=low
+
+ * Note that the layout of gcrypt repositories has changed, and
+ if you created one you must manually upgrade it.
+ See http://git-annex.branchable.com/upgrades/gcrypt/
+ * webapp: Support setting up and using encrypted git repositories on
+ any ssh server, as well as on rsync.net.
+ * git-annex-shell: Added support for operating inside gcrypt repositories.
+ * Disable receive.denyNonFastForwards when setting up a gcrypt special
+ remote, since gcrypt needs to be able to fast-forward the master branch.
+ * import: Preserve top-level directory structure.
+ * Use cryptohash rather than SHA for hashing when no external hash program
+ is available. This is a significant speedup for SHA256 on OSX, for
+ example.
+ * Added SKEIN256 and SKEIN512 backends.
+ * Android build redone from scratch, many dependencies updated,
+ and entire build can now be done using provided scripts.
+ * assistant: Clear the list of failed transfers when doing a full transfer
+ scan. This prevents repeated retries to download files that are not
+ available, or are not referenced by the current git tree.
+ * indirect, direct: Better behavior when a file is not owned by
+ the user running the conversion.
+ * add, import, assistant: Better preserve the mtime of symlinks,
+ when when adding content that gets deduplicated.
+ * Send a git-annex user-agent when downloading urls.
+ Overridable with --user-agent option.
+ (Not yet done for S3 or WebDAV due to limitations of libraries used.)
+ * webapp: Fixed a bug where when a new remote is added, one file
+ may fail to sync to or from it due to the transferrer process not
+ yet knowing about the new remote.
+ * OSX: Bundled gpg upgraded, now compatible with config files
+ written by MacGPG.
+ * assistant: More robust inotify handling; avoid crashing if a directory
+ cannot be read.
+ * Moved list of backends and remote types from status to version
+ command.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 02 Oct 2013 16:00:39 -0400
+
+git-annex (4.20130920) unstable; urgency=low
+
+ * webapp: Initial support for setting up encrypted removable drives.
+ * Recommend using my patched gcrypt, which fixes some bugs:
+ https://github.com/joeyh/git-remote-gcrypt
+ * Support hot-swapping of removable drives containing gcrypt repositories.
+ * list: New command, displays a compact table of remotes that
+ contain files.
+ (Thanks, anarcat for display code and mastensg for inspiration.)
+ * fsck: Fix detection and fixing of present direct mode files that are
+ wrongly represented as standin symlinks on crippled filesystems.
+ * sync: Fix bug that caused direct mode mappings to not be updated
+ when merging files into the tree on Windows.
+ * sync: Don't fail if the directory it is run in gets removed by the
+ sync.
+ * addurl: Fix quvi audodetection, broken in last release.
+ * status: In local mode, displays information about variance from configured
+ numcopies levels. (--fast avoids calculating these)
+ * gcrypt: Ensure that signing key is set to one of the participants keys.
+ * webapp: Show encryption information when editing a remote.
+ * Avoid unnecessarily catting non-symlink files from git, which can be
+ so large it runs out of memory.
+
+ -- Joey Hess <joeyh@debian.org> Fri, 20 Sep 2013 10:34:51 -0400
+
+git-annex (4.20130911) unstable; urgency=low
+
+ * Fix problem with test suite in non-unicode locale.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 11 Sep 2013 12:14:16 -0400
+
+git-annex (4.20130909) unstable; urgency=low
+
+ * initremote: Syntax change when setting up an encrypted special remote.
+ Now use keyid=$KEYID rather than the old encryption=$KEYID
+ * forget: New command, causes git-annex branch history to be forgotten
+ in a way that will spread to other clones of the repository.
+ (As long as they're running this version or newer of git-annex.)
+ * forget --drop-dead: Completely removes mentions of repositories that
+ have been marked as dead from the git-annex branch.
+ * sync, assistant: Force push of the git-annex branch. Necessary
+ to ensure it gets pushed to remotes after being rewritten by forget.
+ * Added gcrypt support. This combines a fully encrypted git
+ repository (using git-remote-gcrypt) with an encrypted git-annex special
+ remote.
+ * sync: Support syncing with gcrypt remotes.
+ * importfeed: Also ignore transient problems with downloading content
+ from feeds.
+ * Honor core.sharedrepository when receiving and adding files in direct
+ mode.
+ * enableremote: gpg keys can be removed from those a remote encrypts
+ to by passing "keyid-=$KEYID". keyid+= is also provided.
+ (Thanks, guilhem for the patch.)
+ * Added encryption=pubkey scheme, which encrypts to public keys directly
+ rather than the hybrid approach. See documentation for advantages
+ and disadvantages, but encryption=hybrid is the recommended scheme still.
+ (Thanks, guilhem for the patch.)
+ * Fix Feeds display in build flags.
+ * Remind user when annex-ignore is set for some remotes, if unable to
+ get or drop a file, possibly because it's on an ignored remote.
+ * gpg: Force --no-textmode in case the user has it turned on in config.
+ * webapp: Improve javascript's handling of longpolling connection
+ failures, by reloading the current page in this case.
+ Works around chromium behavior where ajax connections to urls
+ that were already accessed are denied after navigating back to
+ a previous page.
+ * Allow building without quvi support.
+
+ -- Joey Hess <joeyh@debian.org> Mon, 09 Sep 2013 09:47:02 -0400
+
+git-annex (4.20130827) unstable; urgency=low
+
+ * Youtube support! (And 53 other video hosts). When quvi is installed,
+ git-annex addurl automatically uses it to detect when an page is
+ a video, and downloads the video file.
+ * web special remote: Also support using quvi, for getting files,
+ or checking if files exist in the web.
+ * unused: Is now a minimum of 30 times faster, and typically many
+ more times than that (when a repository has several branches).
+ (Thanks, guilhem for the patch.)
+ * unused: Fix bugs in two edge cases involving manually staged changes.
+ (Thanks, guilhem for the patch.)
+ * Android: Fix bug in terminal app that caused it to spin using much
+ CPU and battery. This problem was introduced in version 4.20130601.
+ * sync, merge: Bug fix: Don't try to merge into master when in a bare repo.
+ * import: Add options to control handling of duplicate files:
+ --duplicate, --deduplicate, and --clean-duplicates
+ * mirror: New command, makes two repositories contain the same set of files.
+ * Set --clobber when running wget to ensure resuming works properly.
+ * Unescape characters in 'file://...' URIs. (Thanks, guilhem for the patch.)
+ * Better error message when trying to use a git remote that has annex.ignore
+ set.
+ * Fix bug that caused typechanged symlinks to be assumed to be unlocked
+ files, so they were added to the annex by the pre-commit hook.
+ * Debian: Run the builtin test suite as an autopkgtest.
+ * Debian: Recommend ssh-askpass, which ssh will use when the assistant
+ is run w/o a tty. Closes: #719832
+
+ -- Joey Hess <joeyh@debian.org> Tue, 27 Aug 2013 11:03:00 -0400
+
+git-annex (4.20130815) unstable; urgency=low
* assistant, watcher: .gitignore files and other git ignores are now
honored, when git 1.8.4 or newer is installed.
@@ -10,7 +280,7 @@ git-annex (4.20130803) UNRELEASED; urgency=low
* Windows: Fixed permissions problem that prevented removing files
from directory special remote. Directory special remotes now fully usable.
- -- Joey Hess <joeyh@debian.org> Fri, 02 Aug 2013 19:26:20 -0400
+ -- Joey Hess <joeyh@debian.org> Thu, 15 Aug 2013 10:14:33 +0200
git-annex (4.20130802) unstable; urgency=low
diff --git a/debian/control b/debian/control
index 49c0bde93..6fbd2a06a 100644
--- a/debian/control
+++ b/debian/control
@@ -9,6 +9,7 @@ Build-Depends:
libghc-hslogger-dev,
libghc-pcre-light-dev,
libghc-sha-dev,
+ libghc-cryptohash-dev,
libghc-regex-tdfa-dev [!mips !mipsel !s390],
libghc-dataenc-dev,
libghc-utf8-string-dev,
@@ -21,6 +22,7 @@ Build-Depends:
libghc-dlist-dev,
libghc-uuid-dev,
libghc-json-dev,
+ libghc-aeson-dev,
libghc-ifelse-dev,
libghc-bloomfilter-dev,
libghc-edit-distance-dev,
@@ -51,7 +53,7 @@ Build-Depends:
libghc-feed-dev,
ikiwiki,
perlmagick,
- git,
+ git (>= 1:1.8.4),
rsync,
wget,
curl,
@@ -60,17 +62,18 @@ Maintainer: Joey Hess <joeyh@debian.org>
Standards-Version: 3.9.4
Vcs-Git: git://git.kitenet.net/git-annex
Homepage: http://git-annex.branchable.com/
+XS-Testsuite: autopkgtest
Package: git-annex
Architecture: any
Section: utils
Depends: ${misc:Depends}, ${shlibs:Depends},
- git (>= 1:1.7.7.6),
+ git (>= 1:1.8.4),
rsync,
wget,
curl,
openssh-client (>= 1:5.6p1)
-Recommends: lsof, gnupg, bind9-host
+Recommends: lsof, gnupg, bind9-host, ssh-askpass, quvi, git-remote-gcrypt (>= 0.20130908-4)
Suggests: graphviz, bup, libnss-mdns
Description: manage files with git, without checking their contents into git
git-annex allows managing files with git, without checking the file
diff --git a/debian/copyright b/debian/copyright
index 5a667adf7..e91cddbb5 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -14,10 +14,6 @@ Copyright: 2011 Bas van Dijk & Roel van Dijk
2012 Joey Hess <joey@kitenet.net>
License: GPL-3+
-Files: Utility/Gpg/Types.hs
-Copyright: 2013 guilhem <guilhem@fripost.org>
-License: GPL-3+
-
Files: doc/logo* */favicon.ico standalone/osx/git-annex.app/Contents/Resources/git-annex.icns standalone/android/icons/*
Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>
2010 Joey Hess <joey@kitenet.net>
diff --git a/debian/tests/basics b/debian/tests/basics
new file mode 100644
index 000000000..2e4ea43fc
--- /dev/null
+++ b/debian/tests/basics
@@ -0,0 +1,4 @@
+#!/bin/sh
+testdir="$(mktemp -d)"
+cd "$testdir"
+exec git-annex test
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 000000000..928caf8e3
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,4 @@
+Tests: basics
+Depends: @, git, rsync, gnupg
+Restrictions: allow-stderr
+
diff --git a/doc/Android/comment_5_ba11b81c671d9bcd6f496fbd6f562b0f._comment b/doc/Android/comment_5_ba11b81c671d9bcd6f496fbd6f562b0f._comment
new file mode 100644
index 000000000..54053b43d
--- /dev/null
+++ b/doc/Android/comment_5_ba11b81c671d9bcd6f496fbd6f562b0f._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://mebus.myopenid.com/"
+ ip="2a01:198:3eb:0:4a5b:39ff:fea4:55b3"
+ subject="comment 5"
+ date="2013-10-19T18:05:52Z"
+ content="""
+Hallo,
+
+how can I use the app with public/private keys for SSH. Where can I add them?
+
+Thanks
+
+Mebus
+
+
+"""]]
diff --git a/doc/assistant.mdwn b/doc/assistant.mdwn
index 437f13af1..ccad08893 100644
--- a/doc/assistant.mdwn
+++ b/doc/assistant.mdwn
@@ -31,12 +31,13 @@ instructions.
## colophon
-The git-annex assistant is being
-[crowd funded on
+The git-annex assistant was [crowd funded on
Kickstarter](http://www.kickstarter.com/projects/joeyh/git-annex-assistant-like-dropbox-but-with-your-own/).
-[[/assistant/Thanks]] to all my backers. This kickstarter is now closed, and there is a new home-made crowdfunding project to support the project for 2013-2014 [here](https://campaign.joeyh.name/).
+[[/assistant/Thanks]] to all my backers. This kickstarter is now closed,
+and there is a new home-made crowdfunding project to support the project
+for 2013-2014 [here](https://campaign.joeyh.name/).
-I blog about my work on the git-annex assistant on a daily basis
-in [[this_blog|design/assistant/blog]]. Follow along!
+I blog about my work on git-annex and the assistant on a daily basis
+in [[this_blog|/devblog]]. Follow along!
See also: The [[design|/design/assistant]] pages.
diff --git a/doc/assistant/brokenrepositoryalert.png b/doc/assistant/brokenrepositoryalert.png
new file mode 100644
index 000000000..ea001aec0
--- /dev/null
+++ b/doc/assistant/brokenrepositoryalert.png
Binary files differ
diff --git a/doc/assistant/encryptdrive.png b/doc/assistant/encryptdrive.png
new file mode 100644
index 000000000..1cb041dda
--- /dev/null
+++ b/doc/assistant/encryptdrive.png
Binary files differ
diff --git a/doc/assistant/fsckconfig.png b/doc/assistant/fsckconfig.png
new file mode 100644
index 000000000..81ae755cf
--- /dev/null
+++ b/doc/assistant/fsckconfig.png
Binary files differ
diff --git a/doc/assistant/genkey.png b/doc/assistant/genkey.png
new file mode 100644
index 000000000..6c1e50971
--- /dev/null
+++ b/doc/assistant/genkey.png
Binary files differ
diff --git a/doc/assistant/local_pairing_walkthrough.mdwn b/doc/assistant/local_pairing_walkthrough.mdwn
index 07b639910..f6282ec28 100644
--- a/doc/assistant/local_pairing_walkthrough.mdwn
+++ b/doc/assistant/local_pairing_walkthrough.mdwn
@@ -34,6 +34,36 @@ git-annex folders. Just like that you can share files.
----
+## Requirements
+
+For local pairing to work, you must have sshd (ssh server daemon) installed and working on all machines involved. That means you must allow at least local connections to sshd. On most Linux distributions, sshd is packaged in either openssh (openSUSE) or openssh-server (Debian).
+
+It is highly recommended that you disable root login, disable password login to sshd and just enable key based authentication instead. No one will be able to login without your key.
+
+To disable root, after installing sshd, edit the sshd config (usually /etc/ssh/sshd_config file) and disable root login by adding:
+
+ PermitRootLogin no
+
+Restart sshd. See man sshd_config for details.
+
+To disable password login and enable key based authentication, edit the sshd config (just like above) by uncommenting and changing the following options:
+
+ ChallengeResponseAuthentication no
+ PasswordAuthentication no
+ UsePAM no
+
+ PubkeyAuthentication yes
+
+Restart sshd. See man sshd_config for details.
+
+You can also restrict login to your local network only (not allow internet users from trying to log into your computer). Edit the hosts.deny file (usually /etc/hosts.deny) by adding the following:
+
+ sshd : ALL EXCEPT LOCAL
+
+Do note that restricting login to your local network may or may not block git-annex. Also note that this will not work on Mac OSX because Apple decided to disable this feature and replace it with a crippled version made by Apple.
+
+## Tips
+
Something to keep in mind, especially if pairing doesn't seem to be
working, is that the two computers need to be on the same network for this
pairing process to work. Sometimes a building will have more than one
diff --git a/doc/assistant/release_notes.mdwn b/doc/assistant/release_notes.mdwn
index 371d7cbc2..1b1ece0a0 100644
--- a/doc/assistant/release_notes.mdwn
+++ b/doc/assistant/release_notes.mdwn
@@ -1,3 +1,34 @@
+## version 4.20131024
+
+This version fixes several different bugs that could cause the webapp to
+refuse to create a repository. Several other bugs are also fixed, including
+a bug that caused it to not add files on Android.
+
+New in this release is the ability to use the webapp to set up scheduled
+consistency checks of your repositories. Many problems with repositories
+are now automatically corrected, and it can even repair damaged git
+repositories.
+
+This is a recommended upgrade.
+
+## version 4.20131002
+
+Now you can use the webapp to set up an encrypted git repository on a
+remote ssh server, or on rsync.net, and use it as a live cloud backup. Or,
+use the webapp to make an encrypted git repository on a removable drive,
+and store it offsite as a secure backup.
+
+## version 4.20130920
+
+This release is the first to support fully encrypted git repositories
+stored on removable drives. This can be set up easily using the webapp.
+
+## version 4.20130909
+
+This release fixes a crash that could occur when using XMPP with the
+assitant. It has only been seen on OS X so far. The bug is not believed to
+be explitable, but upgrading is still recommended.
+
## version 4.20130802
This release fixes several bugs, including a reversion introduced in the last
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_4_978fab3cd165b4ca245e32fc48cf0970._comment b/doc/assistant/remote_sharing_walkthrough/comment_4_978fab3cd165b4ca245e32fc48cf0970._comment
new file mode 100644
index 000000000..ab0b19160
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_4_978fab3cd165b4ca245e32fc48cf0970._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 4"
+ date="2013-11-12T18:18:16Z"
+ content="""
+You can easily use a removable drive as a transfer repository to sync two computers that have no network connection. Just use the webapp to add the drive on one computer. The drive will be set up as a transfer repository by default. The webapp will automatically start copying all your files to it. Then you can disconnect the drive, bring it to the other computer, and repeat the process. Everything from the first computer will then sync over from the drive to the second computer. And repeat moving the drive back and forth to keep things in sync.
+"""]]
diff --git a/doc/assistant/remote_sharing_walkthrough/comment_4_d7e879f7b098964040df2e27a18eda72._comment b/doc/assistant/remote_sharing_walkthrough/comment_4_d7e879f7b098964040df2e27a18eda72._comment
new file mode 100644
index 000000000..71f57e9b3
--- /dev/null
+++ b/doc/assistant/remote_sharing_walkthrough/comment_4_d7e879f7b098964040df2e27a18eda72._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkXtBdMgE1d9nCz2iBc4f85xh4izZ_auU"
+ nickname="Ulrich"
+ subject="Using a portable drive as another transfer device?"
+ date="2013-11-12T16:52:12Z"
+ content="""
+I try to understand how to setup git-annex for the following use case:
+
+Two computers, that are paired via remote sharing, using some cloud repository for transfer, and a local NAS for backups.
+
+These two computers are sometimes in the same network, sometimes in different networks, and sometimes even without network at all. From what I read, it should be possible to bypass the cloud when these two machines are on the same network, which sounds great.
+
+Would it be possible to use a portable drive as \"another link\" between these two computers that can be used to sync them even if there is no network between them?
+
+And as you write, if the pairing has been set up manually, then everything is fine - so could it be that it is really easy and only necessary to setup the git-annex on the local drive as an additional remote on both (or only one?) machine?
+
+thanks for any insight!
+"""]]
diff --git a/doc/assistant/repairrepository.png b/doc/assistant/repairrepository.png
new file mode 100644
index 000000000..d49ea9d95
--- /dev/null
+++ b/doc/assistant/repairrepository.png
Binary files differ
diff --git a/doc/assistant/repoinfo.png b/doc/assistant/repoinfo.png
new file mode 100644
index 000000000..d43ffc9f9
--- /dev/null
+++ b/doc/assistant/repoinfo.png
Binary files differ
diff --git a/doc/assistant/rsync.net.encryption.png b/doc/assistant/rsync.net.encryption.png
new file mode 100644
index 000000000..ec751d10d
--- /dev/null
+++ b/doc/assistant/rsync.net.encryption.png
Binary files differ
diff --git a/doc/backends.mdwn b/doc/backends.mdwn
index 4e9776ff0..79bacd68e 100644
--- a/doc/backends.mdwn
+++ b/doc/backends.mdwn
@@ -14,13 +14,15 @@ can use different ones for different files.
lead to better deduplication but can confuse some programs.
* `WORM` ("Write Once, Read Many") This assumes that any file with
the same basename, size, and modification time has the same content.
- This is the the least expensive backend, recommended for really large
+ This is the least expensive backend, recommended for really large
files or slow systems.
* `SHA512`, `SHA512E` -- Best currently available hash, for the very paranoid.
* `SHA1`, `SHA1E` -- Smaller hash than `SHA256` for those who want a checksum
but are not concerned about security.
* `SHA384`, `SHA384E`, `SHA224`, `SHA224E` -- Hashes for people who like
unusual sizes.
+* `SKEIN512`, `SKEIN256` -- [Skein hash](http://en.wikipedia.org/wiki/Skein_hash),
+ a well-regarded SHA3 hash competition finalist.
The `annex.backends` git-config setting can be used to list the backends
git-annex should use. The first one listed will be used by default when
diff --git a/doc/backends/comment_4_46591a3ba888fb686b1b319b80ca2c22._comment b/doc/backends/comment_4_46591a3ba888fb686b1b319b80ca2c22._comment
new file mode 100644
index 000000000..94f25e996
--- /dev/null
+++ b/doc/backends/comment_4_46591a3ba888fb686b1b319b80ca2c22._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmTho3mActvetF1iQdmui6gH1t6WE6c284"
+ nickname="Michael"
+ subject="SHA256e"
+ date="2013-10-30T02:00:45Z"
+ content="""
+I'd really like to have a SHA256e backend -- same as SHA256E but making sure that extensions of the files in .git/annex are converted to lower case. I normally try to convert filenames from cameras etc to lower case, but not all people that I share annex with do so consistently.
+In my use case, I need to be able to find duplicates among files and .jpg vs .JPG throws git annex dedup off. Otherwise E backends are superior to non-E for me. Thanks, Michael.
+"""]]
diff --git a/doc/backends/comment_5_2210c7ff2d5812fb3b778ac172291656._comment b/doc/backends/comment_5_2210c7ff2d5812fb3b778ac172291656._comment
new file mode 100644
index 000000000..2a205604c
--- /dev/null
+++ b/doc/backends/comment_5_2210c7ff2d5812fb3b778ac172291656._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWBvsZvSsAL8P2ye3F0OBStjFCVnOImzM"
+ nickname="Jarno"
+ subject="Non-E backend drawbacks?"
+ date="2013-10-30T21:25:00Z"
+ content="""
+The page states \"[non-E backends] can confuse some programs\". I like the ideal simplicity and recoverability of pure checksum backends but \"confusion\" sounds a bit worrying. Any practical examples of these problems to help me choose?
+"""]]
diff --git a/doc/backends/comment_6_82f239b58680a2681bd8074c7ef9584d._comment b/doc/backends/comment_6_82f239b58680a2681bd8074c7ef9584d._comment
new file mode 100644
index 000000000..cbd4682ab
--- /dev/null
+++ b/doc/backends/comment_6_82f239b58680a2681bd8074c7ef9584d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 6"
+ date="2013-11-01T15:47:26Z"
+ content="""
+Some examples of problems with the raw SHA backends include, IIRC, calibre, and many programs on OSX. These programs look at the extension of the filename the symlink points at.
+"""]]
diff --git a/doc/bare_repositories.mdwn b/doc/bare_repositories.mdwn
index 86652792b..975a638b8 100644
--- a/doc/bare_repositories.mdwn
+++ b/doc/bare_repositories.mdwn
@@ -31,7 +31,7 @@ Here is a quick example of how to set this up, using `origin` as the remote name
On the server:
git init --bare bare-annex.git
- git annex init origin
+ cd bare-annex.git && git annex init origin
Now configure the remote and do the initial push:
@@ -39,7 +39,7 @@ Now configure the remote and do the initial push:
git remote add origin example.com:bare-annex.git
git push origin master git-annex
-Now `git annex status` should show the configured bare remote. If it does not, you may have to pull from the remote first (older versions of `git-annex`)
+Now `git annex info` should show the configured bare remote. If it does not, you may have to pull from the remote first (older versions of `git-annex`)
If you wish to configure git such that you can push/pull without arguments, set the upstream branch:
diff --git a/doc/bugs/400_mode_leakage.mdwn b/doc/bugs/400_mode_leakage.mdwn
new file mode 100644
index 000000000..63f0fb11d
--- /dev/null
+++ b/doc/bugs/400_mode_leakage.mdwn
@@ -0,0 +1,25 @@
+git-annex tends to preserve files that are added to an annex with
+a mode such as 400. (Happens to me sometimes with email attachments.)
+As these files are rsynced around, and end up on eg, a
+publically visible repo with a webserver frontend, or a repo that is
+acessible to a whole group of users, they will not be readable.
+
+I think it would make sense for git-annex to normalize file permissions
+when adding them. Of course, there's some tension here with generally
+storing file metadata when possible. Perhaps the normalization should only
+ensure that group and other have read access?
+
+(Security: We can assume that a repo that is not intended to be public is
+in a 700 directory. And since git-annex cannot preserve file modes when
+files transit through a special remote, using modes to limit access to
+individual files is not wise.)
+
+--[[Joey]]
+
+> Revisiting this, git-annex already honors core.sharedrepository settings,
+> so I just needed to set it to `world` to allow everyone to read.
+>
+> There was a code path in direct mode where that didn't work; fixed that.
+>
+> [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/Adding_unencrypted_repo_on_drive_in_webapp_gives_internal_server_error__.mdwn b/doc/bugs/Adding_unencrypted_repo_on_drive_in_webapp_gives_internal_server_error__.mdwn
new file mode 100644
index 000000000..ab98c631e
--- /dev/null
+++ b/doc/bugs/Adding_unencrypted_repo_on_drive_in_webapp_gives_internal_server_error__.mdwn
@@ -0,0 +1,69 @@
+### Please describe the problem.
+
+"Internal Server Error This git repository is encrypted with a GnuPG key that you do not have" after having asked *not* to use encryption.
+
+### What steps will reproduce the problem?
+
+Here's what I did:
+
+On Ubuntu 10.4, install git-annex according to http://git-annex.branchable.com/install/Ubuntu/ then:
+
+$ git-annex webapp
+
+Create repo at suggested path Desktop/annex/.
+Add a file to that dir. Create subdir, move file there.
+Select "Add another repository" in webapp, "Removable drive", select external usb drive, leave suggested path "annex", "Use this drive", "Do not encrypt repository".
+
+-> shows "Internal Server Error
+This git repository is encrypted with a GnuPG key that you do not have.
+git-annex version 4.20131002"
+
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version 4.20131002, Ubuntu 12.04.3 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 wit[2013-10-19 00:33:55 BST] main: starting assistant version 4.20131002
+(Recording state in git...)
+(scanning...) [2013-10-19 00:33:55 BST] Watcher: Performing startup scan
+(started...)
+
+ The installed version of git is too old for .gitignores to be honored by git-annex.
+[2013-10-19 00:35:56 BST] Committer: Adding Git Annex..ation.odt
+add Git Annex installation.odt (checksum...) [2013-10-19 00:35:57 BST] Committer: Committing changes to git
+[2013-10-19 00:37:38 BST] Committer: Adding Git Annex..ation.odt
+[2013-10-19 00:37:38 BST] Committer: Committing changes to git
+git: 'remote-gcrypt' is not a git command. See 'git --help'.
+ok
+(Recording state in git...)
+(Recording state in git...)
+ok
+(Recording state in git...)
+(Recording state in git...)
+19/Oct/2013:00:38:54 +0100 [Error#yesod-core] This git repository is encrypted with a GnuPG key that you do not have. @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+git: 'remote-gcrypt' is not a git command. See 'git --help'.
+19/Oct/2013:00:39:09 +0100 [Error#yesod-core] This git repository is encrypted with a GnuPG key that you do not have. @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+.........+++++
+
+Not enough random bytes available. Please do some other work to give
+the OS a chance to collect more entropy! (Need 66 more bytes)
+.............+++++
+gpg: key E0424680 marked as ultimately trusted
+git: 'remote-gcrypt' is not a git command. See 'git --help'.
+19/Oct/2013:00:41:19 +0100 [Error#yesod-core] This git repository is encrypted with a GnuPG key that you do not have. @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+git: 'remote-gcrypt' is not a git command. See 'git --help'.
+19/Oct/2013:00:54:33 +0100 [Error#yesod-core] This git repository is encrypted with a GnuPG key that you do not have. @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+h the git-annex assistant, paste in .git/annex/daemon.log
+
+
+# End of transcript or log.
+"""]]
+
+I'm not at my computer, will check upstream Git later. Sorry if this has been reported before.
+
+> This only occurred when git-remote-gcrypt was not installed.
+> I've fixed the bug. [[done]] --[[Joey]]
diff --git a/doc/bugs/Android_v4.3_-_Framework_18_-___34__Git_annex_webapp_CANNOT_LINK_EXECUTABLE:_git-annex_invalid_R__95__ARM__95__COPY_relocation_against_DT__95__SYMBOLIC_shared_library_libc.so___40__built_with_-Bsymbolic__63____41__.mdwn b/doc/bugs/Android_v4.3_-_Framework_18_-___34__Git_annex_webapp_CANNOT_LINK_EXECUTABLE:_git-annex_invalid_R__95__ARM__95__COPY_relocation_against_DT__95__SYMBOLIC_shared_library_libc.so___40__built_with_-Bsymbolic__63____41__.mdwn
deleted file mode 100644
index 0f2c4305d..000000000
--- a/doc/bugs/Android_v4.3_-_Framework_18_-___34__Git_annex_webapp_CANNOT_LINK_EXECUTABLE:_git-annex_invalid_R__95__ARM__95__COPY_relocation_against_DT__95__SYMBOLIC_shared_library_libc.so___40__built_with_-Bsymbolic__63____41__.mdwn
+++ /dev/null
@@ -1,22 +0,0 @@
-### Please describe the problem.
-Git-annex v20130802 abends on Android v4.3 framework 18
-
-Android v4.3 - Framework 18 - "Git annex webapp CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?)
-
-### What steps will reproduce the problem?
-Start git-annex
-git-annex webapp (auto launch)
-
-### What version of git-annex are you using? On what operating system?
-Git-annex v20130802 abends on Android v4.3 framework 18
-Android app v1.00.52
-
-### 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.
-"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux.mdwn b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux.mdwn
new file mode 100644
index 000000000..a2f79aa6c
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux.mdwn
@@ -0,0 +1,75 @@
+### Please describe the problem.
+
+I am experiencing a weird issue with any install I've had on this one (and only) ArchLinux machine: all of aur/git-annex 4.20130516-1, aur/git-annex-bin-4.20130909-1, aur/git-annex-standalone-4.20130909-1 and a Cabal install just stall when trying to create the initial Git annex repo in the webapp.
+
+When started, it offers me to create the annex in ~/annex/ or ~/Desktop/annex/, where ~ gets turned into /home/USER when I press “Make repository”, but nothing else happens. This is regardless of if that repo exists when I try to create it or start the webapp.
+
+If I start the webapp from an existing annex (now in ~/annex), it seems to work a bit better, but any other remote (SSH) server that I try to add fails. I just get a fleeting Bootstrap message box when I click “Check this server”, and nothing in the logs of eithr git annex webapp or the ssh logs of the server.
+
+If an annex exists, but I start the webapp from another directory, it just behaves as if none were found.
+
+Calls to git annex assistant --autostart complain that "Nothing listed in /home/omehani/.config/git-annex/autostart". I have checked the permissions on that directory, and tried deleting it to let git-annex recreate it, which it did, to no avail.
+
+
+### What steps will reproduce the problem?
+
+Install any of the git-annex packages available from AUR
+
+### What version of git-annex are you using? On what operating system?
+
+* up-to-date ArchLinux, Linux cancey 3.10.10-1-ARCH #1 SMP PREEMPT Fri Aug 30 11:30:06 CEST 2013 x86_64 GNU/Linux
+* aur/git-annex 4.20130516-1, aur/git-annex-bin-4.20130909-1, aur/git-annex-standalone-4.20130909-1 or through Cabal (on 2013-09-12)
+
+### Please provide any additional information below.
+
+The following is the output of webapp --debug. Nothing actually appears when trying to add/edit a repo.
+
+[[!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
+
+~/annex (master)$ git annex webapp --debug
+[2013-09-16 10:26:55 EST] read: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","show-ref","git-annex"]
+[2013-09-16 10:26:55 EST] read: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","show-ref","--hash","refs/heads/git-annex"]
+[2013-09-16 10:26:55 EST] read: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","log","refs/heads/git-annex..27c891f84f6ea7a10c68c0dd696ab84d88ef0cec","--oneline","-n1"]
+[2013-09-16 10:26:55 EST] read: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","log","refs/heads/git-annex..d0a1cb518045af01b443694aa2cd9af6386de38a","--oneline","-n1"]
+[2013-09-16 10:26:55 EST] read: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","log","refs/heads/git-annex..3ff23e23d74ace008b03143120e84f07e52ed8ee","--oneline","-n1"]
+[2013-09-16 10:26:55 EST] chat: git ["--git-dir=/home/omehani/annex/.git","--work-tree=/home/omehani/annex","cat-file","--batch"]
+[2013-09-16 10:26:55 EST] logging to /home/omehani/annex/.git/annex/daemon.log
+[2013-09-16 10:26:55 EST] logging to /home/omehani/annex/.git/annex/daemon.log
+Launching web browser on file:///home/omehani/annex/.git/annex/webapp.html
+START /usr/lib/firefox/firefox "/home/omehani/annex/.git/annex/webapp.html"
+
+(process:2699): GLib-CRITICAL **: g_slice_set_config: assertion `sys_page_size == 0' failed
+
+
+# End of transcript or log.
+"""]]
+
+Running git annex from a different directory.
+[[!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 webapp --debug
+Launching web browser on file:///tmp/webapp3934.html
+START /usr/lib/firefox/firefox "/tmp/webapp3934.html"
+
+(process:4008): GLib-CRITICAL **: g_slice_set_config: assertion `sys_page_size == 0' failed
+
+# End of transcript or log.
+"""]]
+
+Trying the autostart:
+[[!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 assistant --autostart --debug
+git-annex: Nothing listed in /home/omehani/.config/git-annex/autostart
+
+
+# End of transcript or log.
+"""]]
+
+> workaround is in place [[done]] --[[Joey]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_10_ec4a7388ea7106a953f599b664b37f1d._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_10_ec4a7388ea7106a953f599b664b37f1d._comment
new file mode 100644
index 000000000..b0d0bdd55
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_10_ec4a7388ea7106a953f599b664b37f1d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 10"
+ date="2013-10-23T03:30:17Z"
+ content="""
+Right, I actually have 4.20131023-g9898139. This makes more sense.
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_1_6a60c23850a5e2a7bba355e1317abc69._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_1_6a60c23850a5e2a7bba355e1317abc69._comment
new file mode 100644
index 000000000..ed9ace976
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_1_6a60c23850a5e2a7bba355e1317abc69._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 1"
+ date="2013-09-16T01:27:14Z"
+ content="""
+The version with which the following tests were run (installed with Cabal)
+
+[[!format sh \"\"\"
+git-annex version: 4.20130827
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus DNS
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_2_90b6ed232b2917b9fe041532284e1212._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_2_90b6ed232b2917b9fe041532284e1212._comment
new file mode 100644
index 000000000..703be9a84
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_2_90b6ed232b2917b9fe041532284e1212._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 2"
+ date="2013-09-19T17:12:39Z"
+ content="""
+Please send the content of the file /home/omehani/annex/.git/annex/daemon.log
+
+It would also help if you could better describe what happens. Perhaps make a screenshot?
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_3_5a89d79395d96c43d7d8a6fd9dc275f1._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_3_5a89d79395d96c43d7d8a6fd9dc275f1._comment
new file mode 100644
index 000000000..39f0f39b8
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_3_5a89d79395d96c43d7d8a6fd9dc275f1._comment
@@ -0,0 +1,248 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 3"
+ date="2013-09-30T01:29:50Z"
+ content="""
+This is when having manually created the local annex, and trying to add a remote one. Surprisingly, I cannot find any reference to the remote server's address or username...
+
+ [2013-09-30 11:14:38 EST] main: starting assistant version 4.20130827
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"show-ref\",\"git-annex\"]
+ [2013-09-30 11:14:38 EST] read: xdg-open [\"file:///home/USERNAME/annex/.git/annex/webapp.html\"]
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"log\",\"refs/heads/git-annex..9d87789505628a2da8347574cc600e358ff76107\",\"--oneline\",\"-n1\"]
+ [2013-09-30 11:14:38 EST] Merger: watching /home/USERNAME/annex/.git/refs
+ [2013-09-30 11:14:38 EST] TransferWatcher: watching for transfers
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"ls-tree\",\"-z\",\"--\",\"refs/heads/git-annex\",\"uuid.log\",\"remote.log\",\"trust.log\",\"group.log\",\"preferred-content.log\"]
+
+ No known network monitor available through dbus; falling back to polling
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"ls-tree\",\"-z\",\"--\",\"refs/heads/git-annex\",\"uuid.log\",\"remote.log\",\"trust.log\",\"group.log\",\"preferred-content.log\"]
+ (scanning...) [2013-09-30 11:14:38 EST] Watcher: Performing startup scan
+ [2013-09-30 11:14:38 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"ls-files\",\"--deleted\",\"-z\",\"--\",\"/home/USERNAME/annex\"]
+ (started...) [2013-09-30 11:14:38 EST] Watcher: watching .
+ [2013-09-30 11:14:38 EST] MountWatcher: Started DBUS service org.gtk.Private.UDisks2VolumeMonitor to monitor mount events.
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET / Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"show-ref\",\"git-annex\"]
+ [2013-09-30 11:14:39 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-30 11:14:39 EST] read: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"log\",\"refs/heads/git-annex..9d87789505628a2da8347574cc600e358ff76107\",\"--oneline\",\"-n1\"]
+ [2013-09-30 11:14:39 EST] chat: git [\"--git-dir=/home/USERNAME/annex/.git\",\"--work-tree=/home/USERNAME/annex\",\"cat-file\",\"--batch\"]
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/jquery.ui.core.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/jquery.ui.widget.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/jquery.ui.mouse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/jquery.ui.sortable.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /notifier/repolist/RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /notifier/transfers Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /sidebar/NotificationId%200 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%200)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:39 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%200)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:40 EST] 127.0.0.1 GET /sidebar/NotificationId%200 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:40 EST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:40 EST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:40 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:14:40 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /config Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /sidebar/NotificationId%200 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%200)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:16 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:17 EST] 127.0.0.1 GET /sidebar/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:17 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:17 EST] 127.0.0.1 GET /sidebar/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /config/addrepository Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/jquery.ui.core.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/jquery.ui.widget.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/jquery.ui.mouse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/jquery.ui.sortable.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:19 EST] 127.0.0.1 GET /notifier/repolist/RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:20 EST] 127.0.0.1 GET /sidebar/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:20 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%201)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:20 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%201)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:20 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:20 EST] 127.0.0.1 GET /sidebar/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /config/repository/add/ssh Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%201)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /sidebar/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:31 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /sidebar/NotificationId%203 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:32 EST] 127.0.0.1 GET /sidebar/NotificationId%203 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET / Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/jquery.ui.core.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/jquery.ui.widget.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/jquery.ui.mouse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/jquery.ui.sortable.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /notifier/repolist/RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /notifier/transfers Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /sidebar/NotificationId%204 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%202)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /transfers/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%202)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /transfers/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:37 EST] 127.0.0.1 GET /sidebar/NotificationId%204 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /about Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /sidebar/NotificationId%204 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /transfers/NotificationId%202 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%202)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20True%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /sidebar/NotificationId%205 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:47 EST] 127.0.0.1 GET /sidebar/NotificationId%205 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /config Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /sidebar/NotificationId%206 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:50 EST] 127.0.0.1 GET /sidebar/NotificationId%206 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /config/addrepository Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/jquery.ui.widget.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/jquery.ui.mouse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/jquery.ui.core.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/jquery.ui.sortable.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /notifier/repolist/RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%203)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /sidebar/NotificationId%207 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:51 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%203)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:52 EST] 127.0.0.1 GET /sidebar/NotificationId%207 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /config/repository/add/ssh Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /repolist/RepoListNotificationId%20(NotificationId%203)%20(RepoSelector%20%7BonlyCloud%20=%20False,%20onlyConfigured%20=%20False,%20includeHere%20=%20True,%20nudgeAddMore%20=%20False%7D) Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /sidebar/NotificationId%207 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /sidebar/NotificationId%208 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:15:56 EST] 127.0.0.1 GET /sidebar/NotificationId%208 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 POST /config/repository/add/ssh Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /sidebar/NotificationId%208 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /sidebar/NotificationId%209 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:23 EST] 127.0.0.1 GET /sidebar/NotificationId%209 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 POST /config/repository/add/ssh Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /sidebar/NotificationId%209 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:44 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:45 EST] 127.0.0.1 GET /sidebar/NotificationId%2010 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:16:45 EST] 127.0.0.1 GET /sidebar/NotificationId%2010 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /shutdown Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/css/bootstrap.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/css/bootstrap-responsive.css Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/jquery.full.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/js/bootstrap-dropdown.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/js/bootstrap-modal.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/js/bootstrap-collapse.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/longpolling.js Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/img/glyphicons-halflings.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /static/img/glyphicons-halflings-white.png Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /notifier/sidebar Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /sidebar/NotificationId%2011 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:01 EST] 127.0.0.1 GET /sidebar/NotificationId%2011 Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+ [2013-09-30 11:17:02 EST] 127.0.0.1 GET /static/favicon.ico Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
+
+
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_4_cdd26c71875428dbe3c100944a443d3f._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_4_cdd26c71875428dbe3c100944a443d3f._comment
new file mode 100644
index 000000000..4ee062a80
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_4_cdd26c71875428dbe3c100944a443d3f._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 4"
+ date="2013-09-30T01:31:26Z"
+ content="""
+Hum, I'm not allowed to upload images:
+ git-annex-webapp1.png prohibited by allowed_attachments (user is not an admin)
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_5_76242f5d6c815acd5bd58213bd8bb0fe._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_5_76242f5d6c815acd5bd58213bd8bb0fe._comment
new file mode 100644
index 000000000..28a0f7cc4
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_5_76242f5d6c815acd5bd58213bd8bb0fe._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 5"
+ date="2013-09-30T16:13:20Z"
+ content="""
+I see a lot of activity, which looks like you started up the webapp and it ran displaying stuff for some minutes. I see that you clicked on pages to eg, add a ssh repository.
+
+So, what then do you mean by saying it stalls? You have still not described whatever problem you are having.
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_6_10852171c0207ca61ea6df1082107353._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_6_10852171c0207ca61ea6df1082107353._comment
new file mode 100644
index 000000000..452a898f6
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_6_10852171c0207ca61ea6df1082107353._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 6"
+ date="2013-10-04T05:14:16Z"
+ content="""
+Right. By “it stalls”, I mean I get redirected to the same dialog page (either the one asking for the path to the repo to create, or the one asking for the details of the remote to add) that I just validated, rather than going further in the process.
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_7_73e8a5696709f8154e63693ba5e569c3._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_7_73e8a5696709f8154e63693ba5e569c3._comment
new file mode 100644
index 000000000..b6df85923
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_7_73e8a5696709f8154e63693ba5e569c3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 7"
+ date="2013-10-14T16:18:01Z"
+ content="""
+I just ran into this problem myself. Some investigating shows it is a problem with Yesod's XSRF token. Apparently yesod is not seeing the _token, or is seeing one it does not like. However, I verified in chromium inspector that the form post was including the token with the same value used on the page. Also, it would intermittently accept the form, if I kept posting it over and over again.
+
+It seems this must be a bug in yesod, or on something with how I'm using yesod, or possibly in deeper layers like WAI not seeing the form post include the token, but I have not been able to figure out what. As a workaround, since git-annex webapp does its own authentication and only listens to localhost, and so does not actually need XSRF protection, I am going to change it to bypass that.
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_8_392fc344e5833b0eb665fcd38f956b7a._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_8_392fc344e5833b0eb665fcd38f956b7a._comment
new file mode 100644
index 000000000..37acd5e9a
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_8_392fc344e5833b0eb665fcd38f956b7a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 8"
+ date="2013-10-23T03:00:58Z"
+ content="""
+I just tried installing git-annex using Cabal today, but only got git-annex-4.20131002, even from source, which seems to predate your last comment, and no other branch seem to provide the yesod fix. Should I get the source from somewhere else than kitenet to try this out (if you think it is in shape to be tested)?
+"""]]
diff --git a/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_9_9f0fc19a7fcaf7a5827e59e1495cf8c9._comment b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_9_9f0fc19a7fcaf7a5827e59e1495cf8c9._comment
new file mode 100644
index 000000000..1e7aa897b
--- /dev/null
+++ b/doc/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/comment_9_9f0fc19a7fcaf7a5827e59e1495cf8c9._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 9"
+ date="2013-10-23T03:03:30Z"
+ content="""
+Strike that. It actually works. I could create the ~/annex store, and adding a remote also seems to work (I'm on a hotel Wi-Fi at the moment, so I fear the ssh connection will fail, but nothing to do with git-annex).
+"""]]
diff --git a/doc/bugs/Build_error_on_Linux.mdwn b/doc/bugs/Build_error_on_Linux.mdwn
new file mode 100644
index 000000000..af560788a
--- /dev/null
+++ b/doc/bugs/Build_error_on_Linux.mdwn
@@ -0,0 +1,29 @@
+### Please describe the problem.
+Building on Linux, with a particular combination of flags, failed due to missing `async`.
+
+### What steps will reproduce the problem?
+1. Configure with the following flag combination
+
+ cryptohash -quvi -feed tdfa -testsuite -android production -dns -xmpp -pairing -webapp -assistant dbus inotify -webdav s3
+
+2. Attempt to build and you'll get an error on line 16 of `Utility/Batch.hs` because `Control.Concurrent.Async` isn't available.
+
+### What version of git-annex are you using? On what operating system?
+Version 4.20131024 on Linux
+
+### Please provide any additional information below.
+
+This is the patch I applied to `git-annex.cabal`:
+
+ CPP-Options: -DWITH_KQUEUE
+ C-Sources: Utility/libkqueue.c
+
+ + if os(linux)
+ + Build-Depends: async
+ +
+ if os(linux) && flag(Dbus)
+ Build-Depends: dbus (>= 0.10.3)
+ CPP-Options: -DWITH_DBUS
+
+> Feel async is core enough it should depend on it unconditionally.
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_2_38696178e658d1d32deec37dbea66a3d._comment b/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_2_38696178e658d1d32deec37dbea66a3d._comment
new file mode 100644
index 000000000..fa9bd3dd3
--- /dev/null
+++ b/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_2_38696178e658d1d32deec37dbea66a3d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnXm4VZC7ekVOXHGKjBObojiHB2E1kmMgA"
+ nickname="Leonardo"
+ subject="comment 2"
+ date="2013-08-11T21:21:56Z"
+ content="""
+Files with colon are not allowed in windows, they are interpreted as absolute path. The fact that you can checkout them \"fine\" (actually, their name get truncated to whatever was before the colon) using cygwin's GIT implementation is to be interpreted as a bug in cygwin's GIT in my opinion. I suggest renaming them before cygwin get fixed.
+"""]]
diff --git a/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_3_f34d996827f5e7662bec409cbcce961b._comment b/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_3_f34d996827f5e7662bec409cbcce961b._comment
new file mode 100644
index 000000000..14cfa2686
--- /dev/null
+++ b/doc/bugs/Can__39__t_clone_on_Windows_because_some_filenames_have_a_colon_in_them/comment_3_f34d996827f5e7662bec409cbcce961b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 3"
+ date="2013-08-24T19:27:57Z"
+ content="""
+Leonardo, you made me boot up my windows machine just to check if cygwin git truncated files at the colon. It does not.
+
+AFAIK, Cygwin transliterates colons to another unicode character or something like that. I would be highly surprised if the Cygwin people consider this feature to be a bug.
+
+Since you need Cygwin to build git-annex on Windows anyway (though not to run it!), this remains WONTFIX.
+"""]]
diff --git a/doc/bugs/Can__39__t_start_on_Cyanogenmod_10.2_nightly.mdwn b/doc/bugs/Can__39__t_start_on_Cyanogenmod_10.2_nightly.mdwn
new file mode 100644
index 000000000..c28794622
--- /dev/null
+++ b/doc/bugs/Can__39__t_start_on_Cyanogenmod_10.2_nightly.mdwn
@@ -0,0 +1,158 @@
+### Please describe the problem.
+The android app won't start on Cyanogenmod 10.2. Not sure if this is cyanogenmod specific or if it is because the underlying android is now version 4.3
+
+### What steps will reproduce the problem?
+Install the apk and start the program
+
+### What version of git-annex are you using? On what operating system?
+A 7 day old nightly as of this post(can't get specific number since it won't run)
+
+### Please provide any additional information below.
+
+Tested this on both a samsung galaxy S and a samsung galaxy note 2. With different nightlies of cyanogenmod 10.2
+
+[[!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
+
+Falling back to hardcoded app location; cannot find expected files in /data/app-lib
+git annex webapp
+u0_a115@android:/sdcard/git-annex.home $ git annex webapp
+CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?)
+1|u0_a115@android:/sdcard/git-annex.home $
+
+---
+
+
+cat git-annex-install.log
+
+Installation starting to /data/data/ga.androidterm
+34c88243533e9b0a725ebe33533d990e628dc44b
+installing busybox
+installing git-annex
+installing git-shell
+installing git-upload-pack
+installing git
+installing gpg
+installing rsync
+installing ssh
+installing ssh-keygen
+linking ./libexec/git-core/git-config to git
+linking ./libexec/git-core/git-fetch to git
+linking ./libexec/git-core/git-fsck to git
+linking ./libexec/git-core/git-unpack-file to git
+linking ./libexec/git-core/git-get-tar-commit-id to git
+linking ./libexec/git-core/git-fmt-merge-msg to git
+linking ./libexec/git-core/git-push to git
+linking ./libexec/git-core/git-for-each-ref to git
+linking ./libexec/git-core/git-pack-redundant to git
+linking ./libexec/git-core/git-mv to git
+linking ./libexec/git-core/git-ls-remote to git
+linking ./libexec/git-core/git-prune-packed to git
+linking ./libexec/git-core/git-apply to git
+linking ./libexec/git-core/git-check-ignore to git
+linking ./libexec/git-core/git-log to git
+linking ./libexec/git-core/git-cherry-pick to git
+linking ./libexec/git-core/git-diff-files to git
+linking ./libexec/git-core/git-commit-tree to git
+linking ./libexec/git-core/git-index-pack to git
+linking ./libexec/git-core/git-reflog to git
+linking ./libexec/git-core/git-merge-index to git
+linking ./libexec/git-core/git-column to git
+linking ./libexec/git-core/git-checkout-index to git
+linking ./libexec/git-core/git-diff-index to git
+linking ./libexec/git-core/git-count-objects to git
+linking ./libexec/git-core/git-fast-export to git
+linking ./libexec/git-core/git-fetch-pack to git
+linking ./libexec/git-core/git-merge-file to git
+linking ./libexec/git-core/git-init to git
+linking ./libexec/git-core/git-remote to git
+linking ./libexec/git-core/git-init-db to git
+linking ./libexec/git-core/git-ls-tree to git
+linking ./libexec/git-core/git-merge-subtree to git
+linking ./libexec/git-core/git-rev-parse to git
+linking ./libexec/git-core/git-bundle to git
+linking ./libexec/git-core/git-prune to git
+linking ./libexec/git-core/git-peek-remote to git
+linking ./libexec/git-core/git-tar-tree to git
+linking ./libexec/git-core/git-describe to git
+linking ./libexec/git-core/git-update-index to git
+linking ./libexec/git-core/git to git
+linking ./libexec/git-core/git-revert to git
+linking ./libexec/git-core/git-show-ref to git
+linking ./libexec/git-core/git-upload-archive to git
+linking ./libexec/git-core/git-add to git
+linking ./libexec/git-core/git-verify-tag to git
+linking ./libexec/git-core/git-format-patch to git
+linking ./libexec/git-core/git-show-branch to git
+linking ./libexec/git-core/git-remote-fd to git
+linking ./libexec/git-core/git-pack-refs to git
+linking ./libexec/git-core/git-replace to git
+linking ./libexec/git-core/git-pack-objects to git
+linking ./libexec/git-core/git-notes to git
+linking ./libexec/git-core/git-tag to git
+linking ./libexec/git-core/git-var to git
+linking ./libexec/git-core/git-help to git
+linking ./libexec/git-core/git-gc to git
+linking ./libexec/git-core/git-check-ref-format to git
+linking ./libexec/git-core/git-shortlog to git
+linking ./libexec/git-core/git-stage to git
+linking ./libexec/git-core/git-mktree to git
+linking ./libexec/git-core/git-merge-recursive to git
+linking ./libexec/git-core/git-grep to git
+linking ./libexec/git-core/git-clean to git
+linking ./libexec/git-core/git-merge-base to git
+linking ./libexec/git-core/git-repo-config to git
+linking ./libexec/git-core/git-hash-object to git
+linking ./libexec/git-core/git-read-tree to git
+linking ./libexec/git-core/git-rm to git
+linking ./libexec/git-core/git-fsck-objects to git
+linking ./libexec/git-core/git-ls-files to git
+linking ./libexec/git-core/git-mktag to git
+linking ./libexec/git-core/git-stripspace to git
+linking ./libexec/git-core/git-mailsplit to git
+linking ./libexec/git-core/git-diff-tree to git
+linking ./libexec/git-core/git-merge-ours to git
+linking ./libexec/git-core/git-cherry to git
+linking ./libexec/git-core/git-checkout to git
+linking ./libexec/git-core/git-rev-list to git
+linking ./libexec/git-core/git-write-tree to git
+linking ./libexec/git-core/git-update-ref to git
+linking ./libexec/git-core/git-blame to git
+linking ./libexec/git-core/git-archive to git
+linking ./libexec/git-core/git-update-server-info to git
+linking ./libexec/git-core/git-merge-tree to git
+linking ./libexec/git-core/git-show to git
+linking ./libexec/git-core/git-remote-ext to git
+linking ./libexec/git-core/git-merge to git
+linking ./libexec/git-core/git-name-rev to git
+linking ./libexec/git-core/git-bisect--helper to git
+linking ./libexec/git-core/git-clone to git
+linking ./libexec/git-core/git-symbolic-ref to git
+linking ./libexec/git-core/git-send-pack to git
+linking ./libexec/git-core/git-commit to git
+linking ./libexec/git-core/git-mailinfo to git
+linking ./libexec/git-core/git-credential to git
+linking ./libexec/git-core/git-diff to git
+linking ./libexec/git-core/git-patch-id to git
+linking ./libexec/git-core/git-rerere to git
+linking ./libexec/git-core/git-branch to git
+linking ./libexec/git-core/git-reset to git
+linking ./libexec/git-core/git-receive-pack to git
+linking ./libexec/git-core/git-verify-pack to git
+linking ./libexec/git-core/git-unpack-objects to git
+linking ./libexec/git-core/git-check-attr to git
+linking ./libexec/git-core/git-whatchanged to git
+linking ./libexec/git-core/git-status to git
+linking ./libexec/git-core/git-cat-file to git
+linking ./libexec/git-core/git-annotate to git
+linking ./bin/git-upload-archive to git
+linking ./bin/git-receive-pack to git
+linking ./libexec/git-core/git-shell to git-shell
+linking ./libexec/git-core/git-upload-pack to git-upload-pack
+Installation complete
+
+# End of transcript or log.
+"""]]
+
+> [[dup|done]] of [[git-annex_broken_on_Android_4.3]].--[[Joey]]
diff --git a/doc/bugs/Conflicting_archive_descriptions.mdwn b/doc/bugs/Conflicting_archive_descriptions.mdwn
new file mode 100644
index 000000000..832daa4ea
--- /dev/null
+++ b/doc/bugs/Conflicting_archive_descriptions.mdwn
@@ -0,0 +1,16 @@
+This is confusing:
+
+"Next we come to the archive repositories.The archive repositories coordinate together, so that each file is archived in only one place. **When you move files into a folder named "archive"**, they'll be moved to an archive repository, and removed from all your client repositories. This is handy if you have old files you don't need anymore, but want to keep archived for later. When you copy or move a file out of an "archive" folder, it'll be retrieved from the archive repository."
+
+"The small archive repositories are like other archive repositories, but smaller. While archive repositories normally accumulate every file they can, small archive repositories only accumulate files **once you put them in an "archive" directory.**"
+
+Based upon those descriptions, I don't know what the difference is.
+
+> Improved wording to not imply that files are only put into archive
+> repositories once the files are moved to archive directories.
+> (Which is how small archive repositories work.)
+>
+> If you're still confused about it, see
+> <http://git-annex.branchable.com/assistant/archival_walkthrough/>
+>
+> [[done]] --[[Joey]]
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
new file mode 100644
index 000000000..de879f522
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too.mdwn
@@ -0,0 +1,33 @@
+### Please describe the problem.
+
+On my raspberry pi, an SSH remote was in /var/lib/store (symlinked with /home/carlo/store), which contained a LVM volume spanning several USB drives. One of the drives got corrupted, which lead to this:
+
+$ cd /home/carlo/store
+$ ls
+Input/Output Error
+
+On my desktop machine, I then had a lot of transfers. After transfer, the file was turned into a symlink.
+
+### What steps will reproduce the problem?
+
+* Create an annex and a remote ssh server.
+* [Simulate a corrupted drive](http://stackoverflow.com/questions/1361518/how-can-i-simulate-a-failed-disk-during-testing) for the remote, creating an input output error.
+* Wait until the annex starts syncing on the desktop machine. If there were no further unidentified causes on my side, the assistant will start transfers that revert files to symlinks.
+
+### What version of git-annex are you using? On what operating system?
+
+Ubuntu 12.04 64bit
+git annex 3.20121017 ([from Ubuntu PPA](https://launchpad.net/~rubiojr/+archive/git-annex))
+
+### 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
+
+Please see [all my daemon.log](http://capocasa.name/daemon.tgz) files.
+
+I noticed the problem yesterday afternoon (Thu 24 Oct).
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_1_80ca50f5305eda71fe32f2b0bc922c34._comment b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_1_80ca50f5305eda71fe32f2b0bc922c34._comment
new file mode 100644
index 000000000..e47cbd327
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_1_80ca50f5305eda71fe32f2b0bc922c34._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-26T19:22:57Z"
+ content="""
+It seems to me that if a subdirectory of the repository is on a corrupted drive, and so it's not possible to list the files on it, this is basically the same as if you'd 'rm -rf' that subdirectory. So when it starts up, the assistant will see that these files are not present, and commit a removal to git.
+
+Then when another machine syncs with that, it would delete the files from its repository too. However, it actually keeps the contents of the files stashed away in `.git/annex`. So to recover from this, all you have to do is `git annex indirect` and `git revert` the commit that deleted the files. All your files would then be available again.
+
+However, what you describe is instead that the assistant chose to drop the content associated with the files, but kept the symlinks for them checked into git.
+I don't understand why it would do that. Can you show the output of running, on the desktop machine:
+
+ git annex whereis $somefile
+ git annex get $somefile
+
+Where $somefile is one of the files that has been reduced to a symlink.
+
+Looking at your logs, they appear to be the logs from the server. The strange thing that appears in one of them is \"git-annex: Not in a git repository.\"
+which was logged around 2013-10-24 20:07:25 CEST. I am not sure, but I think it might have been the rpi git-annex saying that, because there is also \"fatal: '~/store/annex/' does not appear to be a git repository\"
+"""]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_2_e6bc6d1c0eb8c469e9e00b37bbcc9b86._comment b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_2_e6bc6d1c0eb8c469e9e00b37bbcc9b86._comment
new file mode 100644
index 000000000..18959ed68
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_2_e6bc6d1c0eb8c469e9e00b37bbcc9b86._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 2"
+ date="2013-10-27T19:26:42Z"
+ content="""
+Thanks for looking into it and the recover instructions, will recover and post back when I'm back at work. I also have an another indirect mode repo on my home desktop as an extra backup so nothing real bad happened, but it's reassuring data's still there at work.
+
+"""]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_0d0f6b6b46d0153433fead2bbd1bbe64._comment b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_0d0f6b6b46d0153433fead2bbd1bbe64._comment
new file mode 100644
index 000000000..a254b31a8
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_0d0f6b6b46d0153433fead2bbd1bbe64._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 5"
+ date="2013-10-30T15:05:37Z"
+ content="""
+The assistant autorecovered my work repo before I noticed, so it looks like I can't provide the necessary info. There were a bunch of files missing that got re-synced from my home PC.
+
+For what it's worth, I noticed that on my phone, when cutting the internet connection while syncing, the assistant downloaded existing files into placeholder files, and then continued actually downloading files when the network connection was restored.
+
+
+"""]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_6058a22b733cb02126286af950074ed4._comment b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_6058a22b733cb02126286af950074ed4._comment
new file mode 100644
index 000000000..33e85c772
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_5_6058a22b733cb02126286af950074ed4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 5"
+ date="2013-11-03T01:17:39Z"
+ content="""
+I don't understand what you mean by \"The assistant autorecovered my work repo before I noticed\". What repo is the work repo, and how could the assistant \"autorecover\" it, and what did it do?
+
+At this point, I am completely in the dark about whether you're reporting a problem, and what the problem is.
+"""]]
diff --git a/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_6_593a49669e2fadfb91773f8c84fbb031._comment b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_6_593a49669e2fadfb91773f8c84fbb031._comment
new file mode 100644
index 000000000..af31edcf8
--- /dev/null
+++ b/doc/bugs/Corrupted_drive:_Assistant_seems_consider_files_deleted_and_deletes_them_elsewhere_too/comment_6_593a49669e2fadfb91773f8c84fbb031._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 6"
+ date="2013-10-31T10:03:01Z"
+ content="""
+Of course, the autorecovery wouldn't affect the daemon.log from the work machine... so here they are: http://capocasa.name/work-desktop-ubuntu-12.04-daemonlog.tgz
+"""]]
diff --git a/doc/bugs/Could_not_read_from_remote_repository.mdwn b/doc/bugs/Could_not_read_from_remote_repository.mdwn
new file mode 100644
index 000000000..e4f7b9c43
--- /dev/null
+++ b/doc/bugs/Could_not_read_from_remote_repository.mdwn
@@ -0,0 +1,24 @@
+### Please describe the problem.
+
+I've been using git-annex for a few weeks now, and everything was working fine until today. Now, when git-annex goes to sync my files, it will hang for a while, and then display a red box on the left side, saying `! Synced with adam.liter`. So, basically, it doesn't really sync. The logs say that it cannot read from the remote repository, which is set up on box.com and was working just fine until today.
+
+I've tried reconfiguring my jabber account on all my devices with git-annex as well as deleting and remaking the box.com repository, and none of these steps have solved the problem.
+
+### What steps will reproduce the problem?
+
+Making changes to any file located in the repository.
+
+### What version of git-annex are you using? On what operating system?
+
+Mac OS X 10.8.4 and git-annex version 4.20130801-gc88bbc4.
+
+### Please provide any additional information below.
+
+[[!format sh """
+[2013-09-09 01:33:03 EDT] XMPPSendPack: Syncing with adam.liter
+Already up-to-date.
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+"""]]
diff --git a/doc/bugs/Could_not_read_from_remote_repository/comment_1_da842a9d146bcd5c7773b58364c25597._comment b/doc/bugs/Could_not_read_from_remote_repository/comment_1_da842a9d146bcd5c7773b58364c25597._comment
new file mode 100644
index 000000000..c236beacd
--- /dev/null
+++ b/doc/bugs/Could_not_read_from_remote_repository/comment_1_da842a9d146bcd5c7773b58364c25597._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T06:01:18Z"
+ content="""
+From the small bit of log posted, it seems to be failing to sync over XMPP. Perhaps the XMPP server is down or it cannot connect? You can turn on debugging to get a lot more debugging about XMPP sync attempts.
+"""]]
diff --git a/doc/bugs/Could_not_read_from_remote_repository/comment_2_82746a0cf989d884cd0fd796db092b3c._comment b/doc/bugs/Could_not_read_from_remote_repository/comment_2_82746a0cf989d884cd0fd796db092b3c._comment
new file mode 100644
index 000000000..8312bb3a3
--- /dev/null
+++ b/doc/bugs/Could_not_read_from_remote_repository/comment_2_82746a0cf989d884cd0fd796db092b3c._comment
@@ -0,0 +1,36 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkgH7oNEqNbh3g-N1-UHXuqleXaRYDgj1U"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-09-09T06:12:44Z"
+ content="""
+This is what is in the logs after I turned on debugging:
+
+ [2013-09-09 02:04:22 EDT] XMPPSendPack: finished running push Pushing \"a29\" (PushRequest (UUID \"c96c8493-b702-4ca0-9a88-f8a38dd6c3f5\")) True
+ [2013-09-09 02:04:22 EDT] XMPPSendPack: started running push Pushing \"a29\" (PushRequest (UUID \"c96c8493-b702-4ca0-9a88-f8a38dd6c3f5\"))
+ [2013-09-09 02:04:22 EDT] read: git [\"--git-dir=/Users/adamliter/Library/texmf/.git\",\"--work-tree=/Users/adamliter/Library/texmf\",\"symbolic-ref\",\"HEAD\"]
+ [2013-09-09 02:04:22 EDT] read: git [\"--git-dir=/Users/adamliter/Library/texmf/.git\",\"--work-tree=/Users/adamliter/Library/texmf\",\"show-ref\",\"refs/heads/master\"]
+ [2013-09-09 02:04:22 EDT] call: git [\"--git-dir=/Users/adamliter/Library/texmf/.git\",\"--work-tree=/Users/adamliter/Library/texmf\",\"branch\",\"-f\",\"synced/master\"]
+ [2013-09-09 02:04:22 EDT] XMPPSendPack: Syncing with adam.liter
+ [2013-09-09 02:04:22 EDT] call: git [\"--git-dir=/Users/adamliter/Library/texmf/.git\",\"--work-tree=/Users/adamliter/Library/texmf\",\"push\",\"adam.liter\",\"git-annex:refs/synced/6258750b-9b0d-4f05-b443-61f4fb0a3f66/YWRhbS5saXRlckBnbWFpbC5jb20=/git-annex\",\"refs/heads/master:refs/synced/6258750b-9b0d-4f05-b443-61f4fb0a3f66/YWRhbS5saXRlckBnbWFpbC5jb20=/master\"]
+ [2013-09-09 02:04:22 EDT] XMPPClient: sending: Pushing \"a29\" (StartingPush (UUID \"6258750b-9b0d-4f05-b443-61f4fb0a3f66\"))
+ [2013-09-09 02:04:22 EDT] XMPPClient: to client: a10/F4E99F98
+ [2013-09-09 02:04:23 EDT] XMPPReceivePack: timeout waiting for git send-pack output via XMPP
+ fatal: The remote end hung up unexpectedly
+ [2013-09-09 02:04:23 EDT] XMPPReceivePack: finished running push Pushing \"a29\" (StartingPush (UUID \"c96c8493-b702-4ca0-9a88-f8a38dd6c3f5\")) True
+ [2013-09-09 02:04:23 EDT] XMPPClient: sending: Pushing \"a29\" (ReceivePackDone (ExitFailure 128))
+ [2013-09-09 02:04:23 EDT] XMPPReceivePack: started running push Pushing \"a29\" (StartingPush (UUID \"c96c8493-b702-4ca0-9a88-f8a38dd6c3f5\"))
+ [2013-09-09 02:04:23 EDT] XMPPClient: to client: a10/F4E99F98
+ [2013-09-09 02:04:23 EDT] XMPPReceivePack: Syncing with adam.liter
+ [2013-09-09 02:04:23 EDT] chat: git [\"receive-pack\",\"/Users/adamliter/Library/texmf\"]
+ [2013-09-09 02:04:23 EDT] XMPPClient: sending: Pushing \"a29\" (ReceivePackOutput 1 \"<elided>\")
+ [2013-09-09 02:04:23 EDT] XMPPClient: to client: a10/F4E99F98
+ [2013-09-09 02:04:23 EDT] XMPPClient: sending: Pushing \"a29\" (ReceivePackOutput 2 \"<elided>\")
+ [2013-09-09 02:04:23 EDT] XMPPClient: to client: a10/F4E99F98
+ [2013-09-09 02:04:23 EDT] XMPPClient: received: [\"Pushing \\"a29\\" (StartingPush (UUID \\"c96c8493-b702-4ca0-9a88-f8a38dd6c3f5\\"))\"]
+ [2013-09-09 02:04:23 EDT] XMPPClient: received: [\"Unknown message\"]
+
+
+
+
+"""]]
diff --git a/doc/bugs/Creating_second_repository_leads_to_wrong_ip___40__using_git-annex_webapp_--listen__41__.mdwn b/doc/bugs/Creating_second_repository_leads_to_wrong_ip___40__using_git-annex_webapp_--listen__41__.mdwn
new file mode 100644
index 000000000..28b74bd98
--- /dev/null
+++ b/doc/bugs/Creating_second_repository_leads_to_wrong_ip___40__using_git-annex_webapp_--listen__41__.mdwn
@@ -0,0 +1,35 @@
+### Please describe the problem.
+Using the git-annex webapp in remote mode will forward to the wrong IP (localhost) when creating the second repository
+
+### What steps will reproduce the problem?
+Needs two computers (C1, C2)
+
+- C1: run "git-annex webapp --listen=[IP of C1]
+- C2: use a browser to go to the address you just got on C1 (should contain IP of C1)
+- C2: create an repository as prompted (should work fine)
+- C2: In the dropdown on the top right select "Add another repository", choose desired location, select keep separate
+- C2: Browser forwards to new address, but instead of the IP of C1, 127.0.0.1 is used (which obviously fails)
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format sh """
+$ git-annex version
+git-annex version: 4.20130802
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+$ lsb_release -d
+Description: Ubuntu 13.04
+$ uname -a
+Linux nas 3.8.0-27-generic #40-Ubuntu SMP Tue Jul 9 00:19:35 UTC 2013 i686 i686 i686 GNU/Linux
+"""]]
+
+### 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.
+"""]]
+
+> This is a different effect of the same bug in [[Hangs on creating repository when using --listen]]. Closing as [[dup|done]] --[[Joey]]
diff --git a/doc/bugs/Discrepancy_between_git_annex_add_and_git_annex_watch.mdwn b/doc/bugs/Discrepancy_between_git_annex_add_and_git_annex_watch.mdwn
new file mode 100644
index 000000000..8e836e345
--- /dev/null
+++ b/doc/bugs/Discrepancy_between_git_annex_add_and_git_annex_watch.mdwn
@@ -0,0 +1,33 @@
+### Please describe the problem.
+
+`git annex add` does not add dotfiles (as per the man page) while `git annex watch` does (nothing on the man page). It's not a bug, but rather a surprise (at least to me).
+
+### What steps will reproduce the problem?
+
+[[!format sh """
+git init dotfiles
+cd dotfiles
+git annex init "my dotfiles"
+echo test > test.txt
+echo dottest > .dotest.txt
+git annex add
+git commit -a -m "initial dots"
+git annex whereis .dotest.txt # no answer, as expected
+git annex watch
+git annex whereis .dotest.txt # answers that .dotest.txt is here
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20131101, ubuntu 12.04 with all updates.
+
+### 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.
+"""]]
+
+> Improved documentation. [[done]] --[[Joey]]
diff --git a/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder.mdwn b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder.mdwn
new file mode 100644
index 000000000..d011e4416
--- /dev/null
+++ b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder.mdwn
@@ -0,0 +1,3747 @@
+### Please describe the problem.
+Two repositories A and B. B carries the full data, A only carries a subset of the data by excluding a couple of directories with a preferred content expression. Both repos in direct mode. A was modified quite heavily (thousands of files moved, deleted) with git-annex assistant running but without a possibility to synchronise with B.
+
+During synchronisation (by starting the webapp on A and git-annex assistant on B) suddenly former top-level folders, e.g.
+
+ ./201207
+
+appear in
+
+ ./incoming/5d/201207
+
+in both repositories.
+
+Then deleting
+
+ ./incoming/5d/201207
+
+in repo A unfortunately removes the top-level directory
+
+ ./201207
+
+as well and removes them in both repositories.
+
+### What steps will reproduce the problem?
+I don't know how to reproduce apart from the description above.
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20131002,
+Debian jessie, A: amd64, B: armhf
+
+### Please provide any additional information below.
+
+A paste of .git/annex/daemon.log of repoA below, as I haven't realised the problem immediatly I cannot tell whether this is the relevant log or not. If more is needed, I can provide additional logs.
+
+[[!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
+[2013-10-27 18:35:52 CET] main: Syncing with repoB
+From repoB:/media/srv/img
+ d1e3763..5eba12c git-annex -> repoB/git-annex
+ 611e4f5..a7b9fd7 master -> repoB/master
+ 714ed67..a7b9fd7 synced/master -> repoB/synced/master
+Auto packing the repository for optimum performance. You may also
+run "git gc" manually. See "git help gc" for more information.
+Updating 714ed67..a7b9fd7
+Fast-forward
+ 201109/jmg_7250.cr2 | 1 -
+ 201109/jmg_7250.jpg | 1 -
+ 201109/jmg_7251.cr2 | 1 -
+ 201109/jmg_7251.jpg | 1 -
+ 201109/jmg_7253.cr2 | 1 -
+ 201109/jmg_7253.jpg | 1 -
+ 201109/jmg_7256_raw.jpg | 1 -
+ 201109/jmg_7259.cr2 | 1 -
+ 201109/jmg_7259.jpg | 1 -
+ 201109/jmg_7261.cr2 | 1 -
+ 201109/jmg_7261.jpg | 1 -
+ 201109/jmg_7265.cr2 | 1 -
+ 201109/jmg_7265.jpg | 1 -
+ 201109/jmg_7272.jpg | 1 -
+ 201109/jmg_7274.jpg | 1 -
+ 201109/jmg_7275.jpg | 1 -
+ 201109/jmg_7276.jpg | 1 -
+ 201109/jmg_7280.jpg | 1 -
+ 201109/jmg_7284.jpg | 1 -
+ 201109/jmg_7286.jpg | 1 -
+ 201109/jmg_7288.jpg | 1 -
+ 201109/jmg_7289.jpg | 1 -
+ 201109/jmg_7292.jpg | 1 -
+ 201109/jmg_7293.jpg | 1 -
+ 201109/jmg_7295.cr2 | 1 -
+ 201109/jmg_7295.jpg | 1 -
+ 201109/jmg_7296.cr2 | 1 -
+ 201109/jmg_7296.jpg | 1 -
+ 201109/jmg_7299.cr2 | 1 -
+ 201109/jmg_7299.jpg | 1 -
+ 201109/jmg_7300.cr2 | 1 -
+ 201109/jmg_7300.jpg | 1 -
+ 201109/jmg_7304.jpg | 1 -
+ 201109/jmg_7305_raw.jpg | 1 -
+ 201109/jmg_7307_raw.jpg | 1 -
+ 201202/jmg_8528.jpg | 1 -
+ 201202/jmg_8529.jpg | 1 -
+ 201202/jmg_8595.jpg | 1 -
+ 201202/jmg_8596.jpg | 1 -
+ 201202/jmg_8597.jpg | 1 -
+ 201202/jmg_8601.jpg | 1 -
+ 201202/jmg_8602.cr2 | 1 -
+ 201202/jmg_8602.jpg | 1 -
+ 201202/jmg_8603.cr2 | 1 -
+ 201202/jmg_8603.jpg | 1 -
+ 201202/jmg_8604.jpg | 1 -
+ 201202/jmg_8605.jpg | 1 -
+ 201202/jmg_8606.jpg | 1 -
+ 201202/jmg_8607.jpg | 1 -
+ 201202/jmg_8608.jpg | 1 -
+ 201202/jmg_8609.jpg | 1 -
+ 201202/jmg_8610.jpg | 1 -
+ 201202/jmg_8611.jpg | 1 -
+ 201202/jmg_8612.cr2 | 1 -
+ 201202/jmg_8612.jpg | 1 -
+ 201202/jmg_8613.jpg | 1 -
+ 201202/jmg_8614.jpg | 1 -
+ 201202/jmg_8615.jpg | 1 -
+ 201202/jmg_8616_raw.jpg | 1 -
+ 201202/jmg_8617.jpg | 1 -
+ 201202/jmg_8618.jpg | 1 -
+ 201202/jmg_8619.jpg | 1 -
+ 201202/jmg_8620.jpg | 1 -
+ 201202/jmg_8621.jpg | 1 -
+ 201202/jmg_8622.jpg | 1 -
+ 201202/jmg_8624.jpg | 1 -
+ 201202/jmg_8625.cr2 | 1 -
+ 201202/jmg_8625.jpg | 1 -
+ 201202/jmg_8626.jpg | 1 -
+ 201202/jmg_8627.jpg | 1 -
+ 201202/jmg_8628.jpg | 1 -
+ 201202/jmg_8629.jpg | 1 -
+ 201202/jmg_8630.jpg | 1 -
+ 201202/jmg_8631.jpg | 1 -
+ 201202/jmg_8632.jpg | 1 -
+ 201202/jmg_8633.cr2 | 1 -
+ 201202/jmg_8633.jpg | 1 -
+ 201202/jmg_8634.jpg | 1 -
+ 201202/jmg_8637.jpg | 1 -
+ 201202/jmg_8639.jpg | 1 -
+ 201202/jmg_8640.jpg | 1 -
+ 201202/jmg_8641.jpg | 1 -
+ 201202/jmg_8642_raw.jpg | 1 -
+ 201202/jmg_8643.jpg | 1 -
+ 201202/jmg_8644.jpg | 1 -
+ 201202/jmg_8647.jpg | 1 -
+ 201202/jmg_8648.jpg | 1 -
+ 201202/jmg_8651.cr2 | 1 -
+ 201202/jmg_8651.jpg | 1 -
+ 201202/jmg_8652.jpg | 1 -
+ 201202/jmg_8653.jpg | 1 -
+ 201202/jmg_8654.jpg | 1 -
+ 201202/jmg_8655.jpg | 1 -
+ 201202/jmg_8657.jpg | 1 -
+ 201202/jmg_8665.jpg | 1 -
+ 201202/jmg_8670.jpg | 1 -
+ 201202/jmg_8671.jpg | 1 -
+ 201202/jmg_8673.cr2 | 1 -
+ 201202/jmg_8673.jpg | 1 -
+ 201202/jmg_8674.jpg | 1 -
+ 201202/jmg_8675.jpg | 1 -
+ 201202/jmg_8676.jpg | 1 -
+ 201202/jmg_8677.jpg | 1 -
+ 201202/jmg_8678.jpg | 1 -
+ 201202/jmg_8679.jpg | 1 -
+ 201202/jmg_8680.jpg | 1 -
+ 201202/jmg_8681.jpg | 1 -
+ 201203/jmg_8701.cr2 | 1 -
+ 201203/jmg_8702.jpg | 1 -
+ 201203/jmg_8705.jpg | 1 -
+ 201203/jmg_8711.jpg | 1 -
+ 201203/jmg_8717.jpg | 1 -
+ 201203/jmg_8718.jpg | 1 -
+ 201203/jmg_8719.jpg | 1 -
+ 201203/jmg_8721.jpg | 1 -
+ 201203/jmg_8725.jpg | 1 -
+ 201203/jmg_8726.jpg | 1 -
+ 201203/jmg_8731.jpg | 1 -
+ 201203/jmg_8739.jpg | 1 -
+ 201203/jmg_8745.jpg | 1 -
+ 201203/jmg_8747_raw.jpg | 1 -
+ 201203/jmg_8750.cr2 | 1 -
+ 201203/jmg_8750.jpg | 1 -
+ 201204/jmg_8751.jpg | 1 -
+ 201204/jmg_8752.jpg | 1 -
+ 201204/jmg_8755.jpg | 1 -
+ 201204/jmg_8756.jpg | 1 -
+ 201204/jmg_8757.jpg | 1 -
+ 201204/jmg_8759.jpg | 1 -
+ 201204/jmg_8760.jpg | 1 -
+ 201204/jmg_8761.jpg | 1 -
+ 201204/jmg_8762.jpg | 1 -
+ 201204/jmg_8763.cr2 | 1 -
+ 201204/jmg_8763.jpg | 1 -
+ 201204/jmg_8766.jpg | 1 -
+ 201204/jmg_8767.cr2 | 1 -
+ 201204/jmg_8767.jpg | 1 -
+ 201204/jmg_8768.jpg | 1 -
+ 201204/jmg_8769.jpg | 1 -
+ 201204/jmg_8770.jpg | 1 -
+ 201204/jmg_8771.jpg | 1 -
+ 201204/jmg_8772.jpg | 1 -
+ 201204/jmg_8773.jpg | 1 -
+ 201205/jmg_8822.jpg | 1 -
+ 201205/jmg_8823.jpg | 1 -
+ 201205/jmg_8824.jpg | 1 -
+ 201205/jmg_8826.jpg | 1 -
+ 201205/jmg_8831.jpg | 1 -
+ 201205/jmg_8834.jpg | 1 -
+ 201205/jmg_8835.jpg | 1 -
+ 201205/jmg_8835_raw.jpg | 1 -
+ 201205/jmg_8837.jpg | 1 -
+ 201205/jmg_8839.cr2 | 1 -
+ 201205/jmg_8839.jpg | 1 -
+ 201205/jmg_8839_raw.jpg | 1 -
+ 201205/jmg_8840.cr2 | 1 -
+ 201205/jmg_8840.jpg | 1 -
+ 201205/jmg_8840_raw.jpg | 1 -
+ 201205/jmg_8841.jpg | 1 -
+ 201205/jmg_8842.jpg | 1 -
+ 201205/jmg_8844.cr2 | 1 -
+ 201205/jmg_8844.jpg | 1 -
+ 201205/jmg_8844_raw.jpg | 1 -
+ 201205/jmg_8845.jpg | 1 -
+ 201205/jmg_8846.jpg | 1 -
+ 201205/jmg_8847.cr2 | 1 -
+ 201205/jmg_8847.jpg | 1 -
+ 201205/jmg_8847_raw.jpg | 1 -
+ 201205/jmg_8848.jpg | 1 -
+ 201205/jmg_8849.jpg | 1 -
+ 201205/jmg_8851.cr2 | 1 -
+ 201205/jmg_8851.jpg | 1 -
+ 201205/jmg_8851_raw.jpg | 1 -
+ 201205/jmg_8856.cr2 | 1 -
+ 201205/jmg_8856.jpg | 1 -
+ 201205/jmg_8856_raw.jpg | 1 -
+ 201205/jmg_8857.jpg | 1 -
+ 201205/jmg_8858.jpg | 1 -
+ 201205/jmg_8859.jpg | 1 -
+ 201205/jmg_8861.jpg | 1 -
+ 201205/jmg_8862.jpg | 1 -
+ 201205/jmg_8863.jpg | 1 -
+ 201205/jmg_8871.cr2 | 1 -
+ 201205/jmg_8871.jpg | 1 -
+ 201205/jmg_8872.jpg | 1 -
+ 201205/jmg_8873.jpg | 1 -
+ 201205/jmg_8875.jpg | 1 -
+ 201205/jmg_8876.cr2 | 1 -
+ 201205/jmg_8876.jpg | 1 -
+ 201205/jmg_8878.cr2 | 1 -
+ 201205/jmg_8878.jpg | 1 -
+ 201205/jmg_8879.cr2 | 1 -
+ 201205/jmg_8879.jpg | 1 -
+ 201205/jmg_8880.cr2 | 1 -
+ 201205/jmg_8880.jpg | 1 -
+ 201205/jmg_8881.cr2 | 1 -
+ 201205/jmg_8881.jpg | 1 -
+ 201205/jmg_8892.cr2 | 1 -
+ 201205/jmg_8892.jpg | 1 -
+ 201205/jmg_8893.cr2 | 1 -
+ 201205/jmg_8893.jpg | 1 -
+ 201205/jmg_8894.cr2 | 1 -
+ 201205/jmg_8894.jpg | 1 -
+ 201206/jmg_8989.cr2 | 1 -
+ 201206/jmg_8989.jpg | 1 -
+ 201206/jmg_8990.cr2 | 1 -
+ 201206/jmg_8990.jpg | 1 -
+ 201206/jmg_8995.jpg | 1 -
+ 201206/jmg_8996.jpg | 1 -
+ 201206/jmg_8998.jpg | 1 -
+ 201206/jmg_9001.jpg | 1 -
+ 201206/jmg_9003.jpg | 1 -
+ 201206/jmg_9006.jpg | 1 -
+ 201206/jmg_9007.jpg | 1 -
+ 201206/jmg_9011.jpg | 1 -
+ 201206/jmg_9014.jpg | 1 -
+ 201206/jmg_9014_raw.jpg | 1 -
+ 201206/jmg_9015.jpg | 1 -
+ 201206/jmg_9016.cr2 | 1 -
+ 201206/jmg_9016.jpg | 1 -
+ 201206/jmg_9017.cr2 | 1 -
+ 201206/jmg_9017.jpg | 1 -
+ 201206/jmg_9018.cr2 | 1 -
+ 201206/jmg_9018.jpg | 1 -
+ 201206/jmg_9019.cr2 | 1 -
+ 201206/jmg_9019.jpg | 1 -
+ 201206/jmg_9023.cr2 | 1 -
+ 201206/jmg_9023.jpg | 1 -
+ 201206/jmg_9024.cr2 | 1 -
+ 201206/jmg_9024.jpg | 1 -
+ 201206/jmg_9025.cr2 | 1 -
+ 201206/jmg_9025.jpg | 1 -
+ 201206/jmg_9028.jpg | 1 -
+ 201206/jmg_9029.jpg | 1 -
+ 201206/jmg_9030.jpg | 1 -
+ 201206/jmg_9031.jpg | 1 -
+ 201206/jmg_9032_raw.jpg | 1 -
+ 201206/jmg_9033.jpg | 1 -
+ 201206/jmg_9033_raw.jpg | 1 -
+ 201206/jmg_9034.jpg | 1 -
+ 201206/jmg_9035.jpg | 1 -
+ 201206/jmg_9035_raw.jpg | 1 -
+ 201206/jmg_9036.jpg | 1 -
+ 201206/jmg_9039.cr2 | 1 -
+ 201206/jmg_9039.jpg | 1 -
+ 201206/jmg_9040.cr2 | 1 -
+ 201206/jmg_9040.jpg | 1 -
+ 201206/jmg_9043.cr2 | 1 -
+ 201206/jmg_9043.jpg | 1 -
+ 201206/jmg_9047.cr2 | 1 -
+ 201206/jmg_9047.jpg | 1 -
+ 201207/jmg_9048.jpg | 1 -
+ 201207/jmg_9053.jpg | 1 -
+ 201207/jmg_9054.jpg | 1 -
+ 201207/jmg_9069.cr2 | 1 -
+ 201207/jmg_9069.jpg | 1 -
+ 201207/jmg_9070.cr2 | 1 -
+ 201207/jmg_9070.jpg | 1 -
+ 201207/jmg_9072.cr2 | 1 -
+ 201207/jmg_9072.jpg | 1 -
+ 201207/jmg_9076.cr2 | 1 -
+ 201207/jmg_9076.jpg | 1 -
+ 201208/jmg_9077.jpg | 1 -
+ 201208/jmg_9302_raw.jpg | 1 -
+ 201208/jmg_9303.jpg | 1 -
+ 201208/jmg_9304.cr2 | 1 -
+ 201208/jmg_9304.jpg | 1 -
+ 201208/jmg_9305.cr2 | 1 -
+ 201208/jmg_9305.jpg | 1 -
+ 201208/jmg_9306_raw.jpg | 1 -
+ 201208/jmg_9307.cr2 | 1 -
+ 201208/jmg_9307.jpg | 1 -
+ 201208/jmg_9308_raw.jpg | 1 -
+ 201208/jmg_9309_raw.jpg | 1 -
+ 201208/jmg_9310.cr2 | 1 -
+ 201208/jmg_9310.jpg | 1 -
+ 201208/jmg_9310_bw.jpg | 1 -
+ 201208/jmg_9310_raw.jpg | 1 -
+ 201208/jmg_9312.jpg | 1 -
+ 201208/jmg_9313.jpg | 1 -
+ 201208/jmg_9314.jpg | 1 -
+ 201208/jmg_9315.jpg | 1 -
+ 201208/jmg_9319.jpg | 1 -
+ 201208/jmg_9523.jpg | 1 -
+ 201208/jmg_9524.jpg | 1 -
+ 201208/jmg_9525.jpg | 1 -
+ 201208/jmg_9526.jpg | 1 -
+ 201208/jmg_9527.jpg | 1 -
+ 201208/jmg_9527_raw.jpg | 1 -
+ 201208/jmg_9528.jpg | 1 -
+ 201208/jmg_9529.jpg | 1 -
+ 201208/jmg_9530.jpg | 1 -
+ 201208/jmg_9531.jpg | 1 -
+ 201208/jmg_9532.jpg | 1 -
+ 201208/jmg_9533.cr2 | 1 -
+ 201208/jmg_9533.jpg | 1 -
+ 201208/jmg_9534.cr2 | 1 -
+ 201208/jmg_9534.jpg | 1 -
+ 201208/jmg_9535.jpg | 1 -
+ 201208/jmg_9536.jpg | 1 -
+ 201208/jmg_9537.cr2 | 1 -
+ 201208/jmg_9537.jpg | 1 -
+ 201208/jmg_9538.jpg | 1 -
+ 201208/jmg_9539.jpg | 1 -
+ 201208/jmg_9540.jpg | 1 -
+ 201208/jmg_9541.cr2 | 1 -
+ 201208/jmg_9542.jpg | 1 -
+ 201208/jmg_9543.cr2 | 1 -
+ 201208/jmg_9543.jpg | 1 -
+ 201208/jmg_9544.cr2 | 1 -
+ 201208/jmg_9544.jpg | 1 -
+ 201208/jmg_9545.jpg | 1 -
+ 201209/jmg_9547.jpg | 1 -
+ 201209/jmg_9548.jpg | 1 -
+ 201209/jmg_9549.jpg | 1 -
+ 201209/jmg_9550.jpg | 1 -
+ 201209/jmg_9551.jpg | 1 -
+ 201209/jmg_9552.jpg | 1 -
+ 201209/jmg_9553.jpg | 1 -
+ 201209/jmg_9555.jpg | 1 -
+ 201209/jmg_9556.jpg | 1 -
+ 201209/jmg_9558.jpg | 1 -
+ 201209/jmg_9559.cr2 | 1 -
+ 201209/jmg_9559.jpg | 1 -
+ 201209/jmg_9560.cr2 | 1 -
+ 201209/jmg_9560.jpg | 1 -
+ 201209/jmg_9561.jpg | 1 -
+ 201209/jmg_9562.jpg | 1 -
+ 201209/jmg_9568.jpg | 1 -
+ 201210/jmg_0001.jpg | 1 -
+ 201210/jmg_0021.jpg | 1 -
+ 201210/jmg_0022.cr2 | 1 -
+ 201210/jmg_0022.jpg | 1 -
+ 201210/jmg_0025.jpg | 1 -
+ 201210/jmg_0026.jpg | 1 -
+ 201210/jmg_0027.jpg | 1 -
+ 201210/jmg_0028.jpg | 1 -
+ 201210/jmg_0029.jpg | 1 -
+ 201210/jmg_0030.jpg | 1 -
+ 201210/jmg_0032.jpg | 1 -
+ 201210/jmg_0034.jpg | 1 -
+ 201210/jmg_0035.jpg | 1 -
+ 201210/jmg_0036.jpg | 1 -
+ 201210/jmg_0037.jpg | 1 -
+ 201210/jmg_0039.cr2 | 1 -
+ 201210/jmg_0039.jpg | 1 -
+ 201210/jmg_0040.jpg | 1 -
+ 201210/jmg_9572.jpg | 1 -
+ 201210/jmg_9573.jpg | 1 -
+ 201210/jmg_9574.jpg | 1 -
+ 201210/jmg_9575.jpg | 1 -
+ 201210/jmg_9576.jpg | 1 -
+ 201210/jmg_9578.jpg | 1 -
+ 201210/jmg_9580.jpg | 1 -
+ 201210/jmg_9581.jpg | 1 -
+ 201210/jmg_9582.cr2 | 1 -
+ 201210/jmg_9582.jpg | 1 -
+ 201210/jmg_9585.cr2 | 1 -
+ 201210/jmg_9585.jpg | 1 -
+ 201210/jmg_9587.cr2 | 1 -
+ 201210/jmg_9587.jpg | 1 -
+ 201210/jmg_9588.jpg | 1 -
+ 201210/jmg_9589.jpg | 1 -
+ 201210/jmg_9590.jpg | 1 -
+ 201210/jmg_9591.jpg | 1 -
+ 201210/jmg_9594.jpg | 1 -
+ 201210/jmg_9595.jpg | 1 -
+ 201210/jmg_9596.jpg | 1 -
+ 201210/jmg_9597.cr2 | 1 -
+ 201210/jmg_9597.jpg | 1 -
+ 201210/jmg_9598.cr2 | 1 -
+ 201210/jmg_9598.jpg | 1 -
+ 201210/jmg_9599.cr2 | 1 -
+ 201210/jmg_9599.jpg | 1 -
+ 201210/jmg_9600.jpg | 1 -
+ 201210/jmg_9602.jpg | 1 -
+ 201210/jmg_9603.jpg | 1 -
+ 201210/jmg_9604.jpg | 1 -
+ 201210/jmg_9605.cr2 | 1 -
+ 201210/jmg_9605.jpg | 1 -
+ 201210/jmg_9606.jpg | 1 -
+ 201210/jmg_9608.jpg | 1 -
+ 201210/jmg_9609.jpg | 1 -
+ 201210/jmg_9610.jpg | 1 -
+ 201210/jmg_9611.jpg | 1 -
+ 201210/jmg_9612.jpg | 1 -
+ 201210/jmg_9613.jpg | 1 -
+ 201210/jmg_9614.jpg | 1 -
+ 201210/jmg_9616.cr2 | 1 -
+ 201210/jmg_9616.jpg | 1 -
+ 201210/jmg_9617.jpg | 1 -
+ 201210/jmg_9619.jpg | 1 -
+ 201210/jmg_9620.jpg | 1 -
+ 201210/jmg_9621.jpg | 1 -
+ 201210/jmg_9622.jpg | 1 -
+ 201210/jmg_9623.cr2 | 1 -
+ 201210/jmg_9623.jpg | 1 -
+ 201210/jmg_9624.cr2 | 1 -
+ 201210/jmg_9624.jpg | 1 -
+ 201210/jmg_9736_raw.jpg | 1 -
+ 201210/jmg_9738_raw.jpg | 1 -
+ 201210/jmg_9740.cr2 | 1 -
+ 201210/jmg_9740.jpg | 1 -
+ 201210/jmg_9743.jpg | 1 -
+ 201210/jmg_9744.jpg | 1 -
+ 201210/jmg_9745.cr2 | 1 -
+ 201210/jmg_9745.jpg | 1 -
+ 201210/jmg_9746.cr2 | 1 -
+ 201210/jmg_9746.jpg | 1 -
+ 201210/jmg_9748.jpg | 1 -
+ 201210/jmg_9749_raw.jpg | 1 -
+ 201210/jmg_9751.jpg | 1 -
+ 201210/jmg_9752.jpg | 1 -
+ 201210/jmg_9754.jpg | 1 -
+ 201210/jmg_9755.jpg | 1 -
+ 201210/jmg_9756.jpg | 1 -
+ 201210/jmg_9760.cr2 | 1 -
+ 201210/jmg_9760.jpg | 1 -
+ 201210/jmg_9761.cr2 | 1 -
+ 201210/jmg_9761.jpg | 1 -
+ 201210/jmg_9763.jpg | 1 -
+ 201210/jmg_9764.jpg | 1 -
+ 201210/jmg_9766.jpg | 1 -
+ 201210/jmg_9767.cr2 | 1 -
+ 201210/jmg_9767.jpg | 1 -
+ 201210/jmg_9768.jpg | 1 -
+ 201210/jmg_9771.jpg | 1 -
+ 201210/jmg_9772.jpg | 1 -
+ 201210/jmg_9791.jpg | 1 -
+ 201210/jmg_9792.jpg | 1 -
+ 201210/jmg_9793.jpg | 1 -
+ 201210/jmg_9794.jpg | 1 -
+ 201210/jmg_9796.jpg | 1 -
+ 201210/jmg_9797.jpg | 1 -
+ 201210/jmg_9799.jpg | 1 -
+ 201210/jmg_9800.jpg | 1 -
+ 201210/jmg_9801.jpg | 1 -
+ 201210/jmg_9803.jpg | 1 -
+ 201210/jmg_9807.jpg | 1 -
+ 201210/jmg_9808.jpg | 1 -
+ 201210/jmg_9809.jpg | 1 -
+ 201210/jmg_9810.jpg | 1 -
+ 201210/jmg_9811.jpg | 1 -
+ 201210/jmg_9812.jpg | 1 -
+ 201210/jmg_9813.jpg | 1 -
+ 201210/jmg_9815.jpg | 1 -
+ 201210/jmg_9818.jpg | 1 -
+ 201210/jmg_9819.jpg | 1 -
+ 201210/jmg_9820.jpg | 1 -
+ 201210/jmg_9821.jpg | 1 -
+ 201210/jmg_9822.jpg | 1 -
+ 201210/jmg_9823.jpg | 1 -
+ 201210/jmg_9825.jpg | 1 -
+ 201210/jmg_9826.jpg | 1 -
+ 201210/jmg_9827.jpg | 1 -
+ 201210/jmg_9828.jpg | 1 -
+ 201210/jmg_9829.jpg | 1 -
+ 201210/jmg_9830.cr2 | 1 -
+ 201210/jmg_9830.jpg | 1 -
+ 201210/jmg_9832.cr2 | 1 -
+ 201210/jmg_9832.jpg | 1 -
+ 201210/jmg_9834.jpg | 1 -
+ 201210/jmg_9836.jpg | 1 -
+ 201210/jmg_9838.jpg | 1 -
+ 201210/jmg_9839.jpg | 1 -
+ 201210/jmg_9841.jpg | 1 -
+ 201210/jmg_9843.jpg | 1 -
+ 201210/jmg_9845.jpg | 1 -
+ 201210/jmg_9846.jpg | 1 -
+ 201210/jmg_9848.jpg | 1 -
+ 201210/jmg_9849.jpg | 1 -
+ 201210/jmg_9852.jpg | 1 -
+ 201210/jmg_9853.jpg | 1 -
+ 201210/jmg_9854.jpg | 1 -
+ 201210/jmg_9855.jpg | 1 -
+ 201210/jmg_9856.jpg | 1 -
+ 201210/jmg_9857.cr2 | 1 -
+ 201210/jmg_9857.jpg | 1 -
+ 201210/jmg_9858.cr2 | 1 -
+ 201210/jmg_9858.jpg | 1 -
+ 201210/jmg_9859.jpg | 1 -
+ 201210/jmg_9860.jpg | 1 -
+ 201210/jmg_9915.jpg | 1 -
+ 201210/jmg_9917.jpg | 1 -
+ 201210/jmg_9918.jpg | 1 -
+ 201210/jmg_9919.jpg | 1 -
+ 201210/jmg_9922.jpg | 1 -
+ 201210/jmg_9923.jpg | 1 -
+ 201210/jmg_9925.jpg | 1 -
+ 201210/jmg_9926.cr2 | 1 -
+ 201210/jmg_9926.jpg | 1 -
+ 201210/jmg_9928.jpg | 1 -
+ 201210/jmg_9975.cr2 | 1 -
+ 201210/jmg_9975.jpg | 1 -
+ 201210/jmg_9976.cr2 | 1 -
+ 201210/jmg_9976.jpg | 1 -
+ 201210/jmg_9978.jpg | 1 -
+ 201210/jmg_9986.jpg | 1 -
+ 201210/jmg_9987.jpg | 1 -
+ 201210/jmg_9988.jpg | 1 -
+ 201210/jmg_9989.jpg | 1 -
+ 201210/jmg_9991.jpg | 1 -
+ 201210/jmg_9993.jpg | 1 -
+ 201210/jmg_9994.cr2 | 1 -
+ 201210/jmg_9994.jpg | 1 -
+ 201210/jmg_9997.jpg | 1 -
+ 201210/jmg_9998.jpg | 1 -
+ 201210/jmg_9999.jpg | 1 -
+ 201212/jmg_0131.jpg | 1 -
+ 201212/jmg_0134.jpg | 1 -
+ 201212/jmg_0135.jpg | 1 -
+ 201212/jmg_0152.jpg | 1 -
+ 201212/jmg_0155.jpg | 1 -
+ 201212/jmg_0156.jpg | 1 -
+ 201212/jmg_0162.jpg | 1 -
+ 201212/jmg_0163.jpg | 1 -
+ 201212/jmg_0165.jpg | 1 -
+ 201212/jmg_0176.cr2 | 1 -
+ 201212/jmg_0176.jpg | 1 -
+ 201212/jmg_0177.cr2 | 1 -
+ 201212/jmg_0177.jpg | 1 -
+ 201212/jmg_0178.jpg | 1 -
+ 201212/jmg_0179.jpg | 1 -
+ 201212/jmg_0180.jpg | 1 -
+ 201212/jmg_0184.jpg | 1 -
+ 201212/jmg_0185.jpg | 1 -
+ 201212/jmg_0186.jpg | 1 -
+ 201212/jmg_0187.jpg | 1 -
+ 201212/jmg_0306.jpg | 1 -
+ 201212/jmg_0307.jpg | 1 -
+ 201212/jmg_0308.jpg | 1 -
+ 201212/jmg_0310.jpg | 1 -
+ 201212/jmg_0311.jpg | 1 -
+ 201212/jmg_0312.jpg | 1 -
+ 201212/jmg_0313.jpg | 1 -
+ 201212/jmg_0314.jpg | 1 -
+ 201212/jmg_0315.jpg | 1 -
+ 201212/jmg_0316.jpg | 1 -
+ 201212/jmg_0317.jpg | 1 -
+ 201212/jmg_0321.jpg | 1 -
+ 201212/jmg_0326.jpg | 1 -
+ 201212/jmg_0328.jpg | 1 -
+ 201212/jmg_0330.jpg | 1 -
+ 201212/jmg_0333.jpg | 1 -
+ 201212/jmg_0336.jpg | 1 -
+ 201212/jmg_0340.jpg | 1 -
+ 201212/jmg_0343.jpg | 1 -
+ 201212/jmg_0345.jpg | 1 -
+ 201212/jmg_0360.jpg | 1 -
+ 201212/jmg_0362.jpg | 1 -
+ 201212/jmg_0363.jpg | 1 -
+ 201212/jmg_0364.jpg | 1 -
+ 201212/jmg_0366.jpg | 1 -
+ 201212/jmg_0367.jpg | 1 -
+ 201212/jmg_0368.jpg | 1 -
+ 201212/jmg_0369.jpg | 1 -
+ 201212/jmg_0370.jpg | 1 -
+ 201212/jmg_0372.jpg | 1 -
+ 201212/jmg_0382.jpg | 1 -
+ 201212/jmg_0383.jpg | 1 -
+ 201212/jmg_0384.jpg | 1 -
+ 201212/jmg_0385.jpg | 1 -
+ 201212/jmg_0387.jpg | 1 -
+ 201212/jmg_0388.jpg | 1 -
+ 201212/jmg_0389.jpg | 1 -
+ 201212/jmg_0390.jpg | 1 -
+ 201212/jmg_0392.jpg | 1 -
+ 201212/jmg_0396.jpg | 1 -
+ 201212/jmg_0397.jpg | 1 -
+ 201212/jmg_0398.jpg | 1 -
+ 201212/jmg_0399.jpg | 1 -
+ 201212/jmg_0402.jpg | 1 -
+ 201212/jmg_0404.jpg | 1 -
+ 201212/jmg_0405.jpg | 1 -
+ 201212/jmg_0406.jpg | 1 -
+ 201212/jmg_0407.jpg | 1 -
+ 201212/jmg_0408.jpg | 1 -
+ 201212/jmg_0410.jpg | 1 -
+ 201212/jmg_0411.jpg | 1 -
+ 201212/jmg_0412.jpg | 1 -
+ 201212/jmg_0415.jpg | 1 -
+ 201212/jmg_0417.jpg | 1 -
+ 201212/jmg_0418.jpg | 1 -
+ 201302/jmg_0502.cr2 | 1 -
+ 201302/jmg_0502.jpg | 1 -
+ 201302/jmg_0503.jpg | 1 -
+ 201302/jmg_0507.jpg | 1 -
+ 201302/jmg_0510.jpg | 1 -
+ 201302/jmg_0512.jpg | 1 -
+ 201302/jmg_0513.jpg | 1 -
+ 201302/jmg_0514.jpg | 1 -
+ 201302/jmg_0516.jpg | 1 -
+ 201302/jmg_0517.jpg | 1 -
+ 201302/jmg_0518.jpg | 1 -
+ 201302/jmg_0521.jpg | 1 -
+ 201302/jmg_0522.jpg | 1 -
+ 201302/jmg_0523.jpg | 1 -
+ 201302/jmg_0524.jpg | 1 -
+ 201302/jmg_0526.jpg | 1 -
+ 201302/jmg_0527.jpg | 1 -
+ 201302/jmg_0528.jpg | 1 -
+ 201302/jmg_0532.cr2 | 1 -
+ 201302/jmg_0532.jpg | 1 -
+ 201302/jmg_0534.jpg | 1 -
+ 201302/jmg_0535.jpg | 1 -
+ 201302/jmg_0537.jpg | 1 -
+ 201302/jmg_0539.jpg | 1 -
+ 201302/jmg_0541.jpg | 1 -
+ 201302/jmg_0543.jpg | 1 -
+ 201304/bruecke_saeckingen.tif | 1 -
+ 201304/jmg_0685.cr2 | 1 -
+ 201304/jmg_0685.jpg | 1 -
+ 201304/jmg_0687.cr2 | 1 -
+ 201304/jmg_0687.jpg | 1 -
+ 201304/jmg_0699.jpg | 1 -
+ 201304/jmg_0700.jpg | 1 -
+ 201304/jmg_0726.jpg | 1 -
+ 201304/jmg_0727.jpg | 1 -
+ 201304/jmg_0728.jpg | 1 -
+ 201304/jmg_0729.cr2 | 1 -
+ 201304/jmg_0729.jpg | 1 -
+ 201304/jmg_0730.jpg | 1 -
+ 201304/jmg_0731.jpg | 1 -
+ 201304/jmg_0733.cr2 | 1 -
+ 201304/jmg_0733.jpg | 1 -
+ 201304/jmg_0734.cr2 | 1 -
+ 201304/jmg_0734.jpg | 1 -
+ 201304/jmg_0736.cr2 | 1 -
+ 201304/jmg_0736.jpg | 1 -
+ 201304/jmg_0737.cr2 | 1 -
+ 201304/jmg_0737.jpg | 1 -
+ 201304/jmg_0738.jpg | 1 -
+ 201304/jmg_0739.jpg | 1 -
+ 201304/jmg_0740.jpg | 1 -
+ 201304/jmg_0741.jpg | 1 -
+ 201304/jmg_0742.jpg | 1 -
+ 201304/jmg_0744.cr2 | 1 -
+ 201304/jmg_0744.jpg | 1 -
+ 201304/jmg_0749.jpg | 1 -
+ 201304/jmg_0750.jpg | 1 -
+ 201304/jmg_0751.jpg | 1 -
+ 201304/jmg_0752.jpg | 1 -
+ 201304/jmg_0753.jpg | 1 -
+ 201304/jmg_0755.cr2 | 1 -
+ 201304/jmg_0755.jpg | 1 -
+ 201304/jmg_0757.cr2 | 1 -
+ 201304/jmg_0757.jpg | 1 -
+ 201304/jmg_0758.jpg | 1 -
+ 201304/jmg_0759.jpg | 1 -
+ 201304/jmg_0760.cr2 | 1 -
+ 201304/jmg_0760.jpg | 1 -
+ 201304/jmg_0762.cr2 | 1 -
+ 201304/jmg_0762.jpg | 1 -
+ 201304/jmg_0763.jpg | 1 -
+ 201304/jmg_0764.jpg | 1 -
+ 201304/jmg_0765.jpg | 1 -
+ 201304/jmg_0766.jpg | 1 -
+ 201304/jmg_0769.jpg | 1 -
+ 201304/jmg_0770.jpg | 1 -
+ 201304/jmg_0771.jpg | 1 -
+ 201304/jmg_0785.cr2 | 1 -
+ 201304/jmg_0785.jpg | 1 -
+ 201304/jmg_0786.cr2 | 1 -
+ 201304/jmg_0786.jpg | 1 -
+ 201304/jmg_0787.cr2 | 1 -
+ 201304/jmg_0787.jpg | 1 -
+ 201304/jmg_0789.jpg | 1 -
+ 201304/jmg_0790.jpg | 1 -
+ 201304/jmg_0791.jpg | 1 -
+ 201304/jmg_0800.jpg | 1 -
+ 201304/jmg_0801.jpg | 1 -
+ 201304/jmg_0802.jpg | 1 -
+ 201304/jmg_0803.jpg | 1 -
+ 201304/jmg_0809.jpg | 1 -
+ 201304/jmg_0810.jpg | 1 -
+ 201304/jmg_0812.jpg | 1 -
+ 201304/jmg_0813.jpg | 1 -
+ 201304/jmg_0824.jpg | 1 -
+ 201304/jmg_0825.jpg | 1 -
+ 201304/jmg_0827.jpg | 1 -
+ 201304/jmg_0831.jpg | 1 -
+ 201304/jmg_0833.jpg | 1 -
+ 201304/jmg_0834.jpg | 1 -
+ 201304/jmg_0836.jpg | 1 -
+ 201304/jmg_0837.jpg | 1 -
+ 201304/jmg_0845.jpg | 1 -
+ 201304/jmg_0846.jpg | 1 -
+ 201304/jmg_0847.jpg | 1 -
+ 201304/jmg_0848.jpg | 1 -
+ 201304/jmg_0849.jpg | 1 -
+ 201304/jmg_0850.jpg | 1 -
+ 201304/jmg_0851.jpg | 1 -
+ 201304/jmg_0857.jpg | 1 -
+ 201304/jmg_0858.jpg | 1 -
+ 201304/jmg_0860.jpg | 1 -
+ 201304/jmg_0861.jpg | 1 -
+ 201304/jmg_0862.jpg | 1 -
+ 201304/jmg_0863.jpg | 1 -
+ 201304/jmg_0864.jpg | 1 -
+ 201304/jmg_0866.jpg | 1 -
+ 201304/jmg_0867.jpg | 1 -
+ 201304/jmg_0868.cr2 | 1 -
+ 201304/jmg_0868.jpg | 1 -
+ 201304/jmg_0869.cr2 | 1 -
+ 201304/jmg_0869.jpg | 1 -
+ 201304/jmg_0872.cr2 | 1 -
+ 201304/jmg_0872.jpg | 1 -
+ 201304/jmg_0874.cr2 | 1 -
+ 201304/jmg_0874.jpg | 1 -
+ 201304/jmg_0875.jpg | 1 -
+ 201304/jmg_0875_raw.jpg | 1 -
+ 201304/jmg_0876.jpg | 1 -
+ 201304/jmg_0877.jpg | 1 -
+ 201304/jmg_0878.jpg | 1 -
+ 201304/jmg_0880.jpg | 1 -
+ 201304/jmg_0881.jpg | 1 -
+ 201304/jmg_0882.jpg | 1 -
+ 201304/jmg_0884.jpg | 1 -
+ 201304/jmg_0885.jpg | 1 -
+ 201304/jmg_0886.jpg | 1 -
+ 201304/jmg_0888.jpg | 1 -
+ 201304/jmg_0889.jpg | 1 -
+ 201304/jmg_0890.jpg | 1 -
+ 201304/jmg_0891.jpg | 1 -
+ 201304/jmg_0892.jpg | 1 -
+ 201304/jmg_0893.cr2 | 1 -
+ 201304/jmg_0893.jpg | 1 -
+ 201304/jmg_0894.jpg | 1 -
+ 201304/jmg_0896.jpg | 1 -
+ 201304/jmg_0897.jpg | 1 -
+ 201304/jmg_0898.jpg | 1 -
+ 201304/jmg_0899.jpg | 1 -
+ 201304/jmg_0900.jpg | 1 -
+ 201304/jmg_0902.jpg | 1 -
+ 201304/jmg_0905.jpg | 1 -
+ 201304/jmg_0921.jpg | 1 -
+ 201304/jmg_0922.jpg | 1 -
+ 201304/jmg_0932.jpg | 1 -
+ 201304/jmg_0935.jpg | 1 -
+ 201304/jmg_0936.jpg | 1 -
+ 201304/jmg_0937.jpg | 1 -
+ 201304/jmg_0938.jpg | 1 -
+ 201304/jmg_0942.jpg | 1 -
+ 201304/jmg_0944.jpg | 1 -
+ 201304/jmg_0946.jpg | 1 -
+ 201304/jmg_0947.jpg | 1 -
+ 201304/jmg_0948.jpg | 1 -
+ 201304/jmg_0949.jpg | 1 -
+ 201304/jmg_0950.jpg | 1 -
+ 201304/jmg_0951.jpg | 1 -
+ 201304/jmg_0952.jpg | 1 -
+ 201304/jmg_0953.jpg | 1 -
+ 201304/jmg_0954.jpg | 1 -
+ 201304/jmg_0958.jpg | 1 -
+ 201304/jmg_0959.jpg | 1 -
+ 201304/jmg_0960.jpg | 1 -
+ 201304/jmg_0961.jpg | 1 -
+ 201304/jmg_0962.jpg | 1 -
+ 201304/jmg_0963.jpg | 1 -
+ 201304/jmg_0964.jpg | 1 -
+ 201304/jmg_0965.jpg | 1 -
+ 201304/jmg_0966.jpg | 1 -
+ 201304/jmg_0967.jpg | 1 -
+ 201304/jmg_0968.jpg | 1 -
+ 201304/jmg_0969.jpg | 1 -
+ 201304/jmg_0976.cr2 | 1 -
+ 201304/jmg_0976.jpg | 1 -
+ 201304/jmg_0978.jpg | 1 -
+ 201304/jmg_0979.jpg | 1 -
+ 201304/jmg_0980.jpg | 1 -
+ 201304/jmg_0981.cr2 | 1 -
+ 201304/jmg_0981.jpg | 1 -
+ 201304/jmg_0982.jpg | 1 -
+ 201304/jmg_0984.cr2 | 1 -
+ 201304/jmg_0984.jpg | 1 -
+ 201304/jmg_0987.jpg | 1 -
+ 201304/jmg_0988.jpg | 1 -
+ 201304/jmg_0989.jpg | 1 -
+ 201304/jmg_0990.jpg | 1 -
+ 201304/jmg_0991.jpg | 1 -
+ 201304/jmg_0992.jpg | 1 -
+ 201304/jmg_1206.jpg | 1 -
+ 201304/jmg_1207.jpg | 1 -
+ 201304/jmg_1208.jpg | 1 -
+ 201304/jmg_1209.jpg | 1 -
+ 201304/jmg_1210.cr2 | 1 -
+ 201304/jmg_1210.jpg | 1 -
+ 201304/jmg_1211.jpg | 1 -
+ 201304/jmg_1212.jpg | 1 -
+ 201304/jmg_1213.jpg | 1 -
+ 201304/jmg_1214.cr2 | 1 -
+ 201304/jmg_1214.jpg | 1 -
+ 201304/jmg_1215.jpg | 1 -
+ 201304/jmg_1216.cr2 | 1 -
+ 201304/jmg_1216.jpg | 1 -
+ 201304/jmg_1217.cr2 | 1 -
+ 201304/jmg_1217.jpg | 1 -
+ 201304/jmg_1220.cr2 | 1 -
+ 201304/jmg_1220.jpg | 1 -
+ 201304/jmg_1222.cr2 | 1 -
+ 201304/jmg_1222.jpg | 1 -
+ 201304/jmg_1223.jpg | 1 -
+ 201306/jmg_1465.jpg | 1 -
+ 201306/jmg_1466.jpg | 1 -
+ 201306/jmg_1467.jpg | 1 -
+ 201306/jmg_1468.jpg | 1 -
+ 201306/jmg_1469.jpg | 1 -
+ 201306/jmg_1470.jpg | 1 -
+ 201306/jmg_1471.jpg | 1 -
+ 201306/jmg_1472.jpg | 1 -
+ 201306/jmg_1473.jpg | 1 -
+ 201306/jmg_1475.jpg | 1 -
+ 201306/jmg_1476.jpg | 1 -
+ 201306/jmg_1477.jpg | 1 -
+ 201306/jmg_1478.jpg | 1 -
+ 201306/jmg_1479.jpg | 1 -
+ 201306/jmg_1480.jpg | 1 -
+ 201306/jmg_1481.jpg | 1 -
+ 201306/jmg_1482.jpg | 1 -
+ 201306/jmg_1483.jpg | 1 -
+ 201306/jmg_1484.jpg | 1 -
+ 201306/jmg_1485.jpg | 1 -
+ 201306/jmg_1486.jpg | 1 -
+ 201306/jmg_1487.jpg | 1 -
+ 201306/jmg_1488.jpg | 1 -
+ 201306/jmg_1489.jpg | 1 -
+ 201306/jmg_1490.jpg | 1 -
+ 201306/jmg_1491.jpg | 1 -
+ 201306/jmg_1492.jpg | 1 -
+ 201306/jmg_1495.jpg | 1 -
+ 201306/jmg_1496.jpg | 1 -
+ 201306/jmg_1498.jpg | 1 -
+ 201306/jmg_1499.jpg | 1 -
+ 201306/jmg_1500.jpg | 1 -
+ 201306/jmg_1501.jpg | 1 -
+ 201306/jmg_1502.jpg | 1 -
+ 201306/jmg_1504.jpg | 1 -
+ 201306/jmg_1506.jpg | 1 -
+ 201306/jmg_1510.jpg | 1 -
+ 201306/jmg_1512.jpg | 1 -
+ 201306/jmg_1513.jpg | 1 -
+ 201306/jmg_1514.jpg | 1 -
+ 201306/jmg_1515.jpg | 1 -
+ 201306/jmg_1517.jpg | 1 -
+ 201306/jmg_1520.jpg | 1 -
+ 201306/jmg_1521.jpg | 1 -
+ 201306/jmg_1526.jpg | 1 -
+ 201306/jmg_1533.jpg | 1 -
+ 201306/jmg_1540.jpg | 1 -
+ 201306/jmg_1546.jpg | 1 -
+ 201306/jmg_1547.jpg | 1 -
+ 201306/jmg_1549.jpg | 1 -
+ 201306/jmg_1550.jpg | 1 -
+ 201306/jmg_1551.jpg | 1 -
+ 201306/jmg_1552.jpg | 1 -
+ 201306/jmg_1553.jpg | 1 -
+ 201306/jmg_1555.jpg | 1 -
+ 201306/jmg_1556.jpg | 1 -
+ 201306/jmg_1557.jpg | 1 -
+ 201306/jmg_1558.jpg | 1 -
+ 201306/jmg_1559.jpg | 1 -
+ 201306/jmg_1560.jpg | 1 -
+ 201306/jmg_1562.jpg | 1 -
+ 201306/jmg_1566.jpg | 1 -
+ 201306/jmg_1568.jpg | 1 -
+ 201306/jmg_1570.jpg | 1 -
+ 201306/jmg_1571.jpg | 1 -
+ 201306/jmg_1572.jpg | 1 -
+ 201306/jmg_1574.jpg | 1 -
+ 201306/jmg_1575.jpg | 1 -
+ 201306/jmg_1576.jpg | 1 -
+ 201306/jmg_1577.jpg | 1 -
+ 201306/jmg_1578.jpg | 1 -
+ 201306/jmg_1579.jpg | 1 -
+ 201306/jmg_1579_raw.jpg | 1 -
+ 201306/jmg_1581.jpg | 1 -
+ 201306/jmg_1583.jpg | 1 -
+ 201306/jmg_1583_cut.jpg | 1 -
+ 201306/jmg_1583_raw.jpg | 1 -
+ 201306/jmg_1584.jpg | 1 -
+ 201306/jmg_1586.jpg | 1 -
+ 201306/jmg_1587.jpg | 1 -
+ 201306/jmg_1588.jpg | 1 -
+ 201306/jmg_1589.jpg | 1 -
+ 201306/jmg_1591.jpg | 1 -
+ 201306/jmg_1592.jpg | 1 -
+ 201306/jmg_1593.jpg | 1 -
+ 201306/jmg_1593_raw.jpg | 1 -
+ 201306/jmg_1594.jpg | 1 -
+ 201306/jmg_1594_raw.jpg | 1 -
+ 201306/jmg_1595.jpg | 1 -
+ 201306/jmg_1596.jpg | 1 -
+ 201306/jmg_1597.jpg | 1 -
+ 201306/jmg_1599.jpg | 1 -
+ 201306/jmg_1626.jpg | 1 -
+ 201306/jmg_1628.jpg | 1 -
+ 201306/jmg_1629.jpg | 1 -
+ 201306/jmg_1630.jpg | 1 -
+ 201306/jmg_1631.jpg | 1 -
+ 201306/jmg_1633.jpg | 1 -
+ 201306/jmg_1635.jpg | 1 -
+ 201306/jmg_1636.jpg | 1 -
+ 201306/jmg_1637.jpg | 1 -
+ 201306/jmg_1638.jpg | 1 -
+ 201306/jmg_1640.jpg | 1 -
+ 201306/jmg_1642.jpg | 1 -
+ 201306/jmg_1643.jpg | 1 -
+ 201306/jmg_1644.jpg | 1 -
+ 201306/jmg_1647.jpg | 1 -
+ 201306/jmg_1649.jpg | 1 -
+ 201306/jmg_1650.jpg | 1 -
+ 201306/jmg_1651.jpg | 1 -
+ 201306/jmg_1652.jpg | 1 -
+ 201306/jmg_1653.jpg | 1 -
+ 201306/jmg_1655.jpg | 1 -
+ 201306/jmg_1656.jpg | 1 -
+ 201306/jmg_1660.jpg | 1 -
+ 201306/jmg_1667.jpg | 1 -
+ 201306/jmg_1682.jpg | 1 -
+ 201306/jmg_1688.jpg | 1 -
+ 201306/jmg_1689.jpg | 1 -
+ 201306/jmg_1701.jpg | 1 -
+ 201306/jmg_1702.jpg | 1 -
+ 201306/jmg_1703.jpg | 1 -
+ 201306/jmg_1710.jpg | 1 -
+ 201306/jmg_1710_raw.jpg | 1 -
+ 201306/jmg_1715.jpg | 1 -
+ 201306/jmg_1716.jpg | 1 -
+ 201306/jmg_1719.jpg | 1 -
+ 201306/jmg_1722.jpg | 1 -
+ 201306/jmg_1723.jpg | 1 -
+ 201306/jmg_1729.cr2 | 1 -
+ 201308/jmg_2038.jpg | 1 -
+ 201308/jmg_2039.jpg | 1 -
+ 201308/jmg_2040.jpg | 1 -
+ 201308/jmg_2041.jpg | 1 -
+ 201308/jmg_2042.jpg | 1 -
+ 201308/jmg_2043.jpg | 1 -
+ 201308/jmg_2045.jpg | 1 -
+ 201308/jmg_2047.jpg | 1 -
+ 201308/jmg_2048.jpg | 1 -
+ 201308/jmg_2049.jpg | 1 -
+ 201308/jmg_2050.jpg | 1 -
+ 201308/jmg_2051.jpg | 1 -
+ 201308/jmg_2052.jpg | 1 -
+ 201308/jmg_2053.jpg | 1 -
+ 201308/jmg_2054.jpg | 1 -
+ 201308/jmg_2055.jpg | 1 -
+ 201308/jmg_2056.jpg | 1 -
+ 201308/jmg_2057.jpg | 1 -
+ 201308/jmg_2058.jpg | 1 -
+ 201308/jmg_2059.jpg | 1 -
+ 201308/jmg_2060.jpg | 1 -
+ 201308/jmg_2061.jpg | 1 -
+ 201308/jmg_2062.jpg | 1 -
+ 201308/jmg_2089.cr2 | 1 -
+ 201308/jmg_2089.jpg | 1 -
+ 201308/jmg_2089_raw.jpg | 1 -
+ 201308/jmg_2090.jpg | 1 -
+ 201308/jmg_2091.jpg | 1 -
+ 201308/jmg_2092.jpg | 1 -
+ 201308/jmg_2093.jpg | 1 -
+ 201308/jmg_2096.jpg | 1 -
+ 201308/jmg_2097.jpg | 1 -
+ 201308/jmg_2098.jpg | 1 -
+ 201308/jmg_2099.cr2 | 1 -
+ 201308/jmg_2099.jpg | 1 -
+ 201308/jmg_2099_raw.jpg | 1 -
+ 201308/jmg_2100.cr2 | 1 -
+ 201308/jmg_2100.jpg | 1 -
+ 201308/jmg_2100_raw.jpg | 1 -
+ 201308/jmg_2102.jpg | 1 -
+ 201308/jmg_2103.jpg | 1 -
+ 201308/jmg_2104.jpg | 1 -
+ 201308/jmg_2105.jpg | 1 -
+ 201308/jmg_2106.jpg | 1 -
+ 201308/jmg_2107.jpg | 1 -
+ 201308/jmg_2108.jpg | 1 -
+ 201308/jmg_2109.jpg | 1 -
+ 201308/jmg_2110.jpg | 1 -
+ 201308/jmg_2111.jpg | 1 -
+ 201308/jmg_2112.jpg | 1 -
+ 201308/jmg_2113.jpg | 1 -
+ 201308/jmg_2114.jpg | 1 -
+ 201308/jmg_2115.jpg | 1 -
+ 201308/jmg_2117.jpg | 1 -
+ 201308/jmg_2118.jpg | 1 -
+ 201308/jmg_2119.jpg | 1 -
+ 201308/jmg_2120.jpg | 1 -
+ 201308/jmg_2122.jpg | 1 -
+ 201308/jmg_2125.jpg | 1 -
+ 201308/jmg_2127.jpg | 1 -
+ 201308/jmg_2129.jpg | 1 -
+ 201308/jmg_2130.jpg | 1 -
+ 201308/jmg_2132.jpg | 1 -
+ 201308/jmg_2134.jpg | 1 -
+ 201308/jmg_2135.jpg | 1 -
+ 201308/jmg_2136.jpg | 1 -
+ 201308/jmg_2137.jpg | 1 -
+ 201308/jmg_2138.jpg | 1 -
+ 201308/jmg_2148.jpg | 1 -
+ 201308/jmg_2150.jpg | 1 -
+ 201308/jmg_2151.jpg | 1 -
+ 201308/jmg_2156.jpg | 1 -
+ 201308/jmg_2158.cr2 | 1 -
+ 201308/jmg_2158.jpg | 1 -
+ 201308/jmg_2159.jpg | 1 -
+ 201308/jmg_2160.jpg | 1 -
+ 201308/jmg_2161.jpg | 1 -
+ 201308/jmg_2162.jpg | 1 -
+ 201308/jmg_2165.jpg | 1 -
+ 201308/jmg_2166.jpg | 1 -
+ 201308/jmg_2168.jpg | 1 -
+ 201308/jmg_2169.jpg | 1 -
+ 201308/jmg_2171.jpg | 1 -
+ 201308/jmg_2173.jpg | 1 -
+ 201308/jmg_2174.jpg | 1 -
+ 201308/jmg_2175.jpg | 1 -
+ 201308/jmg_2177.jpg | 1 -
+ 201308/jmg_2178.jpg | 1 -
+ 201308/jmg_2180.jpg | 1 -
+ 201308/jmg_2181.jpg | 1 -
+ 201308/jmg_2182.jpg | 1 -
+ 201308/jmg_2183.jpg | 1 -
+ 201308/jmg_2184.jpg | 1 -
+ 201308/jmg_2187.jpg | 1 -
+ 201308/jmg_2188.jpg | 1 -
+ 201308/jmg_2189.jpg | 1 -
+ 201308/jmg_2191.cr2 | 1 -
+ 201308/jmg_2191.jpg | 1 -
+ 201308/jmg_2193.cr2 | 1 -
+ 201308/jmg_2193.jpg | 1 -
+ 201308/jmg_2194.cr2 | 1 -
+ 201308/jmg_2194.jpg | 1 -
+ 201308/jmg_2197.cr2 | 1 -
+ 201308/jmg_2197.jpg | 1 -
+ 201308/jmg_2200.cr2 | 1 -
+ 201308/jmg_2200.jpg | 1 -
+ 201308/jmg_2201.cr2 | 1 -
+ 201308/jmg_2201.jpg | 1 -
+ 201308/jmg_2202.cr2 | 1 -
+ 201308/jmg_2202.jpg | 1 -
+ 201308/jmg_2209.jpg | 1 -
+ 201308/jmg_2210.jpg | 1 -
+ 201308/jmg_2215.jpg | 1 -
+ 201308/jmg_2216.jpg | 1 -
+ 201308/jmg_2217.cr2 | 1 -
+ 201308/jmg_2217.jpg | 1 -
+ 201308/jmg_2219.cr2 | 1 -
+ 201308/jmg_2219.jpg | 1 -
+ 201308/jmg_2223.jpg | 1 -
+ 201308/jmg_2224.jpg | 1 -
+ 201308/jmg_2225.cr2 | 1 -
+ 201308/jmg_2225.jpg | 1 -
+ 201308/jmg_2227.jpg | 1 -
+ 201308/jmg_2228.jpg | 1 -
+ 201308/jmg_2235.jpg | 1 -
+ 201308/jmg_2237.jpg | 1 -
+ 201308/jmg_2238.jpg | 1 -
+ 201308/jmg_2239.cr2 | 1 -
+ 201308/jmg_2239.jpg | 1 -
+ 201308/jmg_2239_raw.jpg | 1 -
+ 201308/jmg_2240.jpg | 1 -
+ 201308/jmg_2243.jpg | 1 -
+ 201308/jmg_2244.jpg | 1 -
+ 201308/jmg_2245.jpg | 1 -
+ 201308/jmg_2247.cr2 | 1 -
+ 201308/jmg_2247.jpg | 1 -
+ 201308/jmg_2249.jpg | 1 -
+ 201308/jmg_2250.cr2 | 1 -
+ 201308/jmg_2250.jpg | 1 -
+ 201308/jmg_2252.jpg | 1 -
+ 201308/jmg_2253.jpg | 1 -
+ 201308/jmg_2254.jpg | 1 -
+ incoming/5d/201203/jmg_8701.cr2 | 1 +
+ incoming/5d/201203/jmg_8702.jpg | 1 +
+ incoming/5d/201203/jmg_8705.jpg | 1 +
+ incoming/5d/201203/jmg_8711.jpg | 1 +
+ incoming/5d/201203/jmg_8717.jpg | 1 +
+ incoming/5d/201203/jmg_8718.jpg | 1 +
+ incoming/5d/201203/jmg_8719.jpg | 1 +
+ incoming/5d/201203/jmg_8721.jpg | 1 +
+ incoming/5d/201203/jmg_8725.jpg | 1 +
+ incoming/5d/201203/jmg_8726.jpg | 1 +
+ incoming/5d/201203/jmg_8731.jpg | 1 +
+ incoming/5d/201203/jmg_8745.jpg | 1 +
+ incoming/5d/201203/jmg_8747_raw.jpg | 1 +
+ incoming/5d/201203/jmg_8750.cr2 | 1 +
+ incoming/5d/201203/jmg_8750.jpg | 1 +
+ incoming/5d/201207/jmg_9048.jpg | 1 +
+ incoming/5d/201207/jmg_9053.jpg | 1 +
+ incoming/5d/201207/jmg_9054.jpg | 1 +
+ incoming/5d/201207/jmg_9069.cr2 | 1 +
+ incoming/5d/201207/jmg_9069.jpg | 1 +
+ incoming/5d/201207/jmg_9070.cr2 | 1 +
+ incoming/5d/201207/jmg_9070.jpg | 1 +
+ incoming/5d/201207/jmg_9072.cr2 | 1 +
+ incoming/5d/201207/jmg_9072.jpg | 1 +
+ incoming/5d/201207/jmg_9076.cr2 | 1 +
+ incoming/5d/201207/jmg_9076.jpg | 1 +
+ incoming/5d/201302/jmg_0502.cr2 | 1 +
+ incoming/5d/201302/jmg_0502.jpg | 1 +
+ incoming/5d/201302/jmg_0503.jpg | 1 +
+ incoming/5d/201302/jmg_0507.jpg | 1 +
+ incoming/5d/201302/jmg_0510.jpg | 1 +
+ incoming/5d/201302/jmg_0512.jpg | 1 +
+ incoming/5d/201302/jmg_0513.jpg | 1 +
+ incoming/5d/201302/jmg_0514.jpg | 1 +
+ incoming/5d/201302/jmg_0516.jpg | 1 +
+ incoming/5d/201302/jmg_0517.jpg | 1 +
+ incoming/5d/201302/jmg_0518.jpg | 1 +
+ incoming/5d/201302/jmg_0521.jpg | 1 +
+ incoming/5d/201302/jmg_0522.jpg | 1 +
+ incoming/5d/201302/jmg_0523.jpg | 1 +
+ incoming/5d/201302/jmg_0524.jpg | 1 +
+ incoming/5d/201302/jmg_0526.jpg | 1 +
+ incoming/5d/201302/jmg_0527.jpg | 1 +
+ incoming/5d/201302/jmg_0528.jpg | 1 +
+ incoming/5d/201302/jmg_0532.cr2 | 1 +
+ incoming/5d/201302/jmg_0532.jpg | 1 +
+ incoming/5d/201302/jmg_0534.jpg | 1 +
+ incoming/5d/201302/jmg_0535.jpg | 1 +
+ incoming/5d/201302/jmg_0537.jpg | 1 +
+ incoming/5d/201302/jmg_0539.jpg | 1 +
+ incoming/5d/201302/jmg_0541.jpg | 1 +
+ incoming/5d/201302/jmg_0543.jpg | 1 +
+ incoming/5d/jmg_0021.jpg | 1 +
+ incoming/5d/jmg_0025.jpg | 1 +
+ incoming/5d/jmg_0026.jpg | 1 +
+ incoming/5d/jmg_0027.jpg | 1 +
+ incoming/5d/jmg_0034.jpg | 1 +
+ incoming/5d/jmg_0035.jpg | 1 +
+ incoming/5d/jmg_0036.jpg | 1 +
+ incoming/5d/jmg_0130.jpg | 1 +
+ incoming/5d/jmg_0131.jpg | 1 +
+ incoming/5d/jmg_0133.jpg | 1 +
+ incoming/5d/jmg_0155.jpg | 1 +
+ incoming/5d/jmg_0156.jpg | 1 +
+ incoming/5d/jmg_0158.cr2 | 1 +
+ incoming/5d/jmg_0165.cr2 | 1 +
+ incoming/5d/jmg_0166.cr2 | 1 +
+ incoming/5d/jmg_0178.cr2 | 1 +
+ incoming/5d/jmg_0179.jpg | 1 +
+ incoming/5d/jmg_0180.cr2 | 1 +
+ incoming/5d/jmg_0184.jpg | 1 +
+ incoming/5d/jmg_0185.cr2 | 1 +
+ incoming/5d/jmg_0187.cr2 | 1 +
+ incoming/5d/jmg_0310.jpg | 1 +
+ incoming/5d/jmg_0312.jpg | 1 +
+ incoming/5d/jmg_0315.jpg | 1 +
+ incoming/5d/jmg_0340.jpg | 1 +
+ incoming/5d/jmg_0357.jpg | 1 +
+ incoming/5d/jmg_0364.jpg | 1 +
+ incoming/5d/jmg_0365.jpg | 1 +
+ incoming/5d/jmg_0368.jpg | 1 +
+ incoming/5d/jmg_0374.jpg | 1 +
+ incoming/5d/jmg_0375.jpg | 1 +
+ incoming/5d/jmg_0386.jpg | 1 +
+ incoming/5d/jmg_0399.jpg | 1 +
+ incoming/5d/jmg_0411.jpg | 1 +
+ incoming/5d/jmg_0418.jpg | 1 +
+ incoming/5d/jmg_0476.cr2 | 1 +
+ incoming/5d/jmg_0476.jpg | 1 +
+ incoming/5d/jmg_0503.jpg | 1 +
+ incoming/5d/jmg_0507.cr2 | 1 +
+ incoming/5d/jmg_0513.cr2 | 1 +
+ incoming/5d/jmg_0513.jpg | 1 +
+ incoming/5d/jmg_0516.cr2 | 1 +
+ incoming/5d/jmg_0517.cr2 | 1 +
+ incoming/5d/jmg_0518.jpg | 1 +
+ incoming/5d/jmg_0522.cr2 | 1 +
+ incoming/5d/jmg_0524.cr2 | 1 +
+ incoming/5d/jmg_0524.jpg | 1 +
+ incoming/5d/jmg_0530.jpg | 1 +
+ incoming/5d/jmg_0541.cr2 | 1 +
+ incoming/5d/jmg_0550.jpg | 1 +
+ incoming/5d/jmg_0554.jpg | 1 +
+ incoming/5d/jmg_0555.jpg | 1 +
+ incoming/5d/jmg_0558.jpg | 1 +
+ incoming/5d/jmg_0563.jpg | 1 +
+ incoming/5d/jmg_0573.jpg | 1 +
+ incoming/5d/jmg_0575.cr2 | 1 +
+ incoming/5d/jmg_0578.cr2 | 1 +
+ incoming/5d/jmg_0579.cr2 | 1 +
+ incoming/5d/jmg_0582.jpg | 1 +
+ incoming/5d/jmg_0593.cr2 | 1 +
+ incoming/5d/jmg_0594.cr2 | 1 +
+ incoming/5d/jmg_0594.jpg | 1 +
+ incoming/5d/jmg_0595.cr2 | 1 +
+ incoming/5d/jmg_0600.jpg | 1 +
+ incoming/5d/jmg_0606.cr2 | 1 +
+ incoming/5d/jmg_0607.jpg | 1 +
+ incoming/5d/jmg_0610.cr2 | 1 +
+ incoming/5d/jmg_0610.jpg | 1 +
+ incoming/5d/jmg_0612.jpg | 1 +
+ incoming/5d/jmg_0613.cr2 | 1 +
+ incoming/5d/jmg_0614.jpg | 1 +
+ incoming/5d/jmg_0619.cr2 | 1 +
+ incoming/5d/jmg_0623.jpg | 1 +
+ incoming/5d/jmg_0628.cr2 | 1 +
+ incoming/5d/jmg_0628.jpg | 1 +
+ incoming/5d/jmg_0639.jpg | 1 +
+ incoming/5d/jmg_0645.cr2 | 1 +
+ incoming/5d/jmg_0646.jpg | 1 +
+ incoming/5d/jmg_0647.cr2 | 1 +
+ incoming/5d/jmg_0648.jpg | 1 +
+ incoming/5d/jmg_0649.jpg | 1 +
+ incoming/5d/jmg_0655.jpg | 1 +
+ incoming/5d/jmg_0667.jpg | 1 +
+ incoming/5d/jmg_0670.jpg | 1 +
+ incoming/5d/jmg_0673.jpg | 1 +
+ incoming/5d/jmg_0679.jpg | 1 +
+ incoming/5d/jmg_0685.jpg | 1 +
+ incoming/5d/jmg_0699.cr2 | 1 +
+ incoming/5d/jmg_0700.cr2 | 1 +
+ incoming/5d/jmg_0701.cr2 | 1 +
+ incoming/5d/jmg_0708.jpg | 1 +
+ incoming/5d/jmg_0718.jpg | 1 +
+ incoming/5d/jmg_0726.cr2 | 1 +
+ incoming/5d/jmg_0728.jpg | 1 +
+ incoming/5d/jmg_0730.jpg | 1 +
+ incoming/5d/jmg_0734.jpg | 1 +
+ incoming/5d/jmg_0740.jpg | 1 +
+ incoming/5d/jmg_0743.cr2 | 1 +
+ incoming/5d/jmg_0744.cr2 | 1 +
+ incoming/5d/jmg_0745.cr2 | 1 +
+ incoming/5d/jmg_0747.jpg | 1 +
+ incoming/5d/jmg_0750.cr2 | 1 +
+ incoming/5d/jmg_0755.cr2 | 1 +
+ incoming/5d/jmg_0759.cr2 | 1 +
+ incoming/5d/jmg_0760.cr2 | 1 +
+ incoming/5d/jmg_0761.jpg | 1 +
+ incoming/5d/jmg_0765.jpg | 1 +
+ incoming/5d/jmg_0768.jpg | 1 +
+ incoming/5d/jmg_0771.jpg | 1 +
+ incoming/5d/jmg_0778.jpg | 1 +
+ incoming/5d/jmg_0780.jpg | 1 +
+ incoming/5d/jmg_0782.cr2 | 1 +
+ incoming/5d/jmg_0786.cr2 | 1 +
+ incoming/5d/jmg_0787.cr2 | 1 +
+ incoming/5d/jmg_0788.cr2 | 1 +
+ incoming/5d/jmg_0794.jpg | 1 +
+ incoming/5d/jmg_0796.jpg | 1 +
+ incoming/5d/jmg_0801.cr2 | 1 +
+ incoming/5d/jmg_0803.cr2 | 1 +
+ incoming/5d/jmg_0804.cr2 | 1 +
+ incoming/5d/jmg_0812.jpg | 1 +
+ incoming/5d/jmg_0819.jpg | 1 +
+ incoming/5d/jmg_0827.jpg | 1 +
+ incoming/5d/jmg_0830.jpg | 1 +
+ incoming/5d/jmg_0842.jpg | 1 +
+ incoming/5d/jmg_0846.jpg | 1 +
+ incoming/5d/jmg_0857.cr2 | 1 +
+ incoming/5d/jmg_0863.jpg | 1 +
+ incoming/5d/jmg_0866.cr2 | 1 +
+ incoming/5d/jmg_0868.cr2 | 1 +
+ incoming/5d/jmg_0868.jpg | 1 +
+ incoming/5d/jmg_0870.jpg | 1 +
+ incoming/5d/jmg_0877.jpg | 1 +
+ incoming/5d/jmg_0882.cr2 | 1 +
+ incoming/5d/jmg_0883.jpg | 1 +
+ incoming/5d/jmg_0888.jpg | 1 +
+ incoming/5d/jmg_0891.jpg | 1 +
+ incoming/5d/jmg_0894.cr2 | 1 +
+ incoming/5d/jmg_0896.cr2 | 1 +
+ incoming/5d/jmg_0897.cr2 | 1 +
+ incoming/5d/jmg_0898.jpg | 1 +
+ incoming/5d/jmg_0899.cr2 | 1 +
+ incoming/5d/jmg_0900.jpg | 1 +
+ incoming/5d/jmg_0905.jpg | 1 +
+ incoming/5d/jmg_0908.jpg | 1 +
+ incoming/5d/jmg_0914.jpg | 1 +
+ incoming/5d/jmg_0915.jpg | 1 +
+ incoming/5d/jmg_0916.jpg | 1 +
+ incoming/5d/jmg_0923.jpg | 1 +
+ incoming/5d/jmg_0924.jpg | 1 +
+ incoming/5d/jmg_0926.jpg | 1 +
+ incoming/5d/jmg_0928.jpg | 1 +
+ incoming/5d/jmg_0929.jpg | 1 +
+ incoming/5d/jmg_0936.jpg | 1 +
+ incoming/5d/jmg_0942.jpg | 1 +
+ incoming/5d/jmg_0944.jpg | 1 +
+ incoming/5d/jmg_0948.jpg | 1 +
+ incoming/5d/jmg_0960.jpg | 1 +
+ incoming/5d/jmg_0966.jpg | 1 +
+ incoming/5d/jmg_0970.cr2 | 1 +
+ incoming/5d/jmg_0970.jpg | 1 +
+ incoming/5d/jmg_0972.jpg | 1 +
+ incoming/5d/jmg_0976.jpg | 1 +
+ incoming/5d/jmg_0983.cr2 | 1 +
+ incoming/5d/jmg_0985.cr2 | 1 +
+ incoming/5d/jmg_0985.jpg | 1 +
+ incoming/5d/jmg_0994.jpg | 1 +
+ incoming/5d/jmg_1005.jpg | 2 +-
+ incoming/5d/jmg_1009.jpg | 2 +-
+ incoming/5d/jmg_1012.jpg | 2 +-
+ incoming/5d/jmg_1020.jpg | 2 +-
+ incoming/5d/jmg_1021.jpg | 2 +-
+ incoming/5d/jmg_1032.jpg | 2 +-
+ incoming/5d/jmg_1033.jpg | 2 +-
+ incoming/5d/jmg_1037.jpg | 2 +-
+ incoming/5d/jmg_1039.jpg | 2 +-
+ incoming/5d/jmg_1048.jpg | 2 +-
+ incoming/5d/jmg_1051.jpg | 2 +-
+ incoming/5d/jmg_1063.jpg | 2 +-
+ incoming/5d/jmg_1064.jpg | 2 +-
+ incoming/5d/jmg_1067.jpg | 2 +-
+ incoming/5d/jmg_1116.jpg | 2 +-
+ incoming/5d/jmg_1118.jpg | 2 +-
+ incoming/5d/jmg_1125.jpg | 2 +-
+ incoming/5d/jmg_1126.jpg | 2 +-
+ incoming/5d/jmg_1129.jpg | 2 +-
+ incoming/5d/jmg_1133.jpg | 2 +-
+ incoming/5d/jmg_1138.jpg | 2 +-
+ incoming/5d/jmg_1139.jpg | 2 +-
+ incoming/5d/jmg_1143.jpg | 2 +-
+ incoming/5d/jmg_1149.jpg | 2 +-
+ incoming/5d/jmg_1150.jpg | 2 +-
+ incoming/5d/jmg_1155.jpg | 2 +-
+ incoming/5d/jmg_1160.jpg | 2 +-
+ incoming/5d/jmg_1168.jpg | 2 +-
+ incoming/5d/jmg_1173.jpg | 2 +-
+ incoming/5d/jmg_1175.jpg | 2 +-
+ incoming/5d/jmg_1177.jpg | 2 +-
+ incoming/5d/jmg_1179.jpg | 2 +-
+ incoming/5d/jmg_1183.jpg | 2 +-
+ incoming/5d/jmg_1185.jpg | 2 +-
+ incoming/5d/jmg_1189.jpg | 2 +-
+ incoming/5d/jmg_1192.jpg | 2 +-
+ incoming/5d/jmg_1199.jpg | 2 +-
+ incoming/5d/jmg_1205.jpg | 2 +-
+ incoming/5d/jmg_1209.cr2 | 1 +
+ incoming/5d/jmg_1209.jpg | 1 +
+ incoming/5d/jmg_1211.cr2 | 1 +
+ incoming/5d/jmg_1211.jpg | 1 +
+ incoming/5d/jmg_1217.cr2 | 1 +
+ incoming/5d/jmg_1467.cr2 | 1 +
+ incoming/5d/jmg_1469.jpg | 1 +
+ incoming/5d/jmg_1470.cr2 | 1 +
+ incoming/5d/jmg_1471.cr2 | 1 +
+ incoming/5d/jmg_1472.cr2 | 1 +
+ incoming/5d/jmg_1477.cr2 | 1 +
+ incoming/5d/jmg_1477.jpg | 1 +
+ incoming/5d/jmg_1481.cr2 | 1 +
+ incoming/5d/jmg_1483.cr2 | 1 +
+ incoming/5d/jmg_1485.jpg | 1 +
+ incoming/5d/jmg_1488.jpg | 1 +
+ incoming/5d/jmg_1491.jpg | 1 +
+ incoming/5d/jmg_1496.cr2 | 1 +
+ incoming/5d/jmg_1502.jpg | 1 +
+ incoming/5d/jmg_1503.cr2 | 1 +
+ incoming/5d/jmg_1504.jpg | 1 +
+ incoming/5d/jmg_1507.jpg | 1 +
+ incoming/5d/jmg_1515.jpg | 1 +
+ incoming/5d/jmg_1520.jpg | 1 +
+ incoming/5d/jmg_1523.jpg | 1 +
+ incoming/5d/jmg_1525.jpg | 1 +
+ incoming/5d/jmg_1539.jpg | 1 +
+ incoming/5d/jmg_1542.jpg | 1 +
+ incoming/5d/jmg_1546.jpg | 1 +
+ incoming/5d/jmg_1547.cr2 | 1 +
+ incoming/5d/jmg_1549.jpg | 1 +
+ incoming/5d/jmg_1552.jpg | 1 +
+ incoming/5d/jmg_1554.cr2 | 1 +
+ incoming/5d/jmg_1555.cr2 | 1 +
+ incoming/5d/jmg_1556.cr2 | 1 +
+ incoming/5d/jmg_1559.cr2 | 1 +
+ incoming/5d/jmg_1560.cr2 | 1 +
+ incoming/5d/jmg_1561.cr2 | 1 +
+ incoming/5d/jmg_1562.cr2 | 1 +
+ incoming/5d/jmg_1565.cr2 | 1 +
+ incoming/5d/jmg_1567.cr2 | 1 +
+ incoming/5d/jmg_1572.cr2 | 1 +
+ incoming/5d/jmg_1577.cr2 | 1 +
+ incoming/5d/jmg_1578.jpg | 1 +
+ incoming/5d/jmg_1583_cut.jpg | 1 +
+ incoming/5d/jmg_1583_raw.jpg | 1 +
+ incoming/5d/jmg_1592.cr2 | 1 +
+ incoming/5d/jmg_1593.jpg | 1 +
+ incoming/5d/jmg_1626.cr2 | 1 +
+ incoming/5d/jmg_1627.jpg | 1 +
+ incoming/5d/jmg_1628.cr2 | 1 +
+ incoming/5d/jmg_1629.jpg | 1 +
+ incoming/5d/jmg_1630.cr2 | 1 +
+ incoming/5d/jmg_1631.cr2 | 1 +
+ incoming/5d/jmg_1633.cr2 | 1 +
+ incoming/5d/jmg_1638.jpg | 1 +
+ incoming/5d/jmg_1639.cr2 | 1 +
+ incoming/5d/jmg_1646.cr2 | 1 +
+ incoming/5d/jmg_1646.jpg | 1 +
+ incoming/5d/jmg_1650.jpg | 1 +
+ incoming/5d/jmg_1651.cr2 | 1 +
+ incoming/5d/jmg_1654.cr2 | 1 +
+ incoming/5d/jmg_1656.jpg | 1 +
+ incoming/5d/jmg_1677.jpg | 1 +
+ incoming/5d/jmg_1689.jpg | 1 +
+ incoming/5d/jmg_1701.jpg | 1 +
+ incoming/5d/jmg_1703.jpg | 1 +
+ incoming/5d/jmg_1723.jpg | 1 +
+ incoming/5d/jmg_2039.jpg | 1 +
+ incoming/5d/jmg_2041.jpg | 1 +
+ incoming/5d/jmg_2048.cr2 | 1 +
+ incoming/5d/jmg_2052.jpg | 1 +
+ incoming/5d/jmg_2061.jpg | 1 +
+ incoming/5d/jmg_2064_raw.jpg | 1 -
+ incoming/5d/jmg_2065_mo.jpg | 1 -
+ incoming/5d/jmg_2065_raw.jpg | 1 -
+ incoming/5d/jmg_2066_mo.jpg | 1 -
+ incoming/5d/jmg_2066_raw.jpg | 1 -
+ incoming/5d/jmg_2090.jpg | 1 +
+ incoming/5d/jmg_2093.jpg | 1 +
+ incoming/5d/jmg_2100.cr2 | 1 +
+ incoming/5d/jmg_2103.jpg | 1 +
+ incoming/5d/jmg_2107.jpg | 1 +
+ incoming/5d/jmg_2108.jpg | 1 +
+ incoming/5d/jmg_2112.jpg | 1 +
+ incoming/5d/jmg_2118.jpg | 1 +
+ incoming/5d/jmg_2119.jpg | 1 +
+ incoming/5d/jmg_2122.jpg | 1 +
+ incoming/5d/jmg_2125.jpg | 1 +
+ incoming/5d/jmg_2137.jpg | 1 +
+ incoming/5d/jmg_2149.jpg | 1 +
+ incoming/5d/jmg_2150.jpg | 1 +
+ incoming/5d/jmg_2158.cr2 | 1 +
+ incoming/5d/jmg_2160.jpg | 1 +
+ incoming/5d/jmg_2165.jpg | 1 +
+ incoming/5d/jmg_2188.jpg | 1 +
+ incoming/5d/jmg_2189.jpg | 1 +
+ incoming/5d/jmg_2193.jpg | 1 +
+ incoming/5d/jmg_2194.cr2 | 1 +
+ incoming/5d/jmg_2200.jpg | 1 +
+ incoming/5d/jmg_2201.cr2 | 1 +
+ incoming/5d/jmg_2201.jpg | 1 +
+ incoming/5d/jmg_2210.jpg | 1 +
+ incoming/5d/jmg_2215.cr2 | 1 +
+ incoming/5d/jmg_2216.cr2 | 1 +
+ incoming/5d/jmg_2216.jpg | 1 +
+ incoming/5d/jmg_2224.jpg | 1 +
+ incoming/5d/jmg_2235.jpg | 1 +
+ incoming/5d/jmg_2238.jpg | 1 +
+ incoming/5d/jmg_2239.cr2 | 1 +
+ incoming/5d/jmg_2239.jpg | 1 +
+ incoming/5d/jmg_2240.jpg | 1 +
+ incoming/5d/jmg_2244.jpg | 1 +
+ incoming/5d/jmg_2247.jpg | 1 +
+ incoming/5d/jmg_7250.cr2 | 1 +
+ incoming/5d/jmg_7250.jpg | 1 +
+ incoming/5d/jmg_7256.jpg | 1 +
+ incoming/5d/jmg_7257.cr2 | 1 +
+ incoming/5d/jmg_7259.cr2 | 1 +
+ incoming/5d/jmg_7263.jpg | 1 +
+ incoming/5d/jmg_7265.cr2 | 1 +
+ incoming/5d/jmg_7269.cr2 | 1 +
+ incoming/5d/jmg_7270.cr2 | 1 +
+ incoming/5d/jmg_7279.cr2 | 1 +
+ incoming/5d/jmg_7286.cr2 | 1 +
+ incoming/5d/jmg_7286.jpg | 1 +
+ incoming/5d/jmg_7290.cr2 | 1 +
+ incoming/5d/jmg_7290.jpg | 1 +
+ incoming/5d/jmg_7293.cr2 | 1 +
+ incoming/5d/jmg_7296.cr2 | 1 +
+ incoming/5d/jmg_7299.jpg | 1 +
+ incoming/5d/jmg_7300.cr2 | 1 +
+ incoming/5d/jmg_7300.jpg | 1 +
+ incoming/5d/jmg_7305_raw.jpg | 1 +
+ incoming/5d/jmg_8532.cr2 | 1 +
+ incoming/5d/jmg_8533.cr2 | 1 +
+ incoming/5d/jmg_8534.cr2 | 1 +
+ incoming/5d/jmg_8536.jpg | 1 +
+ incoming/5d/jmg_8538.cr2 | 1 +
+ incoming/5d/jmg_8549.cr2 | 1 +
+ incoming/5d/jmg_8549.jpg | 1 +
+ incoming/5d/jmg_8552.cr2 | 1 +
+ incoming/5d/jmg_8557.cr2 | 1 +
+ incoming/5d/jmg_8560.cr2 | 1 +
+ incoming/5d/jmg_8565.cr2 | 1 +
+ incoming/5d/jmg_8566.cr2 | 1 +
+ incoming/5d/jmg_8569.jpg | 1 +
+ incoming/5d/jmg_8575.jpg | 1 +
+ incoming/5d/jmg_8576.jpg | 1 +
+ incoming/5d/jmg_8578.cr2 | 1 +
+ incoming/5d/jmg_8579.cr2 | 1 +
+ incoming/5d/jmg_8580.jpg | 1 +
+ incoming/5d/jmg_8583.cr2 | 1 +
+ incoming/5d/jmg_8588.cr2 | 1 +
+ incoming/5d/jmg_8589.cr2 | 1 +
+ incoming/5d/jmg_8595.jpg | 1 +
+ incoming/5d/jmg_8597.jpg | 1 +
+ incoming/5d/jmg_8599.jpg | 1 +
+ incoming/5d/jmg_8602.cr2 | 1 +
+ incoming/5d/jmg_8603.cr2 | 1 +
+ incoming/5d/jmg_8606.cr2 | 1 +
+ incoming/5d/jmg_8606.jpg | 1 +
+ incoming/5d/jmg_8609.jpg | 1 +
+ incoming/5d/jmg_8613.jpg | 1 +
+ incoming/5d/jmg_8615.cr2 | 1 +
+ incoming/5d/jmg_8617.jpg | 1 +
+ incoming/5d/jmg_8619.cr2 | 1 +
+ incoming/5d/jmg_8620.jpg | 1 +
+ incoming/5d/jmg_8625.jpg | 1 +
+ incoming/5d/jmg_8627.jpg | 1 +
+ incoming/5d/jmg_8628.jpg | 1 +
+ incoming/5d/jmg_8632.cr2 | 1 +
+ incoming/5d/jmg_8636.cr2 | 1 +
+ incoming/5d/jmg_8636.jpg | 1 +
+ incoming/5d/jmg_8637.cr2 | 1 +
+ incoming/5d/jmg_8639.jpg | 1 +
+ incoming/5d/jmg_8640.cr2 | 1 +
+ incoming/5d/jmg_8655.jpg | 1 +
+ incoming/5d/jmg_8657.jpg | 1 +
+ incoming/5d/jmg_8670.cr2 | 1 +
+ incoming/5d/jmg_8673.jpg | 1 +
+ incoming/5d/jmg_8674.cr2 | 1 +
+ incoming/5d/jmg_8676.cr2 | 1 +
+ incoming/5d/jmg_8676.jpg | 1 +
+ incoming/5d/jmg_8677.cr2 | 1 +
+ incoming/5d/jmg_8681.jpg | 1 +
+ incoming/5d/jmg_8682.cr2 | 1 +
+ incoming/5d/jmg_8702.cr2 | 1 +
+ incoming/5d/jmg_8702.jpg | 1 +
+ incoming/5d/jmg_8707.jpg | 1 +
+ incoming/5d/jmg_8714.jpg | 1 +
+ incoming/5d/jmg_8716.jpg | 1 +
+ incoming/5d/jmg_8717.cr2 | 1 +
+ incoming/5d/jmg_8719.jpg | 1 +
+ incoming/5d/jmg_8721.jpg | 1 +
+ incoming/5d/jmg_8727.cr2 | 1 +
+ incoming/5d/jmg_8730.jpg | 1 +
+ incoming/5d/jmg_8736.cr2 | 1 +
+ incoming/5d/jmg_8737.cr2 | 1 +
+ incoming/5d/jmg_8742.cr2 | 1 +
+ incoming/5d/jmg_8742.jpg | 1 +
+ incoming/5d/jmg_8745.jpg | 1 +
+ incoming/5d/jmg_8748.cr2 | 1 +
+ incoming/5d/jmg_8748.jpg | 1 +
+ incoming/5d/jmg_8751.cr2 | 1 +
+ incoming/5d/jmg_8755.cr2 | 1 +
+ incoming/5d/jmg_8757.cr2 | 1 +
+ incoming/5d/jmg_8760.cr2 | 1 +
+ incoming/5d/jmg_8760.jpg | 1 +
+ incoming/5d/jmg_8765.cr2 | 1 +
+ incoming/5d/jmg_8771.jpg | 1 +
+ incoming/5d/jmg_8801.jpg | 1 +
+ incoming/5d/jmg_8803.cr2 | 1 +
+ incoming/5d/jmg_8803.jpg | 1 +
+ incoming/5d/jmg_8804.jpg | 1 +
+ incoming/5d/jmg_8805.jpg | 1 +
+ incoming/5d/jmg_8813.jpg | 1 +
+ incoming/5d/jmg_8816.cr2 | 1 +
+ incoming/5d/jmg_8823.jpg | 1 +
+ incoming/5d/jmg_8827.cr2 | 1 +
+ incoming/5d/jmg_8829.cr2 | 1 +
+ incoming/5d/jmg_8832.jpg | 1 +
+ incoming/5d/jmg_8833.cr2 | 1 +
+ incoming/5d/jmg_8837.cr2 | 1 +
+ incoming/5d/jmg_8838.jpg | 1 +
+ incoming/5d/jmg_8840.jpg | 1 +
+ incoming/5d/jmg_8842.jpg | 1 +
+ incoming/5d/jmg_8844.cr2 | 1 +
+ incoming/5d/jmg_8850.cr2 | 1 +
+ incoming/5d/jmg_8850.jpg | 1 +
+ incoming/5d/jmg_8852.cr2 | 1 +
+ incoming/5d/jmg_8853.cr2 | 1 +
+ incoming/5d/jmg_8853.jpg | 1 +
+ incoming/5d/jmg_8856.cr2 | 1 +
+ incoming/5d/jmg_8859.jpg | 1 +
+ incoming/5d/jmg_8863.jpg | 1 +
+ incoming/5d/jmg_8870.jpg | 1 +
+ incoming/5d/jmg_8871.cr2 | 1 +
+ incoming/5d/jmg_8871.jpg | 1 +
+ incoming/5d/jmg_8881.jpg | 1 +
+ incoming/5d/jmg_8883.jpg | 1 +
+ incoming/5d/jmg_8886.jpg | 1 +
+ incoming/5d/jmg_8887.cr2 | 1 +
+ incoming/5d/jmg_8889.cr2 | 1 +
+ incoming/5d/jmg_8894.cr2 | 1 +
+ incoming/5d/jmg_8897.cr2 | 1 +
+ incoming/5d/jmg_8898.cr2 | 1 +
+ incoming/5d/jmg_8900.jpg | 1 +
+ incoming/5d/jmg_8901.cr2 | 1 +
+ incoming/5d/jmg_8902.cr2 | 1 +
+ incoming/5d/jmg_8904.cr2 | 1 +
+ incoming/5d/jmg_8906.jpg | 1 +
+ incoming/5d/jmg_8908.cr2 | 1 +
+ incoming/5d/jmg_8920.cr2 | 1 +
+ incoming/5d/jmg_8920.jpg | 1 +
+ incoming/5d/jmg_8922.cr2 | 1 +
+ incoming/5d/jmg_8922.jpg | 1 +
+ incoming/5d/jmg_8923.cr2 | 1 +
+ incoming/5d/jmg_8924.jpg | 1 +
+ incoming/5d/jmg_8925.cr2 | 1 +
+ incoming/5d/jmg_8929.jpg | 1 +
+ incoming/5d/jmg_8930.jpg | 1 +
+ incoming/5d/jmg_8937.cr2 | 1 +
+ incoming/5d/jmg_8939.cr2 | 1 +
+ incoming/5d/jmg_8940.jpg | 1 +
+ incoming/5d/jmg_8941.jpg | 1 +
+ incoming/5d/jmg_8943.cr2 | 1 +
+ incoming/5d/jmg_8944.jpg | 1 +
+ incoming/5d/jmg_8950.cr2 | 1 +
+ incoming/5d/jmg_8951.jpg | 1 +
+ incoming/5d/jmg_8955.jpg | 1 +
+ incoming/5d/jmg_8959.cr2 | 1 +
+ incoming/5d/jmg_8960.jpg | 1 +
+ incoming/5d/jmg_8962.cr2 | 1 +
+ incoming/5d/jmg_8964.cr2 | 1 +
+ incoming/5d/jmg_8965.jpg | 1 +
+ incoming/5d/jmg_8966.jpg | 1 +
+ incoming/5d/jmg_8971.jpg | 1 +
+ incoming/5d/jmg_8976.jpg | 1 +
+ incoming/5d/jmg_8978.cr2 | 1 +
+ incoming/5d/jmg_8981.jpg | 1 +
+ incoming/5d/jmg_8982.jpg | 1 +
+ incoming/5d/jmg_8985.jpg | 1 +
+ incoming/5d/jmg_8988.cr2 | 1 +
+ incoming/5d/jmg_8988.jpg | 1 +
+ incoming/5d/jmg_8992.cr2 | 1 +
+ incoming/5d/jmg_8995.jpg | 1 +
+ incoming/5d/jmg_8996.cr2 | 1 +
+ incoming/5d/jmg_8997.cr2 | 1 +
+ incoming/5d/jmg_8999.cr2 | 1 +
+ incoming/5d/jmg_9000.cr2 | 1 +
+ incoming/5d/jmg_9015.cr2 | 1 +
+ incoming/5d/jmg_9017.cr2 | 1 +
+ incoming/5d/jmg_9019.cr2 | 1 +
+ incoming/5d/jmg_9021.cr2 | 1 +
+ incoming/5d/jmg_9021.jpg | 1 +
+ incoming/5d/jmg_9022.cr2 | 1 +
+ incoming/5d/jmg_9027.cr2 | 1 +
+ incoming/5d/jmg_9028.jpg | 1 +
+ incoming/5d/jmg_9031.cr2 | 1 +
+ incoming/5d/jmg_9035.cr2 | 1 +
+ incoming/5d/jmg_9043.jpg | 1 +
+ incoming/5d/jmg_9057.cr2 | 1 +
+ incoming/5d/jmg_9064.cr2 | 1 +
+ incoming/5d/jmg_9077.jpg | 1 +
+ incoming/5d/jmg_9078.jpg | 1 +
+ incoming/5d/jmg_9081.jpg | 1 +
+ incoming/5d/jmg_9082.cr2 | 1 +
+ incoming/5d/jmg_9083.jpg | 1 +
+ incoming/5d/jmg_9086.cr2 | 1 +
+ incoming/5d/jmg_9088.jpg | 1 +
+ incoming/5d/jmg_9308.jpg | 1 +
+ incoming/5d/jmg_9312.cr2 | 1 +
+ incoming/5d/jmg_9313.jpg | 1 +
+ incoming/5d/jmg_9319.jpg | 1 +
+ incoming/5d/jmg_9521.cr2 | 1 +
+ incoming/5d/jmg_9522.cr2 | 1 +
+ incoming/5d/jmg_9533.jpg | 1 +
+ incoming/5d/jmg_9534.jpg | 1 +
+ incoming/5d/jmg_9535.cr2 | 1 +
+ incoming/5d/jmg_9538.cr2 | 1 +
+ incoming/5d/jmg_9538.jpg | 1 +
+ incoming/5d/jmg_9540.jpg | 1 +
+ incoming/5d/jmg_9542.cr2 | 1 +
+ incoming/5d/jmg_9545.jpg | 1 +
+ incoming/5d/jmg_9554.jpg | 1 +
+ incoming/5d/jmg_9555.jpg | 1 +
+ incoming/5d/jmg_9558.jpg | 1 +
+ incoming/5d/jmg_9561.cr2 | 1 +
+ incoming/5d/jmg_9585.cr2 | 1 +
+ incoming/5d/jmg_9587.jpg | 1 +
+ incoming/5d/jmg_9591.jpg | 1 +
+ incoming/5d/jmg_9595.jpg | 1 +
+ incoming/5d/jmg_9598.cr2 | 1 +
+ incoming/5d/jmg_9600.jpg | 1 +
+ incoming/5d/jmg_9604.jpg | 1 +
+ incoming/5d/jmg_9610.jpg | 1 +
+ incoming/5d/jmg_9613.cr2 | 1 +
+ incoming/5d/jmg_9613.jpg | 1 +
+ incoming/5d/jmg_9614.cr2 | 1 +
+ incoming/5d/jmg_9618.jpg | 1 +
+ incoming/5d/jmg_9619.jpg | 1 +
+ incoming/5d/jmg_9620.jpg | 1 +
+ incoming/5d/jmg_9621.jpg | 1 +
+ incoming/5d/jmg_9623.cr2 | 1 +
+ incoming/5d/jmg_9746.jpg | 1 +
+ incoming/5d/jmg_9763.cr2 | 1 +
+ incoming/5d/jmg_9763.jpg | 1 +
+ incoming/5d/jmg_9764.cr2 | 1 +
+ incoming/5d/jmg_9772.jpg | 1 +
+ incoming/5d/jmg_9773.jpg | 1 +
+ incoming/5d/jmg_9781.jpg | 1 +
+ incoming/5d/jmg_9790.jpg | 1 +
+ incoming/5d/jmg_9800.jpg | 1 +
+ incoming/5d/jmg_9808.jpg | 1 +
+ incoming/5d/jmg_9830.jpg | 1 +
+ incoming/5d/jmg_9834.cr2 | 1 +
+ incoming/5d/jmg_9843.jpg | 1 +
+ incoming/5d/jmg_9848.jpg | 1 +
+ incoming/5d/jmg_9849.jpg | 1 +
+ incoming/5d/jmg_9853.cr2 | 1 +
+ incoming/5d/jmg_9856.jpg | 1 +
+ incoming/5d/jmg_9857.cr2 | 1 +
+ incoming/5d/jmg_9859.cr2 | 1 +
+ incoming/5d/jmg_9860.jpg | 1 +
+ incoming/5d/jmg_9917.jpg | 1 +
+ incoming/5d/jmg_9923.jpg | 1 +
+ incoming/5d/jmg_9926.jpg | 1 +
+ incoming/5d/jmg_9975.cr2 | 1 +
+ incoming/5d/jmg_9976.cr2 | 1 +
+ incoming/5d/jmg_9978.jpg | 1 +
+ incoming/5d/jmg_9988.jpg | 1 +
+ incoming/5d/jmg_9997.cr2 | 1 +
+ incoming/5d/jmg_9998.jpg | 1 +
+ incoming/5d/jmg_9999.jpg | 1 +
+ list_5d_repoB | 1 -
+ only_on_repoB | 1 +
+ dir/2012/dir2/jmg_0128.cr2 | 1 -
+ dir/2012/dir2/jmg_0128.jpg | 1 -
+ dir/2012/dir2/jmg_0129.cr2 | 1 -
+ dir/2012/dir2/jmg_0129.jpg | 1 -
+ dir/2012/dir2/jmg_0353.jpg | 1 -
+ dir/2012/dir2/jmg_0354.jpg | 1 -
+ dir/2012/dir2/jmg_0375.jpg | 1 -
+ dir/2012/dir2/jmg_0376.jpg | 1 -
+ dir/2012/dir2/jmg_0378.jpg | 1 -
+ dir/2012/dir2/jmg_8707.cr2 | 1 -
+ dir/2012/dir2/jmg_8707.jpg | 1 -
+ dir/2012/dir2/jmg_8727.cr2 | 1 -
+ dir/2012/dir2/jmg_8727.jpg | 1 -
+ dir/2012/dir2/jmg_8728.cr2 | 1 -
+ dir/2012/dir2/jmg_8728.jpg | 1 -
+ dir/2012/dir2/jmg_8729.cr2 | 1 -
+ dir/2012/dir2/jmg_8729.jpg | 1 -
+ dir/2012/dir2/jmg_8740.cr2 | 1 -
+ dir/2012/dir2/jmg_8740.jpg | 1 -
+ dir/2012/dir2/jmg_8742.cr2 | 1 -
+ dir/2012/dir2/jmg_8742.jpg | 1 -
+ dir/2012/dir2/jmg_8825.cr2 | 1 -
+ dir/2012/dir2/jmg_8825.jpg | 1 -
+ dir/2012/dir2/jmg_8991.cr2 | 1 -
+ dir/2012/dir2/jmg_8991.jpg | 1 -
+ dir/2012/dir2/jmg_8992.cr2 | 1 -
+ dir/2012/dir2/jmg_8992.jpg | 1 -
+ dir/2012/dir2/jmg_8993.cr2 | 1 -
+ dir/2012/dir2/jmg_8993.jpg | 1 -
+ dir/2012/dir2/jmg_9059.cr2 | 1 -
+ dir/2012/dir2/jmg_9059.jpg | 1 -
+ dir/2012/dir2/jmg_9060.cr2 | 1 -
+ dir/2012/dir2/jmg_9060.jpg | 1 -
+ dir/2012/dir2/jmg_9064.cr2 | 1 -
+ dir/2012/dir2/jmg_9064.jpg | 1 -
+ dir/2012/dir2/jmg_9065.cr2 | 1 -
+ dir/2012/dir2/jmg_9065.jpg | 1 -
+ dir/2012/dir2/jmg_9081.cr2 | 1 -
+ dir/2012/dir2/jmg_9081.jpg | 1 -
+ dir/2012/dir2/jmg_9082.cr2 | 1 -
+ dir/2012/dir2/jmg_9082.jpg | 1 -
+ dir/2012/dir2/jmg_9083.cr2 | 1 -
+ dir/2012/dir2/jmg_9083.jpg | 1 -
+ dir/2012/dir1/jmg_0132.cr2 | 1 -
+ dir/2012/dir1/jmg_0132.jpg | 1 -
+ dir/2012/dir1/jmg_0133.cr2 | 1 -
+ dir/2012/dir1/jmg_0133.jpg | 1 -
+ dir/2012/dir1/jmg_0347.jpg | 1 -
+ dir/2012/dir1/jmg_0351.jpg | 1 -
+ dir/2012/dir1/jmg_0352.jpg | 1 -
+ dir/2012/dir1/jmg_0374.jpg | 1 -
+ dir/2012/dir1/jmg_8714.cr2 | 1 -
+ dir/2012/dir1/jmg_8714.jpg | 1 -
+ dir/2012/dir1/jmg_8716.cr2 | 1 -
+ dir/2012/dir1/jmg_8716.jpg | 1 -
+ dir/2012/dir1/jmg_8734.cr2 | 1 -
+ dir/2012/dir1/jmg_8734.jpg | 1 -
+ dir/2012/dir1/jmg_8735.cr2 | 1 -
+ dir/2012/dir1/jmg_8735.jpg | 1 -
+ dir/2012/dir1/jmg_8736.cr2 | 1 -
+ dir/2012/dir1/jmg_8736.jpg | 1 -
+ dir/2012/dir1/jmg_8743.cr2 | 1 -
+ dir/2012/dir1/jmg_8743.jpg | 1 -
+ dir/2012/dir1/jmg_8746.cr2 | 1 -
+ dir/2012/dir1/jmg_8746.jpg | 1 -
+ dir/2012/dir1/jmg_8828.cr2 | 1 -
+ dir/2012/dir1/jmg_8828.jpg | 1 -
+ dir/2012/dir1/jmg_8984.cr2 | 1 -
+ dir/2012/dir1/jmg_8984.jpg | 1 -
+ dir/2012/dir1/jmg_8985.cr2 | 1 -
+ dir/2012/dir1/jmg_8985.jpg | 1 -
+ dir/2012/dir1/jmg_8986.cr2 | 1 -
+ dir/2012/dir1/jmg_8986.jpg | 1 -
+ dir/2012/dir1/jmg_8988.cr2 | 1 -
+ dir/2012/dir1/jmg_8988.jpg | 1 -
+ dir/2012/dir1/jmg_9057.cr2 | 1 -
+ dir/2012/dir1/jmg_9057.jpg | 1 -
+ dir/2012/dir1/jmg_9058.cr2 | 1 -
+ dir/2012/dir1/jmg_9058.jpg | 1 -
+ dir/2012/dir1/jmg_9086.cr2 | 1 -
+ dir/2012/dir1/jmg_9086.jpg | 1 -
+ dir/2012/dir1/jmg_9087.cr2 | 1 -
+ dir/2012/dir1/jmg_9087.jpg | 1 -
+ dir/2013/dir2/jmg_0477.cr2 | 1 -
+ dir/2013/dir2/jmg_0477.jpg | 1 -
+ dir/2013/dir2/jmg_0478.cr2 | 1 -
+ dir/2013/dir2/jmg_0478.jpg | 1 -
+ dir/2013/dir2/jmg_0479.cr2 | 1 -
+ dir/2013/dir2/jmg_0479.jpg | 1 -
+ dir/2013/dir2/jmg_0604.cr2 | 1 -
+ dir/2013/dir2/jmg_0604.jpg | 1 -
+ dir/2013/dir2/jmg_0605.cr2 | 1 -
+ dir/2013/dir2/jmg_0605.jpg | 1 -
+ dir/2013/dir2/jmg_0606.cr2 | 1 -
+ dir/2013/dir2/jmg_0606.jpg | 1 -
+ dir/2013/dir2/jmg_0607.cr2 | 1 -
+ dir/2013/dir2/jmg_0607.jpg | 1 -
+ dir/2013/dir2/jmg_0608.cr2 | 1 -
+ dir/2013/dir2/jmg_0608.jpg | 1 -
+ dir/2013/dir2/jmg_0708.cr2 | 1 -
+ dir/2013/dir2/jmg_0708.jpg | 1 -
+ dir/2013/dir2/jmg_0709.cr2 | 1 -
+ dir/2013/dir2/jmg_0709.jpg | 1 -
+ dir/2013/dir2/jmg_0710.cr2 | 1 -
+ dir/2013/dir2/jmg_0710.jpg | 1 -
+ dir/2013/dir1/jmg_0475.cr2 | 1 -
+ dir/2013/dir1/jmg_0475.jpg | 1 -
+ dir/2013/dir1/jmg_0476.cr2 | 1 -
+ dir/2013/dir1/jmg_0476.jpg | 1 -
+ dir/2013/dir1/jmg_0718.cr2 | 1 -
+ dir/2013/dir1/jmg_0718.jpg | 1 -
+ dir/2013/dir1/jmg_0719.cr2 | 1 -
+ dir/2013/dir1/jmg_0719.jpg | 1 -
+ 1821 files changed, 628 insertions(+), 1231 deletions(-)
+ delete mode 120000 201109/jmg_7250.cr2
+ delete mode 120000 201109/jmg_7250.jpg
+ delete mode 120000 201109/jmg_7251.cr2
+ delete mode 120000 201109/jmg_7251.jpg
+ delete mode 120000 201109/jmg_7253.cr2
+ delete mode 120000 201109/jmg_7253.jpg
+ delete mode 120000 201109/jmg_7256_raw.jpg
+ delete mode 120000 201109/jmg_7259.cr2
+ delete mode 120000 201109/jmg_7259.jpg
+ delete mode 120000 201109/jmg_7261.cr2
+ delete mode 120000 201109/jmg_7261.jpg
+ delete mode 120000 201109/jmg_7265.cr2
+ delete mode 120000 201109/jmg_7265.jpg
+ delete mode 120000 201109/jmg_7272.jpg
+ delete mode 120000 201109/jmg_7274.jpg
+ delete mode 120000 201109/jmg_7275.jpg
+ delete mode 120000 201109/jmg_7276.jpg
+ delete mode 120000 201109/jmg_7280.jpg
+ delete mode 120000 201109/jmg_7284.jpg
+ delete mode 120000 201109/jmg_7286.jpg
+ delete mode 120000 201109/jmg_7288.jpg
+ delete mode 120000 201109/jmg_7289.jpg
+ delete mode 120000 201109/jmg_7292.jpg
+ delete mode 120000 201109/jmg_7293.jpg
+ delete mode 120000 201109/jmg_7295.cr2
+ delete mode 120000 201109/jmg_7295.jpg
+ delete mode 120000 201109/jmg_7296.cr2
+ delete mode 120000 201109/jmg_7296.jpg
+ delete mode 120000 201109/jmg_7299.cr2
+ delete mode 120000 201109/jmg_7299.jpg
+ delete mode 120000 201109/jmg_7300.cr2
+ delete mode 120000 201109/jmg_7300.jpg
+ delete mode 120000 201109/jmg_7304.jpg
+ delete mode 120000 201109/jmg_7305_raw.jpg
+ delete mode 120000 201109/jmg_7307_raw.jpg
+ delete mode 120000 201202/jmg_8528.jpg
+ delete mode 120000 201202/jmg_8529.jpg
+ delete mode 120000 201202/jmg_8595.jpg
+ delete mode 120000 201202/jmg_8596.jpg
+ delete mode 120000 201202/jmg_8597.jpg
+ delete mode 120000 201202/jmg_8601.jpg
+ delete mode 120000 201202/jmg_8602.cr2
+ delete mode 120000 201202/jmg_8602.jpg
+ delete mode 120000 201202/jmg_8603.cr2
+ delete mode 120000 201202/jmg_8603.jpg
+ delete mode 120000 201202/jmg_8604.jpg
+ delete mode 120000 201202/jmg_8605.jpg
+ delete mode 120000 201202/jmg_8606.jpg
+ delete mode 120000 201202/jmg_8607.jpg
+ delete mode 120000 201202/jmg_8608.jpg
+ delete mode 120000 201202/jmg_8609.jpg
+ delete mode 120000 201202/jmg_8610.jpg
+ delete mode 120000 201202/jmg_8611.jpg
+ delete mode 120000 201202/jmg_8612.cr2
+ delete mode 120000 201202/jmg_8612.jpg
+ delete mode 120000 201202/jmg_8613.jpg
+ delete mode 120000 201202/jmg_8614.jpg
+ delete mode 120000 201202/jmg_8615.jpg
+ delete mode 120000 201202/jmg_8616_raw.jpg
+ delete mode 120000 201202/jmg_8617.jpg
+ delete mode 120000 201202/jmg_8618.jpg
+ delete mode 120000 201202/jmg_8619.jpg
+ delete mode 120000 201202/jmg_8620.jpg
+ delete mode 120000 201202/jmg_8621.jpg
+ delete mode 120000 201202/jmg_8622.jpg
+ delete mode 120000 201202/jmg_8624.jpg
+ delete mode 120000 201202/jmg_8625.cr2
+ delete mode 120000 201202/jmg_8625.jpg
+ delete mode 120000 201202/jmg_8626.jpg
+ delete mode 120000 201202/jmg_8627.jpg
+ delete mode 120000 201202/jmg_8628.jpg
+ delete mode 120000 201202/jmg_8629.jpg
+ delete mode 120000 201202/jmg_8630.jpg
+ delete mode 120000 201202/jmg_8631.jpg
+ delete mode 120000 201202/jmg_8632.jpg
+ delete mode 120000 201202/jmg_8633.cr2
+ delete mode 120000 201202/jmg_8633.jpg
+ delete mode 120000 201202/jmg_8634.jpg
+ delete mode 120000 201202/jmg_8637.jpg
+ delete mode 120000 201202/jmg_8639.jpg
+ delete mode 120000 201202/jmg_8640.jpg
+ delete mode 120000 201202/jmg_8641.jpg
+ delete mode 120000 201202/jmg_8642_raw.jpg
+ delete mode 120000 201202/jmg_8643.jpg
+ delete mode 120000 201202/jmg_8644.jpg
+ delete mode 120000 201202/jmg_8647.jpg
+ delete mode 120000 201202/jmg_8648.jpg
+ delete mode 120000 201202/jmg_8651.cr2
+ delete mode 120000 201202/jmg_8651.jpg
+ delete mode 120000 201202/jmg_8652.jpg
+ delete mode 120000 201202/jmg_8653.jpg
+ delete mode 120000 201202/jmg_8654.jpg
+ delete mode 120000 201202/jmg_8655.jpg
+ delete mode 120000 201202/jmg_8657.jpg
+ delete mode 120000 201202/jmg_8665.jpg
+ delete mode 120000 201202/jmg_8670.jpg
+ delete mode 120000 201202/jmg_8671.jpg
+ delete mode 120000 201202/jmg_8673.cr2
+ delete mode 120000 201202/jmg_8673.jpg
+ delete mode 120000 201202/jmg_8674.jpg
+ delete mode 120000 201202/jmg_8675.jpg
+ delete mode 120000 201202/jmg_8676.jpg
+ delete mode 120000 201202/jmg_8677.jpg
+ delete mode 120000 201202/jmg_8678.jpg
+ delete mode 120000 201202/jmg_8679.jpg
+ delete mode 120000 201202/jmg_8680.jpg
+ delete mode 120000 201202/jmg_8681.jpg
+ delete mode 120000 201203/jmg_8701.cr2
+ delete mode 120000 201203/jmg_8702.jpg
+ delete mode 120000 201203/jmg_8705.jpg
+ delete mode 120000 201203/jmg_8711.jpg
+ delete mode 120000 201203/jmg_8717.jpg
+ delete mode 120000 201203/jmg_8718.jpg
+ delete mode 120000 201203/jmg_8719.jpg
+ delete mode 120000 201203/jmg_8721.jpg
+ delete mode 120000 201203/jmg_8725.jpg
+ delete mode 120000 201203/jmg_8726.jpg
+ delete mode 120000 201203/jmg_8731.jpg
+ delete mode 120000 201203/jmg_8739.jpg
+ delete mode 120000 201203/jmg_8745.jpg
+ delete mode 120000 201203/jmg_8747_raw.jpg
+ delete mode 120000 201203/jmg_8750.cr2
+ delete mode 120000 201203/jmg_8750.jpg
+ delete mode 120000 201204/jmg_8751.jpg
+ delete mode 120000 201204/jmg_8752.jpg
+ delete mode 120000 201204/jmg_8755.jpg
+ delete mode 120000 201204/jmg_8756.jpg
+ delete mode 120000 201204/jmg_8757.jpg
+ delete mode 120000 201204/jmg_8759.jpg
+ delete mode 120000 201204/jmg_8760.jpg
+ delete mode 120000 201204/jmg_8761.jpg
+ delete mode 120000 201204/jmg_8762.jpg
+ delete mode 120000 201204/jmg_8763.cr2
+ delete mode 120000 201204/jmg_8763.jpg
+ delete mode 120000 201204/jmg_8766.jpg
+ delete mode 120000 201204/jmg_8767.cr2
+ delete mode 120000 201204/jmg_8767.jpg
+ delete mode 120000 201204/jmg_8768.jpg
+ delete mode 120000 201204/jmg_8769.jpg
+ delete mode 120000 201204/jmg_8770.jpg
+ delete mode 120000 201204/jmg_8771.jpg
+ delete mode 120000 201204/jmg_8772.jpg
+ delete mode 120000 201204/jmg_8773.jpg
+ delete mode 120000 201205/jmg_8822.jpg
+ delete mode 120000 201205/jmg_8823.jpg
+ delete mode 120000 201205/jmg_8824.jpg
+ delete mode 120000 201205/jmg_8826.jpg
+ delete mode 120000 201205/jmg_8831.jpg
+ delete mode 120000 201205/jmg_8834.jpg
+ delete mode 120000 201205/jmg_8835.jpg
+ delete mode 120000 201205/jmg_8835_raw.jpg
+ delete mode 120000 201205/jmg_8837.jpg
+ delete mode 120000 201205/jmg_8839.cr2
+ delete mode 120000 201205/jmg_8839.jpg
+ delete mode 120000 201205/jmg_8839_raw.jpg
+ delete mode 120000 201205/jmg_8840.cr2
+ delete mode 120000 201205/jmg_8840.jpg
+ delete mode 120000 201205/jmg_8840_raw.jpg
+ delete mode 120000 201205/jmg_8841.jpg
+ delete mode 120000 201205/jmg_8842.jpg
+ delete mode 120000 201205/jmg_8844.cr2
+ delete mode 120000 201205/jmg_8844.jpg
+ delete mode 120000 201205/jmg_8844_raw.jpg
+ delete mode 120000 201205/jmg_8845.jpg
+ delete mode 120000 201205/jmg_8846.jpg
+ delete mode 120000 201205/jmg_8847.cr2
+ delete mode 120000 201205/jmg_8847.jpg
+ delete mode 120000 201205/jmg_8847_raw.jpg
+ delete mode 120000 201205/jmg_8848.jpg
+ delete mode 120000 201205/jmg_8849.jpg
+ delete mode 120000 201205/jmg_8851.cr2
+ delete mode 120000 201205/jmg_8851.jpg
+ delete mode 120000 201205/jmg_8851_raw.jpg
+ delete mode 120000 201205/jmg_8856.cr2
+ delete mode 120000 201205/jmg_8856.jpg
+ delete mode 120000 201205/jmg_8856_raw.jpg
+ delete mode 120000 201205/jmg_8857.jpg
+ delete mode 120000 201205/jmg_8858.jpg
+ delete mode 120000 201205/jmg_8859.jpg
+ delete mode 120000 201205/jmg_8861.jpg
+ delete mode 120000 201205/jmg_8862.jpg
+ delete mode 120000 201205/jmg_8863.jpg
+ delete mode 120000 201205/jmg_8871.cr2
+ delete mode 120000 201205/jmg_8871.jpg
+ delete mode 120000 201205/jmg_8872.jpg
+ delete mode 120000 201205/jmg_8873.jpg
+ delete mode 120000 201205/jmg_8875.jpg
+ delete mode 120000 201205/jmg_8876.cr2
+ delete mode 120000 201205/jmg_8876.jpg
+ delete mode 120000 201205/jmg_8878.cr2
+ delete mode 120000 201205/jmg_8878.jpg
+ delete mode 120000 201205/jmg_8879.cr2
+ delete mode 120000 201205/jmg_8879.jpg
+ delete mode 120000 201205/jmg_8880.cr2
+ delete mode 120000 201205/jmg_8880.jpg
+ delete mode 120000 201205/jmg_8881.cr2
+ delete mode 120000 201205/jmg_8881.jpg
+ delete mode 120000 201205/jmg_8892.cr2
+ delete mode 120000 201205/jmg_8892.jpg
+ delete mode 120000 201205/jmg_8893.cr2
+ delete mode 120000 201205/jmg_8893.jpg
+ delete mode 120000 201205/jmg_8894.cr2
+ delete mode 120000 201205/jmg_8894.jpg
+ delete mode 120000 201206/jmg_8989.cr2
+ delete mode 120000 201206/jmg_8989.jpg
+ delete mode 120000 201206/jmg_8990.cr2
+ delete mode 120000 201206/jmg_8990.jpg
+ delete mode 120000 201206/jmg_8995.jpg
+ delete mode 120000 201206/jmg_8996.jpg
+ delete mode 120000 201206/jmg_8998.jpg
+ delete mode 120000 201206/jmg_9001.jpg
+ delete mode 120000 201206/jmg_9003.jpg
+ delete mode 120000 201206/jmg_9006.jpg
+ delete mode 120000 201206/jmg_9007.jpg
+ delete mode 120000 201206/jmg_9011.jpg
+ delete mode 120000 201206/jmg_9014.jpg
+ delete mode 120000 201206/jmg_9014_raw.jpg
+ delete mode 120000 201206/jmg_9015.jpg
+ delete mode 120000 201206/jmg_9016.cr2
+ delete mode 120000 201206/jmg_9016.jpg
+ delete mode 120000 201206/jmg_9017.cr2
+ delete mode 120000 201206/jmg_9017.jpg
+ delete mode 120000 201206/jmg_9018.cr2
+ delete mode 120000 201206/jmg_9018.jpg
+ delete mode 120000 201206/jmg_9019.cr2
+ delete mode 120000 201206/jmg_9019.jpg
+ delete mode 120000 201206/jmg_9023.cr2
+ delete mode 120000 201206/jmg_9023.jpg
+ delete mode 120000 201206/jmg_9024.cr2
+ delete mode 120000 201206/jmg_9024.jpg
+ delete mode 120000 201206/jmg_9025.cr2
+ delete mode 120000 201206/jmg_9025.jpg
+ delete mode 120000 201206/jmg_9028.jpg
+ delete mode 120000 201206/jmg_9029.jpg
+ delete mode 120000 201206/jmg_9030.jpg
+ delete mode 120000 201206/jmg_9031.jpg
+ delete mode 120000 201206/jmg_9032_raw.jpg
+ delete mode 120000 201206/jmg_9033.jpg
+ delete mode 120000 201206/jmg_9033_raw.jpg
+ delete mode 120000 201206/jmg_9034.jpg
+ delete mode 120000 201206/jmg_9035.jpg
+ delete mode 120000 201206/jmg_9035_raw.jpg
+ delete mode 120000 201206/jmg_9036.jpg
+ delete mode 120000 201206/jmg_9039.cr2
+ delete mode 120000 201206/jmg_9039.jpg
+ delete mode 120000 201206/jmg_9040.cr2
+ delete mode 120000 201206/jmg_9040.jpg
+ delete mode 120000 201206/jmg_9043.cr2
+ delete mode 120000 201206/jmg_9043.jpg
+ delete mode 120000 201206/jmg_9047.cr2
+ delete mode 120000 201206/jmg_9047.jpg
+ delete mode 120000 201207/jmg_9048.jpg
+ delete mode 120000 201207/jmg_9053.jpg
+ delete mode 120000 201207/jmg_9054.jpg
+ delete mode 120000 201207/jmg_9069.cr2
+ delete mode 120000 201207/jmg_9069.jpg
+ delete mode 120000 201207/jmg_9070.cr2
+ delete mode 120000 201207/jmg_9070.jpg
+ delete mode 120000 201207/jmg_9072.cr2
+ delete mode 120000 201207/jmg_9072.jpg
+ delete mode 120000 201207/jmg_9076.cr2
+ delete mode 120000 201207/jmg_9076.jpg
+ delete mode 120000 201208/jmg_9077.jpg
+ delete mode 120000 201208/jmg_9302_raw.jpg
+ delete mode 120000 201208/jmg_9303.jpg
+ delete mode 120000 201208/jmg_9304.cr2
+ delete mode 120000 201208/jmg_9304.jpg
+ delete mode 120000 201208/jmg_9305.cr2
+ delete mode 120000 201208/jmg_9305.jpg
+ delete mode 120000 201208/jmg_9306_raw.jpg
+ delete mode 120000 201208/jmg_9307.cr2
+ delete mode 120000 201208/jmg_9307.jpg
+ delete mode 120000 201208/jmg_9308_raw.jpg
+ delete mode 120000 201208/jmg_9309_raw.jpg
+ delete mode 120000 201208/jmg_9310.cr2
+ delete mode 120000 201208/jmg_9310.jpg
+ delete mode 120000 201208/jmg_9310_bw.jpg
+ delete mode 120000 201208/jmg_9310_raw.jpg
+ delete mode 120000 201208/jmg_9312.jpg
+ delete mode 120000 201208/jmg_9313.jpg
+ delete mode 120000 201208/jmg_9314.jpg
+ delete mode 120000 201208/jmg_9315.jpg
+ delete mode 120000 201208/jmg_9319.jpg
+ delete mode 120000 201208/jmg_9523.jpg
+ delete mode 120000 201208/jmg_9524.jpg
+ delete mode 120000 201208/jmg_9525.jpg
+ delete mode 120000 201208/jmg_9526.jpg
+ delete mode 120000 201208/jmg_9527.jpg
+ delete mode 120000 201208/jmg_9527_raw.jpg
+ delete mode 120000 201208/jmg_9528.jpg
+ delete mode 120000 201208/jmg_9529.jpg
+ delete mode 120000 201208/jmg_9530.jpg
+ delete mode 120000 201208/jmg_9531.jpg
+ delete mode 120000 201208/jmg_9532.jpg
+ delete mode 120000 201208/jmg_9533.cr2
+ delete mode 120000 201208/jmg_9533.jpg
+ delete mode 120000 201208/jmg_9534.cr2
+ delete mode 120000 201208/jmg_9534.jpg
+ delete mode 120000 201208/jmg_9535.jpg
+ delete mode 120000 201208/jmg_9536.jpg
+ delete mode 120000 201208/jmg_9537.cr2
+ delete mode 120000 201208/jmg_9537.jpg
+ delete mode 120000 201208/jmg_9538.jpg
+ delete mode 120000 201208/jmg_9539.jpg
+ delete mode 120000 201208/jmg_9540.jpg
+ delete mode 120000 201208/jmg_9541.cr2
+ delete mode 120000 201208/jmg_9542.jpg
+ delete mode 120000 201208/jmg_9543.cr2
+ delete mode 120000 201208/jmg_9543.jpg
+ delete mode 120000 201208/jmg_9544.cr2
+ delete mode 120000 201208/jmg_9544.jpg
+ delete mode 120000 201208/jmg_9545.jpg
+ delete mode 120000 201209/jmg_9547.jpg
+ delete mode 120000 201209/jmg_9548.jpg
+ delete mode 120000 201209/jmg_9549.jpg
+ delete mode 120000 201209/jmg_9550.jpg
+ delete mode 120000 201209/jmg_9551.jpg
+ delete mode 120000 201209/jmg_9552.jpg
+ delete mode 120000 201209/jmg_9553.jpg
+ delete mode 120000 201209/jmg_9555.jpg
+ delete mode 120000 201209/jmg_9556.jpg
+ delete mode 120000 201209/jmg_9558.jpg
+ delete mode 120000 201209/jmg_9559.cr2
+ delete mode 120000 201209/jmg_9559.jpg
+ delete mode 120000 201209/jmg_9560.cr2
+ delete mode 120000 201209/jmg_9560.jpg
+ delete mode 120000 201209/jmg_9561.jpg
+ delete mode 120000 201209/jmg_9562.jpg
+ delete mode 120000 201209/jmg_9568.jpg
+ delete mode 120000 201210/jmg_0001.jpg
+ delete mode 120000 201210/jmg_0021.jpg
+ delete mode 120000 201210/jmg_0022.cr2
+ delete mode 120000 201210/jmg_0022.jpg
+ delete mode 120000 201210/jmg_0025.jpg
+ delete mode 120000 201210/jmg_0026.jpg
+ delete mode 120000 201210/jmg_0027.jpg
+ delete mode 120000 201210/jmg_0028.jpg
+ delete mode 120000 201210/jmg_0029.jpg
+ delete mode 120000 201210/jmg_0030.jpg
+ delete mode 120000 201210/jmg_0032.jpg
+ delete mode 120000 201210/jmg_0034.jpg
+ delete mode 120000 201210/jmg_0035.jpg
+ delete mode 120000 201210/jmg_0036.jpg
+ delete mode 120000 201210/jmg_0037.jpg
+ delete mode 120000 201210/jmg_0039.cr2
+ delete mode 120000 201210/jmg_0039.jpg
+ delete mode 120000 201210/jmg_0040.jpg
+ delete mode 120000 201210/jmg_9572.jpg
+ delete mode 120000 201210/jmg_9573.jpg
+ delete mode 120000 201210/jmg_9574.jpg
+ delete mode 120000 201210/jmg_9575.jpg
+ delete mode 120000 201210/jmg_9576.jpg
+ delete mode 120000 201210/jmg_9578.jpg
+ delete mode 120000 201210/jmg_9580.jpg
+ delete mode 120000 201210/jmg_9581.jpg
+ delete mode 120000 201210/jmg_9582.cr2
+ delete mode 120000 201210/jmg_9582.jpg
+ delete mode 120000 201210/jmg_9585.cr2
+ delete mode 120000 201210/jmg_9585.jpg
+ delete mode 120000 201210/jmg_9587.cr2
+ delete mode 120000 201210/jmg_9587.jpg
+ delete mode 120000 201210/jmg_9588.jpg
+ delete mode 120000 201210/jmg_9589.jpg
+ delete mode 120000 201210/jmg_9590.jpg
+ delete mode 120000 201210/jmg_9591.jpg
+ delete mode 120000 201210/jmg_9594.jpg
+ delete mode 120000 201210/jmg_9595.jpg
+ delete mode 120000 201210/jmg_9596.jpg
+ delete mode 120000 201210/jmg_9597.cr2
+ delete mode 120000 201210/jmg_9597.jpg
+ delete mode 120000 201210/jmg_9598.cr2
+ delete mode 120000 201210/jmg_9598.jpg
+ delete mode 120000 201210/jmg_9599.cr2
+ delete mode 120000 201210/jmg_9599.jpg
+ delete mode 120000 201210/jmg_9600.jpg
+ delete mode 120000 201210/jmg_9602.jpg
+ delete mode 120000 201210/jmg_9603.jpg
+ delete mode 120000 201210/jmg_9604.jpg
+ delete mode 120000 201210/jmg_9605.cr2
+ delete mode 120000 201210/jmg_9605.jpg
+ delete mode 120000 201210/jmg_9606.jpg
+ delete mode 120000 201210/jmg_9608.jpg
+ delete mode 120000 201210/jmg_9609.jpg
+ delete mode 120000 201210/jmg_9610.jpg
+ delete mode 120000 201210/jmg_9611.jpg
+ delete mode 120000 201210/jmg_9612.jpg
+ delete mode 120000 201210/jmg_9613.jpg
+ delete mode 120000 201210/jmg_9614.jpg
+ delete mode 120000 201210/jmg_9616.cr2
+ delete mode 120000 201210/jmg_9616.jpg
+ delete mode 120000 201210/jmg_9617.jpg
+ delete mode 120000 201210/jmg_9619.jpg
+ delete mode 120000 201210/jmg_9620.jpg
+ delete mode 120000 201210/jmg_9621.jpg
+ delete mode 120000 201210/jmg_9622.jpg
+ delete mode 120000 201210/jmg_9623.cr2
+ delete mode 120000 201210/jmg_9623.jpg
+ delete mode 120000 201210/jmg_9624.cr2
+ delete mode 120000 201210/jmg_9624.jpg
+ delete mode 120000 201210/jmg_9736_raw.jpg
+ delete mode 120000 201210/jmg_9738_raw.jpg
+ delete mode 120000 201210/jmg_9740.cr2
+ delete mode 120000 201210/jmg_9740.jpg
+ delete mode 120000 201210/jmg_9743.jpg
+ delete mode 120000 201210/jmg_9744.jpg
+ delete mode 120000 201210/jmg_9745.cr2
+ delete mode 120000 201210/jmg_9745.jpg
+ delete mode 120000 201210/jmg_9746.cr2
+ delete mode 120000 201210/jmg_9746.jpg
+ delete mode 120000 201210/jmg_9748.jpg
+ delete mode 120000 201210/jmg_9749_raw.jpg
+ delete mode 120000 201210/jmg_9751.jpg
+ delete mode 120000 201210/jmg_9752.jpg
+ delete mode 120000 201210/jmg_9754.jpg
+ delete mode 120000 201210/jmg_9755.jpg
+ delete mode 120000 201210/jmg_9756.jpg
+ delete mode 120000 201210/jmg_9760.cr2
+ delete mode 120000 201210/jmg_9760.jpg
+ delete mode 120000 201210/jmg_9761.cr2
+ delete mode 120000 201210/jmg_9761.jpg
+ delete mode 120000 201210/jmg_9763.jpg
+ delete mode 120000 201210/jmg_9764.jpg
+ delete mode 120000 201210/jmg_9766.jpg
+ delete mode 120000 201210/jmg_9767.cr2
+ delete mode 120000 201210/jmg_9767.jpg
+ delete mode 120000 201210/jmg_9768.jpg
+ delete mode 120000 201210/jmg_9771.jpg
+ delete mode 120000 201210/jmg_9772.jpg
+ delete mode 120000 201210/jmg_9791.jpg
+ delete mode 120000 201210/jmg_9792.jpg
+ delete mode 120000 201210/jmg_9793.jpg
+ delete mode 120000 201210/jmg_9794.jpg
+ delete mode 120000 201210/jmg_9796.jpg
+ delete mode 120000 201210/jmg_9797.jpg
+ delete mode 120000 201210/jmg_9799.jpg
+ delete mode 120000 201210/jmg_9800.jpg
+ delete mode 120000 201210/jmg_9801.jpg
+ delete mode 120000 201210/jmg_9803.jpg
+ delete mode 120000 201210/jmg_9807.jpg
+ delete mode 120000 201210/jmg_9808.jpg
+ delete mode 120000 201210/jmg_9809.jpg
+ delete mode 120000 201210/jmg_9810.jpg
+ delete mode 120000 201210/jmg_9811.jpg
+ delete mode 120000 201210/jmg_9812.jpg
+ delete mode 120000 201210/jmg_9813.jpg
+ delete mode 120000 201210/jmg_9815.jpg
+ delete mode 120000 201210/jmg_9818.jpg
+ delete mode 120000 201210/jmg_9819.jpg
+ delete mode 120000 201210/jmg_9820.jpg
+ delete mode 120000 201210/jmg_9821.jpg
+ delete mode 120000 201210/jmg_9822.jpg
+ delete mode 120000 201210/jmg_9823.jpg
+ delete mode 120000 201210/jmg_9825.jpg
+ delete mode 120000 201210/jmg_9826.jpg
+ delete mode 120000 201210/jmg_9827.jpg
+ delete mode 120000 201210/jmg_9828.jpg
+ delete mode 120000 201210/jmg_9829.jpg
+ delete mode 120000 201210/jmg_9830.cr2
+ delete mode 120000 201210/jmg_9830.jpg
+ delete mode 120000 201210/jmg_9832.cr2
+ delete mode 120000 201210/jmg_9832.jpg
+ delete mode 120000 201210/jmg_9834.jpg
+ delete mode 120000 201210/jmg_9836.jpg
+ delete mode 120000 201210/jmg_9838.jpg
+ delete mode 120000 201210/jmg_9839.jpg
+ delete mode 120000 201210/jmg_9841.jpg
+ delete mode 120000 201210/jmg_9843.jpg
+ delete mode 120000 201210/jmg_9845.jpg
+ delete mode 120000 201210/jmg_9846.jpg
+ delete mode 120000 201210/jmg_9848.jpg
+ delete mode 120000 201210/jmg_9849.jpg
+ delete mode 120000 201210/jmg_9852.jpg
+ delete mode 120000 201210/jmg_9853.jpg
+ delete mode 120000 201210/jmg_9854.jpg
+ delete mode 120000 201210/jmg_9855.jpg
+ delete mode 120000 201210/jmg_9856.jpg
+ delete mode 120000 201210/jmg_9857.cr2
+ delete mode 120000 201210/jmg_9857.jpg
+ delete mode 120000 201210/jmg_9858.cr2
+ delete mode 120000 201210/jmg_9858.jpg
+ delete mode 120000 201210/jmg_9859.jpg
+ delete mode 120000 201210/jmg_9860.jpg
+ delete mode 120000 201210/jmg_9915.jpg
+ delete mode 120000 201210/jmg_9917.jpg
+ delete mode 120000 201210/jmg_9918.jpg
+ delete mode 120000 201210/jmg_9919.jpg
+ delete mode 120000 201210/jmg_9922.jpg
+ delete mode 120000 201210/jmg_9923.jpg
+ delete mode 120000 201210/jmg_9925.jpg
+ delete mode 120000 201210/jmg_9926.cr2
+ delete mode 120000 201210/jmg_9926.jpg
+ delete mode 120000 201210/jmg_9928.jpg
+ delete mode 120000 201210/jmg_9975.cr2
+ delete mode 120000 201210/jmg_9975.jpg
+ delete mode 120000 201210/jmg_9976.cr2
+ delete mode 120000 201210/jmg_9976.jpg
+ delete mode 120000 201210/jmg_9978.jpg
+ delete mode 120000 201210/jmg_9986.jpg
+ delete mode 120000 201210/jmg_9987.jpg
+ delete mode 120000 201210/jmg_9988.jpg
+ delete mode 120000 201210/jmg_9989.jpg
+ delete mode 120000 201210/jmg_9991.jpg
+ delete mode 120000 201210/jmg_9993.jpg
+ delete mode 120000 201210/jmg_9994.cr2
+ delete mode 120000 201210/jmg_9994.jpg
+ delete mode 120000 201210/jmg_9997.jpg
+ delete mode 120000 201210/jmg_9998.jpg
+ delete mode 120000 201210/jmg_9999.jpg
+ delete mode 120000 201212/jmg_0131.jpg
+ delete mode 120000 201212/jmg_0134.jpg
+ delete mode 120000 201212/jmg_0135.jpg
+ delete mode 120000 201212/jmg_0152.jpg
+ delete mode 120000 201212/jmg_0155.jpg
+ delete mode 120000 201212/jmg_0156.jpg
+ delete mode 120000 201212/jmg_0162.jpg
+ delete mode 120000 201212/jmg_0163.jpg
+ delete mode 120000 201212/jmg_0165.jpg
+ delete mode 120000 201212/jmg_0176.cr2
+ delete mode 120000 201212/jmg_0176.jpg
+ delete mode 120000 201212/jmg_0177.cr2
+ delete mode 120000 201212/jmg_0177.jpg
+ delete mode 120000 201212/jmg_0178.jpg
+ delete mode 120000 201212/jmg_0179.jpg
+ delete mode 120000 201212/jmg_0180.jpg
+ delete mode 120000 201212/jmg_0184.jpg
+ delete mode 120000 201212/jmg_0185.jpg
+ delete mode 120000 201212/jmg_0186.jpg
+ delete mode 120000 201212/jmg_0187.jpg
+ delete mode 120000 201212/jmg_0306.jpg
+ delete mode 120000 201212/jmg_0307.jpg
+ delete mode 120000 201212/jmg_0308.jpg
+ delete mode 120000 201212/jmg_0310.jpg
+ delete mode 120000 201212/jmg_0311.jpg
+ delete mode 120000 201212/jmg_0312.jpg
+ delete mode 120000 201212/jmg_0313.jpg
+ delete mode 120000 201212/jmg_0314.jpg
+ delete mode 120000 201212/jmg_0315.jpg
+ delete mode 120000 201212/jmg_0316.jpg
+ delete mode 120000 201212/jmg_0317.jpg
+ delete mode 120000 201212/jmg_0321.jpg
+ delete mode 120000 201212/jmg_0326.jpg
+ delete mode 120000 201212/jmg_0328.jpg
+ delete mode 120000 201212/jmg_0330.jpg
+ delete mode 120000 201212/jmg_0333.jpg
+ delete mode 120000 201212/jmg_0336.jpg
+ delete mode 120000 201212/jmg_0340.jpg
+ delete mode 120000 201212/jmg_0343.jpg
+ delete mode 120000 201212/jmg_0345.jpg
+ delete mode 120000 201212/jmg_0360.jpg
+ delete mode 120000 201212/jmg_0362.jpg
+ delete mode 120000 201212/jmg_0363.jpg
+ delete mode 120000 201212/jmg_0364.jpg
+ delete mode 120000 201212/jmg_0366.jpg
+ delete mode 120000 201212/jmg_0367.jpg
+ delete mode 120000 201212/jmg_0368.jpg
+ delete mode 120000 201212/jmg_0369.jpg
+ delete mode 120000 201212/jmg_0370.jpg
+ delete mode 120000 201212/jmg_0372.jpg
+ delete mode 120000 201212/jmg_0382.jpg
+ delete mode 120000 201212/jmg_0383.jpg
+ delete mode 120000 201212/jmg_0384.jpg
+ delete mode 120000 201212/jmg_0385.jpg
+ delete mode 120000 201212/jmg_0387.jpg
+ delete mode 120000 201212/jmg_0388.jpg
+ delete mode 120000 201212/jmg_0389.jpg
+ delete mode 120000 201212/jmg_0390.jpg
+ delete mode 120000 201212/jmg_0392.jpg
+ delete mode 120000 201212/jmg_0396.jpg
+ delete mode 120000 201212/jmg_0397.jpg
+ delete mode 120000 201212/jmg_0398.jpg
+ delete mode 120000 201212/jmg_0399.jpg
+ delete mode 120000 201212/jmg_0402.jpg
+ delete mode 120000 201212/jmg_0404.jpg
+ delete mode 120000 201212/jmg_0405.jpg
+ delete mode 120000 201212/jmg_0406.jpg
+ delete mode 120000 201212/jmg_0407.jpg
+ delete mode 120000 201212/jmg_0408.jpg
+ delete mode 120000 201212/jmg_0410.jpg
+ delete mode 120000 201212/jmg_0411.jpg
+ delete mode 120000 201212/jmg_0412.jpg
+ delete mode 120000 201212/jmg_0415.jpg
+ delete mode 120000 201212/jmg_0417.jpg
+ delete mode 120000 201212/jmg_0418.jpg
+ delete mode 120000 201302/jmg_0502.cr2
+ delete mode 120000 201302/jmg_0502.jpg
+ delete mode 120000 201302/jmg_0503.jpg
+ delete mode 120000 201302/jmg_0507.jpg
+ delete mode 120000 201302/jmg_0510.jpg
+ delete mode 120000 201302/jmg_0512.jpg
+ delete mode 120000 201302/jmg_0513.jpg
+ delete mode 120000 201302/jmg_0514.jpg
+ delete mode 120000 201302/jmg_0516.jpg
+ delete mode 120000 201302/jmg_0517.jpg
+ delete mode 120000 201302/jmg_0518.jpg
+ delete mode 120000 201302/jmg_0521.jpg
+ delete mode 120000 201302/jmg_0522.jpg
+ delete mode 120000 201302/jmg_0523.jpg
+ delete mode 120000 201302/jmg_0524.jpg
+ delete mode 120000 201302/jmg_0526.jpg
+ delete mode 120000 201302/jmg_0527.jpg
+ delete mode 120000 201302/jmg_0528.jpg
+ delete mode 120000 201302/jmg_0532.cr2
+ delete mode 120000 201302/jmg_0532.jpg
+ delete mode 120000 201302/jmg_0534.jpg
+ delete mode 120000 201302/jmg_0535.jpg
+ delete mode 120000 201302/jmg_0537.jpg
+ delete mode 120000 201302/jmg_0539.jpg
+ delete mode 120000 201302/jmg_0541.jpg
+ delete mode 120000 201302/jmg_0543.jpg
+ delete mode 120000 201304/bruecke_saeckingen.tif
+ delete mode 120000 201304/jmg_0685.cr2
+ delete mode 120000 201304/jmg_0685.jpg
+ delete mode 120000 201304/jmg_0687.cr2
+ delete mode 120000 201304/jmg_0687.jpg
+ delete mode 120000 201304/jmg_0699.jpg
+ delete mode 120000 201304/jmg_0700.jpg
+ delete mode 120000 201304/jmg_0726.jpg
+ delete mode 120000 201304/jmg_0727.jpg
+ delete mode 120000 201304/jmg_0728.jpg
+ delete mode 120000 201304/jmg_0729.cr2
+ delete mode 120000 201304/jmg_0729.jpg
+ delete mode 120000 201304/jmg_0730.jpg
+ delete mode 120000 201304/jmg_0731.jpg
+ delete mode 120000 201304/jmg_0733.cr2
+ delete mode 120000 201304/jmg_0733.jpg
+ delete mode 120000 201304/jmg_0734.cr2
+ delete mode 120000 201304/jmg_0734.jpg
+ delete mode 120000 201304/jmg_0736.cr2
+ delete mode 120000 201304/jmg_0736.jpg
+ delete mode 120000 201304/jmg_0737.cr2
+ delete mode 120000 201304/jmg_0737.jpg
+ delete mode 120000 201304/jmg_0738.jpg
+ delete mode 120000 201304/jmg_0739.jpg
+ delete mode 120000 201304/jmg_0740.jpg
+ delete mode 120000 201304/jmg_0741.jpg
+ delete mode 120000 201304/jmg_0742.jpg
+ delete mode 120000 201304/jmg_0744.cr2
+ delete mode 120000 201304/jmg_0744.jpg
+ delete mode 120000 201304/jmg_0749.jpg
+ delete mode 120000 201304/jmg_0750.jpg
+ delete mode 120000 201304/jmg_0751.jpg
+ delete mode 120000 201304/jmg_0752.jpg
+ delete mode 120000 201304/jmg_0753.jpg
+ delete mode 120000 201304/jmg_0755.cr2
+ delete mode 120000 201304/jmg_0755.jpg
+ delete mode 120000 201304/jmg_0757.cr2
+ delete mode 120000 201304/jmg_0757.jpg
+ delete mode 120000 201304/jmg_0758.jpg
+ delete mode 120000 201304/jmg_0759.jpg
+ delete mode 120000 201304/jmg_0760.cr2
+ delete mode 120000 201304/jmg_0760.jpg
+ delete mode 120000 201304/jmg_0762.cr2
+ delete mode 120000 201304/jmg_0762.jpg
+ delete mode 120000 201304/jmg_0763.jpg
+ delete mode 120000 201304/jmg_0764.jpg
+ delete mode 120000 201304/jmg_0765.jpg
+ delete mode 120000 201304/jmg_0766.jpg
+ delete mode 120000 201304/jmg_0769.jpg
+ delete mode 120000 201304/jmg_0770.jpg
+ delete mode 120000 201304/jmg_0771.jpg
+ delete mode 120000 201304/jmg_0785.cr2
+ delete mode 120000 201304/jmg_0785.jpg
+ delete mode 120000 201304/jmg_0786.cr2
+ delete mode 120000 201304/jmg_0786.jpg
+ delete mode 120000 201304/jmg_0787.cr2
+ delete mode 120000 201304/jmg_0787.jpg
+ delete mode 120000 201304/jmg_0789.jpg
+ delete mode 120000 201304/jmg_0790.jpg
+ delete mode 120000 201304/jmg_0791.jpg
+ delete mode 120000 201304/jmg_0800.jpg
+ delete mode 120000 201304/jmg_0801.jpg
+ delete mode 120000 201304/jmg_0802.jpg
+ delete mode 120000 201304/jmg_0803.jpg
+ delete mode 120000 201304/jmg_0809.jpg
+ delete mode 120000 201304/jmg_0810.jpg
+ delete mode 120000 201304/jmg_0812.jpg
+ delete mode 120000 201304/jmg_0813.jpg
+ delete mode 120000 201304/jmg_0824.jpg
+ delete mode 120000 201304/jmg_0825.jpg
+ delete mode 120000 201304/jmg_0827.jpg
+ delete mode 120000 201304/jmg_0831.jpg
+ delete mode 120000 201304/jmg_0833.jpg
+ delete mode 120000 201304/jmg_0834.jpg
+ delete mode 120000 201304/jmg_0836.jpg
+ delete mode 120000 201304/jmg_0837.jpg
+ delete mode 120000 201304/jmg_0845.jpg
+ delete mode 120000 201304/jmg_0846.jpg
+ delete mode 120000 201304/jmg_0847.jpg
+ delete mode 120000 201304/jmg_0848.jpg
+ delete mode 120000 201304/jmg_0849.jpg
+ delete mode 120000 201304/jmg_0850.jpg
+ delete mode 120000 201304/jmg_0851.jpg
+ delete mode 120000 201304/jmg_0857.jpg
+ delete mode 120000 201304/jmg_0858.jpg
+ delete mode 120000 201304/jmg_0860.jpg
+ delete mode 120000 201304/jmg_0861.jpg
+ delete mode 120000 201304/jmg_0862.jpg
+ delete mode 120000 201304/jmg_0863.jpg
+ delete mode 120000 201304/jmg_0864.jpg
+ delete mode 120000 201304/jmg_0866.jpg
+ delete mode 120000 201304/jmg_0867.jpg
+ delete mode 120000 201304/jmg_0868.cr2
+ delete mode 120000 201304/jmg_0868.jpg
+ delete mode 120000 201304/jmg_0869.cr2
+ delete mode 120000 201304/jmg_0869.jpg
+ delete mode 120000 201304/jmg_0872.cr2
+ delete mode 120000 201304/jmg_0872.jpg
+ delete mode 120000 201304/jmg_0874.cr2
+ delete mode 120000 201304/jmg_0874.jpg
+ delete mode 120000 201304/jmg_0875.jpg
+ delete mode 120000 201304/jmg_0875_raw.jpg
+ delete mode 120000 201304/jmg_0876.jpg
+ delete mode 120000 201304/jmg_0877.jpg
+ delete mode 120000 201304/jmg_0878.jpg
+ delete mode 120000 201304/jmg_0880.jpg
+ delete mode 120000 201304/jmg_0881.jpg
+ delete mode 120000 201304/jmg_0882.jpg
+ delete mode 120000 201304/jmg_0884.jpg
+ delete mode 120000 201304/jmg_0885.jpg
+ delete mode 120000 201304/jmg_0886.jpg
+ delete mode 120000 201304/jmg_0888.jpg
+ delete mode 120000 201304/jmg_0889.jpg
+ delete mode 120000 201304/jmg_0890.jpg
+ delete mode 120000 201304/jmg_0891.jpg
+ delete mode 120000 201304/jmg_0892.jpg
+ delete mode 120000 201304/jmg_0893.cr2
+ delete mode 120000 201304/jmg_0893.jpg
+ delete mode 120000 201304/jmg_0894.jpg
+ delete mode 120000 201304/jmg_0896.jpg
+ delete mode 120000 201304/jmg_0897.jpg
+ delete mode 120000 201304/jmg_0898.jpg
+ delete mode 120000 201304/jmg_0899.jpg
+ delete mode 120000 201304/jmg_0900.jpg
+ delete mode 120000 201304/jmg_0902.jpg
+ delete mode 120000 201304/jmg_0905.jpg
+ delete mode 120000 201304/jmg_0921.jpg
+ delete mode 120000 201304/jmg_0922.jpg
+ delete mode 120000 201304/jmg_0932.jpg
+ delete mode 120000 201304/jmg_0935.jpg
+ delete mode 120000 201304/jmg_0936.jpg
+ delete mode 120000 201304/jmg_0937.jpg
+ delete mode 120000 201304/jmg_0938.jpg
+ delete mode 120000 201304/jmg_0942.jpg
+ delete mode 120000 201304/jmg_0944.jpg
+ delete mode 120000 201304/jmg_0946.jpg
+ delete mode 120000 201304/jmg_0947.jpg
+ delete mode 120000 201304/jmg_0948.jpg
+ delete mode 120000 201304/jmg_0949.jpg
+ delete mode 120000 201304/jmg_0950.jpg
+ delete mode 120000 201304/jmg_0951.jpg
+ delete mode 120000 201304/jmg_0952.jpg
+ delete mode 120000 201304/jmg_0953.jpg
+ delete mode 120000 201304/jmg_0954.jpg
+ delete mode 120000 201304/jmg_0958.jpg
+ delete mode 120000 201304/jmg_0959.jpg
+ delete mode 120000 201304/jmg_0960.jpg
+ delete mode 120000 201304/jmg_0961.jpg
+ delete mode 120000 201304/jmg_0962.jpg
+ delete mode 120000 201304/jmg_0963.jpg
+ delete mode 120000 201304/jmg_0964.jpg
+ delete mode 120000 201304/jmg_0965.jpg
+ delete mode 120000 201304/jmg_0966.jpg
+ delete mode 120000 201304/jmg_0967.jpg
+ delete mode 120000 201304/jmg_0968.jpg
+ delete mode 120000 201304/jmg_0969.jpg
+ delete mode 120000 201304/jmg_0976.cr2
+ delete mode 120000 201304/jmg_0976.jpg
+ delete mode 120000 201304/jmg_0978.jpg
+ delete mode 120000 201304/jmg_0979.jpg
+ delete mode 120000 201304/jmg_0980.jpg
+ delete mode 120000 201304/jmg_0981.cr2
+ delete mode 120000 201304/jmg_0981.jpg
+ delete mode 120000 201304/jmg_0982.jpg
+ delete mode 120000 201304/jmg_0984.cr2
+ delete mode 120000 201304/jmg_0984.jpg
+ delete mode 120000 201304/jmg_0987.jpg
+ delete mode 120000 201304/jmg_0988.jpg
+ delete mode 120000 201304/jmg_0989.jpg
+ delete mode 120000 201304/jmg_0990.jpg
+ delete mode 120000 201304/jmg_0991.jpg
+ delete mode 120000 201304/jmg_0992.jpg
+ delete mode 120000 201304/jmg_1206.jpg
+ delete mode 120000 201304/jmg_1207.jpg
+ delete mode 120000 201304/jmg_1208.jpg
+ delete mode 120000 201304/jmg_1209.jpg
+ delete mode 120000 201304/jmg_1210.cr2
+ delete mode 120000 201304/jmg_1210.jpg
+ delete mode 120000 201304/jmg_1211.jpg
+ delete mode 120000 201304/jmg_1212.jpg
+ delete mode 120000 201304/jmg_1213.jpg
+ delete mode 120000 201304/jmg_1214.cr2
+ delete mode 120000 201304/jmg_1214.jpg
+ delete mode 120000 201304/jmg_1215.jpg
+ delete mode 120000 201304/jmg_1216.cr2
+ delete mode 120000 201304/jmg_1216.jpg
+ delete mode 120000 201304/jmg_1217.cr2
+ delete mode 120000 201304/jmg_1217.jpg
+ delete mode 120000 201304/jmg_1220.cr2
+ delete mode 120000 201304/jmg_1220.jpg
+ delete mode 120000 201304/jmg_1222.cr2
+ delete mode 120000 201304/jmg_1222.jpg
+ delete mode 120000 201304/jmg_1223.jpg
+ delete mode 120000 201306/jmg_1465.jpg
+ delete mode 120000 201306/jmg_1466.jpg
+ delete mode 120000 201306/jmg_1467.jpg
+ delete mode 120000 201306/jmg_1468.jpg
+ delete mode 120000 201306/jmg_1469.jpg
+ delete mode 120000 201306/jmg_1470.jpg
+ delete mode 120000 201306/jmg_1471.jpg
+ delete mode 120000 201306/jmg_1472.jpg
+ delete mode 120000 201306/jmg_1473.jpg
+ delete mode 120000 201306/jmg_1475.jpg
+ delete mode 120000 201306/jmg_1476.jpg
+ delete mode 120000 201306/jmg_1477.jpg
+ delete mode 120000 201306/jmg_1478.jpg
+ delete mode 120000 201306/jmg_1479.jpg
+ delete mode 120000 201306/jmg_1480.jpg
+ delete mode 120000 201306/jmg_1481.jpg
+ delete mode 120000 201306/jmg_1482.jpg
+ delete mode 120000 201306/jmg_1483.jpg
+ delete mode 120000 201306/jmg_1484.jpg
+ delete mode 120000 201306/jmg_1485.jpg
+ delete mode 120000 201306/jmg_1486.jpg
+ delete mode 120000 201306/jmg_1487.jpg
+ delete mode 120000 201306/jmg_1488.jpg
+ delete mode 120000 201306/jmg_1489.jpg
+ delete mode 120000 201306/jmg_1490.jpg
+ delete mode 120000 201306/jmg_1491.jpg
+ delete mode 120000 201306/jmg_1492.jpg
+ delete mode 120000 201306/jmg_1495.jpg
+ delete mode 120000 201306/jmg_1496.jpg
+ delete mode 120000 201306/jmg_1498.jpg
+ delete mode 120000 201306/jmg_1499.jpg
+ delete mode 120000 201306/jmg_1500.jpg
+ delete mode 120000 201306/jmg_1501.jpg
+ delete mode 120000 201306/jmg_1502.jpg
+ delete mode 120000 201306/jmg_1504.jpg
+ delete mode 120000 201306/jmg_1506.jpg
+ delete mode 120000 201306/jmg_1510.jpg
+ delete mode 120000 201306/jmg_1512.jpg
+ delete mode 120000 201306/jmg_1513.jpg
+ delete mode 120000 201306/jmg_1514.jpg
+ delete mode 120000 201306/jmg_1515.jpg
+ delete mode 120000 201306/jmg_1517.jpg
+ delete mode 120000 201306/jmg_1520.jpg
+ delete mode 120000 201306/jmg_1521.jpg
+ delete mode 120000 201306/jmg_1526.jpg
+ delete mode 120000 201306/jmg_1533.jpg
+ delete mode 120000 201306/jmg_1540.jpg
+ delete mode 120000 201306/jmg_1546.jpg
+ delete mode 120000 201306/jmg_1547.jpg
+ delete mode 120000 201306/jmg_1549.jpg
+ delete mode 120000 201306/jmg_1550.jpg
+ delete mode 120000 201306/jmg_1551.jpg
+ delete mode 120000 201306/jmg_1552.jpg
+ delete mode 120000 201306/jmg_1553.jpg
+ delete mode 120000 201306/jmg_1555.jpg
+ delete mode 120000 201306/jmg_1556.jpg
+ delete mode 120000 201306/jmg_1557.jpg
+ delete mode 120000 201306/jmg_1558.jpg
+ delete mode 120000 201306/jmg_1559.jpg
+ delete mode 120000 201306/jmg_1560.jpg
+ delete mode 120000 201306/jmg_1562.jpg
+ delete mode 120000 201306/jmg_1566.jpg
+ delete mode 120000 201306/jmg_1568.jpg
+ delete mode 120000 201306/jmg_1570.jpg
+ delete mode 120000 201306/jmg_1571.jpg
+ delete mode 120000 201306/jmg_1572.jpg
+ delete mode 120000 201306/jmg_1574.jpg
+ delete mode 120000 201306/jmg_1575.jpg
+ delete mode 120000 201306/jmg_1576.jpg
+ delete mode 120000 201306/jmg_1577.jpg
+ delete mode 120000 201306/jmg_1578.jpg
+ delete mode 120000 201306/jmg_1579.jpg
+ delete mode 120000 201306/jmg_1579_raw.jpg
+ delete mode 120000 201306/jmg_1581.jpg
+ delete mode 120000 201306/jmg_1583.jpg
+ delete mode 120000 201306/jmg_1583_cut.jpg
+ delete mode 120000 201306/jmg_1583_raw.jpg
+ delete mode 120000 201306/jmg_1584.jpg
+ delete mode 120000 201306/jmg_1586.jpg
+ delete mode 120000 201306/jmg_1587.jpg
+ delete mode 120000 201306/jmg_1588.jpg
+ delete mode 120000 201306/jmg_1589.jpg
+ delete mode 120000 201306/jmg_1591.jpg
+ delete mode 120000 201306/jmg_1592.jpg
+ delete mode 120000 201306/jmg_1593.jpg
+ delete mode 120000 201306/jmg_1593_raw.jpg
+ delete mode 120000 201306/jmg_1594.jpg
+ delete mode 120000 201306/jmg_1594_raw.jpg
+ delete mode 120000 201306/jmg_1595.jpg
+ delete mode 120000 201306/jmg_1596.jpg
+ delete mode 120000 201306/jmg_1597.jpg
+ delete mode 120000 201306/jmg_1599.jpg
+ delete mode 120000 201306/jmg_1626.jpg
+ delete mode 120000 201306/jmg_1628.jpg
+ delete mode 120000 201306/jmg_1629.jpg
+ delete mode 120000 201306/jmg_1630.jpg
+ delete mode 120000 201306/jmg_1631.jpg
+ delete mode 120000 201306/jmg_1633.jpg
+ delete mode 120000 201306/jmg_1635.jpg
+ delete mode 120000 201306/jmg_1636.jpg
+ delete mode 120000 201306/jmg_1637.jpg
+ delete mode 120000 201306/jmg_1638.jpg
+ delete mode 120000 201306/jmg_1640.jpg
+ delete mode 120000 201306/jmg_1642.jpg
+ delete mode 120000 201306/jmg_1643.jpg
+ delete mode 120000 201306/jmg_1644.jpg
+ delete mode 120000 201306/jmg_1647.jpg
+ delete mode 120000 201306/jmg_1649.jpg
+ delete mode 120000 201306/jmg_1650.jpg
+ delete mode 120000 201306/jmg_1651.jpg
+ delete mode 120000 201306/jmg_1652.jpg
+ delete mode 120000 201306/jmg_1653.jpg
+ delete mode 120000 201306/jmg_1655.jpg
+ delete mode 120000 201306/jmg_1656.jpg
+ delete mode 120000 201306/jmg_1660.jpg
+ delete mode 120000 201306/jmg_1667.jpg
+ delete mode 120000 201306/jmg_1682.jpg
+ delete mode 120000 201306/jmg_1688.jpg
+ delete mode 120000 201306/jmg_1689.jpg
+ delete mode 120000 201306/jmg_1701.jpg
+ delete mode 120000 201306/jmg_1702.jpg
+ delete mode 120000 201306/jmg_1703.jpg
+ delete mode 120000 201306/jmg_1710.jpg
+ delete mode 120000 201306/jmg_1710_raw.jpg
+ delete mode 120000 201306/jmg_1715.jpg
+ delete mode 120000 201306/jmg_1716.jpg
+ delete mode 120000 201306/jmg_1719.jpg
+ delete mode 120000 201306/jmg_1722.jpg
+ delete mode 120000 201306/jmg_1723.jpg
+ delete mode 120000 201306/jmg_1729.cr2
+ delete mode 120000 201308/jmg_2038.jpg
+ delete mode 120000 201308/jmg_2039.jpg
+ delete mode 120000 201308/jmg_2040.jpg
+ delete mode 120000 201308/jmg_2041.jpg
+ delete mode 120000 201308/jmg_2042.jpg
+ delete mode 120000 201308/jmg_2043.jpg
+ delete mode 120000 201308/jmg_2045.jpg
+ delete mode 120000 201308/jmg_2047.jpg
+ delete mode 120000 201308/jmg_2048.jpg
+ delete mode 120000 201308/jmg_2049.jpg
+ delete mode 120000 201308/jmg_2050.jpg
+ delete mode 120000 201308/jmg_2051.jpg
+ delete mode 120000 201308/jmg_2052.jpg
+ delete mode 120000 201308/jmg_2053.jpg
+ delete mode 120000 201308/jmg_2054.jpg
+ delete mode 120000 201308/jmg_2055.jpg
+ delete mode 120000 201308/jmg_2056.jpg
+ delete mode 120000 201308/jmg_2057.jpg
+ delete mode 120000 201308/jmg_2058.jpg
+ delete mode 120000 201308/jmg_2059.jpg
+ delete mode 120000 201308/jmg_2060.jpg
+ delete mode 120000 201308/jmg_2061.jpg
+ delete mode 120000 201308/jmg_2062.jpg
+ delete mode 120000 201308/jmg_2089.cr2
+ delete mode 120000 201308/jmg_2089.jpg
+ delete mode 120000 201308/jmg_2089_raw.jpg
+ delete mode 120000 201308/jmg_2090.jpg
+ delete mode 120000 201308/jmg_2091.jpg
+ delete mode 120000 201308/jmg_2092.jpg
+ delete mode 120000 201308/jmg_2093.jpg
+ delete mode 120000 201308/jmg_2096.jpg
+ delete mode 120000 201308/jmg_2097.jpg
+ delete mode 120000 201308/jmg_2098.jpg
+ delete mode 120000 201308/jmg_2099.cr2
+ delete mode 120000 201308/jmg_2099.jpg
+ delete mode 120000 201308/jmg_2099_raw.jpg
+ delete mode 120000 201308/jmg_2100.cr2
+ delete mode 120000 201308/jmg_2100.jpg
+ delete mode 120000 201308/jmg_2100_raw.jpg
+ delete mode 120000 201308/jmg_2102.jpg
+ delete mode 120000 201308/jmg_2103.jpg
+ delete mode 120000 201308/jmg_2104.jpg
+ delete mode 120000 201308/jmg_2105.jpg
+ delete mode 120000 201308/jmg_2106.jpg
+ delete mode 120000 201308/jmg_2107.jpg
+ delete mode 120000 201308/jmg_2108.jpg
+ delete mode 120000 201308/jmg_2109.jpg
+ delete mode 120000 201308/jmg_2110.jpg
+ delete mode 120000 201308/jmg_2111.jpg
+ delete mode 120000 201308/jmg_2112.jpg
+ delete mode 120000 201308/jmg_2113.jpg
+ delete mode 120000 201308/jmg_2114.jpg
+ delete mode 120000 201308/jmg_2115.jpg
+ delete mode 120000 201308/jmg_2117.jpg
+ delete mode 120000 201308/jmg_2118.jpg
+ delete mode 120000 201308/jmg_2119.jpg
+ delete mode 120000 201308/jmg_2120.jpg
+ delete mode 120000 201308/jmg_2122.jpg
+ delete mode 120000 201308/jmg_2125.jpg
+ delete mode 120000 201308/jmg_2127.jpg
+ delete mode 120000 201308/jmg_2129.jpg
+ delete mode 120000 201308/jmg_2130.jpg
+ delete mode 120000 201308/jmg_2132.jpg
+ delete mode 120000 201308/jmg_2134.jpg
+ delete mode 120000 201308/jmg_2135.jpg
+ delete mode 120000 201308/jmg_2136.jpg
+ delete mode 120000 201308/jmg_2137.jpg
+ delete mode 120000 201308/jmg_2138.jpg
+ delete mode 120000 201308/jmg_2148.jpg
+ delete mode 120000 201308/jmg_2150.jpg
+ delete mode 120000 201308/jmg_2151.jpg
+ delete mode 120000 201308/jmg_2156.jpg
+ delete mode 120000 201308/jmg_2158.cr2
+ delete mode 120000 201308/jmg_2158.jpg
+ delete mode 120000 201308/jmg_2159.jpg
+ delete mode 120000 201308/jmg_2160.jpg
+ delete mode 120000 201308/jmg_2161.jpg
+ delete mode 120000 201308/jmg_2162.jpg
+ delete mode 120000 201308/jmg_2165.jpg
+ delete mode 120000 201308/jmg_2166.jpg
+ delete mode 120000 201308/jmg_2168.jpg
+ delete mode 120000 201308/jmg_2169.jpg
+ delete mode 120000 201308/jmg_2171.jpg
+ delete mode 120000 201308/jmg_2173.jpg
+ delete mode 120000 201308/jmg_2174.jpg
+ delete mode 120000 201308/jmg_2175.jpg
+ delete mode 120000 201308/jmg_2177.jpg
+ delete mode 120000 201308/jmg_2178.jpg
+ delete mode 120000 201308/jmg_2180.jpg
+ delete mode 120000 201308/jmg_2181.jpg
+ delete mode 120000 201308/jmg_2182.jpg
+ delete mode 120000 201308/jmg_2183.jpg
+ delete mode 120000 201308/jmg_2184.jpg
+ delete mode 120000 201308/jmg_2187.jpg
+ delete mode 120000 201308/jmg_2188.jpg
+ delete mode 120000 201308/jmg_2189.jpg
+ delete mode 120000 201308/jmg_2191.cr2
+ delete mode 120000 201308/jmg_2191.jpg
+ delete mode 120000 201308/jmg_2193.cr2
+ delete mode 120000 201308/jmg_2193.jpg
+ delete mode 120000 201308/jmg_2194.cr2
+ delete mode 120000 201308/jmg_2194.jpg
+ delete mode 120000 201308/jmg_2197.cr2
+ delete mode 120000 201308/jmg_2197.jpg
+ delete mode 120000 201308/jmg_2200.cr2
+ delete mode 120000 201308/jmg_2200.jpg
+ delete mode 120000 201308/jmg_2201.cr2
+ delete mode 120000 201308/jmg_2201.jpg
+ delete mode 120000 201308/jmg_2202.cr2
+ delete mode 120000 201308/jmg_2202.jpg
+ delete mode 120000 201308/jmg_2209.jpg
+ delete mode 120000 201308/jmg_2210.jpg
+ delete mode 120000 201308/jmg_2215.jpg
+ delete mode 120000 201308/jmg_2216.jpg
+ delete mode 120000 201308/jmg_2217.cr2
+ delete mode 120000 201308/jmg_2217.jpg
+ delete mode 120000 201308/jmg_2219.cr2
+ delete mode 120000 201308/jmg_2219.jpg
+ delete mode 120000 201308/jmg_2223.jpg
+ delete mode 120000 201308/jmg_2224.jpg
+ delete mode 120000 201308/jmg_2225.cr2
+ delete mode 120000 201308/jmg_2225.jpg
+ delete mode 120000 201308/jmg_2227.jpg
+ delete mode 120000 201308/jmg_2228.jpg
+ delete mode 120000 201308/jmg_2235.jpg
+ delete mode 120000 201308/jmg_2237.jpg
+ delete mode 120000 201308/jmg_2238.jpg
+ delete mode 120000 201308/jmg_2239.cr2
+ delete mode 120000 201308/jmg_2239.jpg
+ delete mode 120000 201308/jmg_2239_raw.jpg
+ delete mode 120000 201308/jmg_2240.jpg
+ delete mode 120000 201308/jmg_2243.jpg
+ delete mode 120000 201308/jmg_2244.jpg
+ delete mode 120000 201308/jmg_2245.jpg
+ delete mode 120000 201308/jmg_2247.cr2
+ delete mode 120000 201308/jmg_2247.jpg
+ delete mode 120000 201308/jmg_2249.jpg
+ delete mode 120000 201308/jmg_2250.cr2
+ delete mode 120000 201308/jmg_2250.jpg
+ delete mode 120000 201308/jmg_2252.jpg
+ delete mode 120000 201308/jmg_2253.jpg
+ delete mode 120000 201308/jmg_2254.jpg
+ create mode 120000 incoming/5d/201203/jmg_8701.cr2
+ create mode 120000 incoming/5d/201203/jmg_8702.jpg
+ create mode 120000 incoming/5d/201203/jmg_8705.jpg
+ create mode 120000 incoming/5d/201203/jmg_8711.jpg
+ create mode 120000 incoming/5d/201203/jmg_8717.jpg
+ create mode 120000 incoming/5d/201203/jmg_8718.jpg
+ create mode 120000 incoming/5d/201203/jmg_8719.jpg
+ create mode 120000 incoming/5d/201203/jmg_8721.jpg
+ create mode 120000 incoming/5d/201203/jmg_8725.jpg
+ create mode 120000 incoming/5d/201203/jmg_8726.jpg
+ create mode 120000 incoming/5d/201203/jmg_8731.jpg
+ create mode 120000 incoming/5d/201203/jmg_8745.jpg
+ create mode 120000 incoming/5d/201203/jmg_8747_raw.jpg
+ create mode 120000 incoming/5d/201203/jmg_8750.cr2
+ create mode 120000 incoming/5d/201203/jmg_8750.jpg
+ create mode 120000 incoming/5d/201207/jmg_9048.jpg
+ create mode 120000 incoming/5d/201207/jmg_9053.jpg
+ create mode 120000 incoming/5d/201207/jmg_9054.jpg
+ create mode 120000 incoming/5d/201207/jmg_9069.cr2
+ create mode 120000 incoming/5d/201207/jmg_9069.jpg
+ create mode 120000 incoming/5d/201207/jmg_9070.cr2
+ create mode 120000 incoming/5d/201207/jmg_9070.jpg
+ create mode 120000 incoming/5d/201207/jmg_9072.cr2
+ create mode 120000 incoming/5d/201207/jmg_9072.jpg
+ create mode 120000 incoming/5d/201207/jmg_9076.cr2
+ create mode 120000 incoming/5d/201207/jmg_9076.jpg
+ create mode 120000 incoming/5d/201302/jmg_0502.cr2
+ create mode 120000 incoming/5d/201302/jmg_0502.jpg
+ create mode 120000 incoming/5d/201302/jmg_0503.jpg
+ create mode 120000 incoming/5d/201302/jmg_0507.jpg
+ create mode 120000 incoming/5d/201302/jmg_0510.jpg
+ create mode 120000 incoming/5d/201302/jmg_0512.jpg
+ create mode 120000 incoming/5d/201302/jmg_0513.jpg
+ create mode 120000 incoming/5d/201302/jmg_0514.jpg
+ create mode 120000 incoming/5d/201302/jmg_0516.jpg
+ create mode 120000 incoming/5d/201302/jmg_0517.jpg
+ create mode 120000 incoming/5d/201302/jmg_0518.jpg
+ create mode 120000 incoming/5d/201302/jmg_0521.jpg
+ create mode 120000 incoming/5d/201302/jmg_0522.jpg
+ create mode 120000 incoming/5d/201302/jmg_0523.jpg
+ create mode 120000 incoming/5d/201302/jmg_0524.jpg
+ create mode 120000 incoming/5d/201302/jmg_0526.jpg
+ create mode 120000 incoming/5d/201302/jmg_0527.jpg
+ create mode 120000 incoming/5d/201302/jmg_0528.jpg
+ create mode 120000 incoming/5d/201302/jmg_0532.cr2
+ create mode 120000 incoming/5d/201302/jmg_0532.jpg
+ create mode 120000 incoming/5d/201302/jmg_0534.jpg
+ create mode 120000 incoming/5d/201302/jmg_0535.jpg
+ create mode 120000 incoming/5d/201302/jmg_0537.jpg
+ create mode 120000 incoming/5d/201302/jmg_0539.jpg
+ create mode 120000 incoming/5d/201302/jmg_0541.jpg
+ create mode 120000 incoming/5d/201302/jmg_0543.jpg
+ create mode 120000 incoming/5d/jmg_0021.jpg
+ create mode 120000 incoming/5d/jmg_0025.jpg
+ create mode 120000 incoming/5d/jmg_0026.jpg
+ create mode 120000 incoming/5d/jmg_0027.jpg
+ create mode 120000 incoming/5d/jmg_0034.jpg
+ create mode 120000 incoming/5d/jmg_0035.jpg
+ create mode 120000 incoming/5d/jmg_0036.jpg
+ create mode 120000 incoming/5d/jmg_0130.jpg
+ create mode 120000 incoming/5d/jmg_0131.jpg
+ create mode 120000 incoming/5d/jmg_0133.jpg
+ create mode 120000 incoming/5d/jmg_0155.jpg
+ create mode 120000 incoming/5d/jmg_0156.jpg
+ create mode 120000 incoming/5d/jmg_0158.cr2
+ create mode 120000 incoming/5d/jmg_0165.cr2
+ create mode 120000 incoming/5d/jmg_0166.cr2
+ create mode 120000 incoming/5d/jmg_0178.cr2
+ create mode 120000 incoming/5d/jmg_0179.jpg
+ create mode 120000 incoming/5d/jmg_0180.cr2
+ create mode 120000 incoming/5d/jmg_0184.jpg
+ create mode 120000 incoming/5d/jmg_0185.cr2
+ create mode 120000 incoming/5d/jmg_0187.cr2
+ create mode 120000 incoming/5d/jmg_0310.jpg
+ create mode 120000 incoming/5d/jmg_0312.jpg
+ create mode 120000 incoming/5d/jmg_0315.jpg
+ create mode 120000 incoming/5d/jmg_0340.jpg
+ create mode 120000 incoming/5d/jmg_0357.jpg
+ create mode 120000 incoming/5d/jmg_0364.jpg
+ create mode 120000 incoming/5d/jmg_0365.jpg
+ create mode 120000 incoming/5d/jmg_0368.jpg
+ create mode 120000 incoming/5d/jmg_0374.jpg
+ create mode 120000 incoming/5d/jmg_0375.jpg
+ create mode 120000 incoming/5d/jmg_0386.jpg
+ create mode 120000 incoming/5d/jmg_0399.jpg
+ create mode 120000 incoming/5d/jmg_0411.jpg
+ create mode 120000 incoming/5d/jmg_0418.jpg
+ create mode 120000 incoming/5d/jmg_0476.cr2
+ create mode 120000 incoming/5d/jmg_0476.jpg
+ create mode 120000 incoming/5d/jmg_0503.jpg
+ create mode 120000 incoming/5d/jmg_0507.cr2
+ create mode 120000 incoming/5d/jmg_0513.cr2
+ create mode 120000 incoming/5d/jmg_0513.jpg
+ create mode 120000 incoming/5d/jmg_0516.cr2
+ create mode 120000 incoming/5d/jmg_0517.cr2
+ create mode 120000 incoming/5d/jmg_0518.jpg
+ create mode 120000 incoming/5d/jmg_0522.cr2
+ create mode 120000 incoming/5d/jmg_0524.cr2
+ create mode 120000 incoming/5d/jmg_0524.jpg
+ create mode 120000 incoming/5d/jmg_0530.jpg
+ create mode 120000 incoming/5d/jmg_0541.cr2
+ create mode 120000 incoming/5d/jmg_0550.jpg
+ create mode 120000 incoming/5d/jmg_0554.jpg
+ create mode 120000 incoming/5d/jmg_0555.jpg
+ create mode 120000 incoming/5d/jmg_0558.jpg
+ create mode 120000 incoming/5d/jmg_0563.jpg
+ create mode 120000 incoming/5d/jmg_0573.jpg
+ create mode 120000 incoming/5d/jmg_0575.cr2
+ create mode 120000 incoming/5d/jmg_0578.cr2
+ create mode 120000 incoming/5d/jmg_0579.cr2
+ create mode 120000 incoming/5d/jmg_0582.jpg
+ create mode 120000 incoming/5d/jmg_0593.cr2
+ create mode 120000 incoming/5d/jmg_0594.cr2
+ create mode 120000 incoming/5d/jmg_0594.jpg
+ create mode 120000 incoming/5d/jmg_0595.cr2
+ create mode 120000 incoming/5d/jmg_0600.jpg
+ create mode 120000 incoming/5d/jmg_0606.cr2
+ create mode 120000 incoming/5d/jmg_0607.jpg
+ create mode 120000 incoming/5d/jmg_0610.cr2
+ create mode 120000 incoming/5d/jmg_0610.jpg
+ create mode 120000 incoming/5d/jmg_0612.jpg
+ create mode 120000 incoming/5d/jmg_0613.cr2
+ create mode 120000 incoming/5d/jmg_0614.jpg
+ create mode 120000 incoming/5d/jmg_0619.cr2
+ create mode 120000 incoming/5d/jmg_0623.jpg
+ create mode 120000 incoming/5d/jmg_0628.cr2
+ create mode 120000 incoming/5d/jmg_0628.jpg
+ create mode 120000 incoming/5d/jmg_0639.jpg
+ create mode 120000 incoming/5d/jmg_0645.cr2
+ create mode 120000 incoming/5d/jmg_0646.jpg
+ create mode 120000 incoming/5d/jmg_0647.cr2
+ create mode 120000 incoming/5d/jmg_0648.jpg
+ create mode 120000 incoming/5d/jmg_0649.jpg
+ create mode 120000 incoming/5d/jmg_0655.jpg
+ create mode 120000 incoming/5d/jmg_0667.jpg
+ create mode 120000 incoming/5d/jmg_0670.jpg
+ create mode 120000 incoming/5d/jmg_0673.jpg
+ create mode 120000 incoming/5d/jmg_0679.jpg
+ create mode 120000 incoming/5d/jmg_0685.jpg
+ create mode 120000 incoming/5d/jmg_0699.cr2
+ create mode 120000 incoming/5d/jmg_0700.cr2
+ create mode 120000 incoming/5d/jmg_0701.cr2
+ create mode 120000 incoming/5d/jmg_0708.jpg
+ create mode 120000 incoming/5d/jmg_0718.jpg
+ create mode 120000 incoming/5d/jmg_0726.cr2
+ create mode 120000 incoming/5d/jmg_0728.jpg
+ create mode 120000 incoming/5d/jmg_0730.jpg
+ create mode 120000 incoming/5d/jmg_0734.jpg
+ create mode 120000 incoming/5d/jmg_0740.jpg
+ create mode 120000 incoming/5d/jmg_0743.cr2
+ create mode 120000 incoming/5d/jmg_0744.cr2
+ create mode 120000 incoming/5d/jmg_0745.cr2
+ create mode 120000 incoming/5d/jmg_0747.jpg
+ create mode 120000 incoming/5d/jmg_0750.cr2
+ create mode 120000 incoming/5d/jmg_0755.cr2
+ create mode 120000 incoming/5d/jmg_0759.cr2
+ create mode 120000 incoming/5d/jmg_0760.cr2
+ create mode 120000 incoming/5d/jmg_0761.jpg
+ create mode 120000 incoming/5d/jmg_0765.jpg
+ create mode 120000 incoming/5d/jmg_0768.jpg
+ create mode 120000 incoming/5d/jmg_0771.jpg
+ create mode 120000 incoming/5d/jmg_0778.jpg
+ create mode 120000 incoming/5d/jmg_0780.jpg
+ create mode 120000 incoming/5d/jmg_0782.cr2
+ create mode 120000 incoming/5d/jmg_0786.cr2
+ create mode 120000 incoming/5d/jmg_0787.cr2
+ create mode 120000 incoming/5d/jmg_0788.cr2
+ create mode 120000 incoming/5d/jmg_0794.jpg
+ create mode 120000 incoming/5d/jmg_0796.jpg
+ create mode 120000 incoming/5d/jmg_0801.cr2
+ create mode 120000 incoming/5d/jmg_0803.cr2
+ create mode 120000 incoming/5d/jmg_0804.cr2
+ create mode 120000 incoming/5d/jmg_0812.jpg
+ create mode 120000 incoming/5d/jmg_0819.jpg
+ create mode 120000 incoming/5d/jmg_0827.jpg
+ create mode 120000 incoming/5d/jmg_0830.jpg
+ create mode 120000 incoming/5d/jmg_0842.jpg
+ create mode 120000 incoming/5d/jmg_0846.jpg
+ create mode 120000 incoming/5d/jmg_0857.cr2
+ create mode 120000 incoming/5d/jmg_0863.jpg
+ create mode 120000 incoming/5d/jmg_0866.cr2
+ create mode 120000 incoming/5d/jmg_0868.cr2
+ create mode 120000 incoming/5d/jmg_0868.jpg
+ create mode 120000 incoming/5d/jmg_0870.jpg
+ create mode 120000 incoming/5d/jmg_0877.jpg
+ create mode 120000 incoming/5d/jmg_0882.cr2
+ create mode 120000 incoming/5d/jmg_0883.jpg
+ create mode 120000 incoming/5d/jmg_0888.jpg
+ create mode 120000 incoming/5d/jmg_0891.jpg
+ create mode 120000 incoming/5d/jmg_0894.cr2
+ create mode 120000 incoming/5d/jmg_0896.cr2
+ create mode 120000 incoming/5d/jmg_0897.cr2
+ create mode 120000 incoming/5d/jmg_0898.jpg
+ create mode 120000 incoming/5d/jmg_0899.cr2
+ create mode 120000 incoming/5d/jmg_0900.jpg
+ create mode 120000 incoming/5d/jmg_0905.jpg
+ create mode 120000 incoming/5d/jmg_0908.jpg
+ create mode 120000 incoming/5d/jmg_0914.jpg
+ create mode 120000 incoming/5d/jmg_0915.jpg
+ create mode 120000 incoming/5d/jmg_0916.jpg
+ create mode 120000 incoming/5d/jmg_0923.jpg
+ create mode 120000 incoming/5d/jmg_0924.jpg
+ create mode 120000 incoming/5d/jmg_0926.jpg
+ create mode 120000 incoming/5d/jmg_0928.jpg
+ create mode 120000 incoming/5d/jmg_0929.jpg
+ create mode 120000 incoming/5d/jmg_0936.jpg
+ create mode 120000 incoming/5d/jmg_0942.jpg
+ create mode 120000 incoming/5d/jmg_0944.jpg
+ create mode 120000 incoming/5d/jmg_0948.jpg
+ create mode 120000 incoming/5d/jmg_0960.jpg
+ create mode 120000 incoming/5d/jmg_0966.jpg
+ create mode 120000 incoming/5d/jmg_0970.cr2
+ create mode 120000 incoming/5d/jmg_0970.jpg
+ create mode 120000 incoming/5d/jmg_0972.jpg
+ create mode 120000 incoming/5d/jmg_0976.jpg
+ create mode 120000 incoming/5d/jmg_0983.cr2
+ create mode 120000 incoming/5d/jmg_0985.cr2
+ create mode 120000 incoming/5d/jmg_0985.jpg
+ create mode 120000 incoming/5d/jmg_0994.jpg
+ create mode 120000 incoming/5d/jmg_1209.cr2
+ create mode 120000 incoming/5d/jmg_1209.jpg
+ create mode 120000 incoming/5d/jmg_1211.cr2
+ create mode 120000 incoming/5d/jmg_1211.jpg
+ create mode 120000 incoming/5d/jmg_1217.cr2
+ create mode 120000 incoming/5d/jmg_1467.cr2
+ create mode 120000 incoming/5d/jmg_1469.jpg
+ create mode 120000 incoming/5d/jmg_1470.cr2
+ create mode 120000 incoming/5d/jmg_1471.cr2
+ create mode 120000 incoming/5d/jmg_1472.cr2
+ create mode 120000 incoming/5d/jmg_1477.cr2
+ create mode 120000 incoming/5d/jmg_1477.jpg
+ create mode 120000 incoming/5d/jmg_1481.cr2
+ create mode 120000 incoming/5d/jmg_1483.cr2
+ create mode 120000 incoming/5d/jmg_1485.jpg
+ create mode 120000 incoming/5d/jmg_1488.jpg
+ create mode 120000 incoming/5d/jmg_1491.jpg
+ create mode 120000 incoming/5d/jmg_1496.cr2
+ create mode 120000 incoming/5d/jmg_1502.jpg
+ create mode 120000 incoming/5d/jmg_1503.cr2
+ create mode 120000 incoming/5d/jmg_1504.jpg
+ create mode 120000 incoming/5d/jmg_1507.jpg
+ create mode 120000 incoming/5d/jmg_1515.jpg
+ create mode 120000 incoming/5d/jmg_1520.jpg
+ create mode 120000 incoming/5d/jmg_1523.jpg
+ create mode 120000 incoming/5d/jmg_1525.jpg
+ create mode 120000 incoming/5d/jmg_1539.jpg
+ create mode 120000 incoming/5d/jmg_1542.jpg
+ create mode 120000 incoming/5d/jmg_1546.jpg
+ create mode 120000 incoming/5d/jmg_1547.cr2
+ create mode 120000 incoming/5d/jmg_1549.jpg
+ create mode 120000 incoming/5d/jmg_1552.jpg
+ create mode 120000 incoming/5d/jmg_1554.cr2
+ create mode 120000 incoming/5d/jmg_1555.cr2
+ create mode 120000 incoming/5d/jmg_1556.cr2
+ create mode 120000 incoming/5d/jmg_1559.cr2
+ create mode 120000 incoming/5d/jmg_1560.cr2
+ create mode 120000 incoming/5d/jmg_1561.cr2
+ create mode 120000 incoming/5d/jmg_1562.cr2
+ create mode 120000 incoming/5d/jmg_1565.cr2
+ create mode 120000 incoming/5d/jmg_1567.cr2
+ create mode 120000 incoming/5d/jmg_1572.cr2
+ create mode 120000 incoming/5d/jmg_1577.cr2
+ create mode 120000 incoming/5d/jmg_1578.jpg
+ create mode 120000 incoming/5d/jmg_1583_cut.jpg
+ create mode 120000 incoming/5d/jmg_1583_raw.jpg
+ create mode 120000 incoming/5d/jmg_1592.cr2
+ create mode 120000 incoming/5d/jmg_1593.jpg
+ create mode 120000 incoming/5d/jmg_1626.cr2
+ create mode 120000 incoming/5d/jmg_1627.jpg
+ create mode 120000 incoming/5d/jmg_1628.cr2
+ create mode 120000 incoming/5d/jmg_1629.jpg
+ create mode 120000 incoming/5d/jmg_1630.cr2
+ create mode 120000 incoming/5d/jmg_1631.cr2
+ create mode 120000 incoming/5d/jmg_1633.cr2
+ create mode 120000 incoming/5d/jmg_1638.jpg
+ create mode 120000 incoming/5d/jmg_1639.cr2
+ create mode 120000 incoming/5d/jmg_1646.cr2
+ create mode 120000 incoming/5d/jmg_1646.jpg
+ create mode 120000 incoming/5d/jmg_1650.jpg
+ create mode 120000 incoming/5d/jmg_1651.cr2
+ create mode 120000 incoming/5d/jmg_1654.cr2
+ create mode 120000 incoming/5d/jmg_1656.jpg
+ create mode 120000 incoming/5d/jmg_1677.jpg
+ create mode 120000 incoming/5d/jmg_1689.jpg
+ create mode 120000 incoming/5d/jmg_1701.jpg
+ create mode 120000 incoming/5d/jmg_1703.jpg
+ create mode 120000 incoming/5d/jmg_1723.jpg
+ create mode 120000 incoming/5d/jmg_2039.jpg
+ create mode 120000 incoming/5d/jmg_2041.jpg
+ create mode 120000 incoming/5d/jmg_2048.cr2
+ create mode 120000 incoming/5d/jmg_2052.jpg
+ create mode 120000 incoming/5d/jmg_2061.jpg
+ delete mode 120000 incoming/5d/jmg_2064_raw.jpg
+ delete mode 120000 incoming/5d/jmg_2065_mo.jpg
+ delete mode 120000 incoming/5d/jmg_2065_raw.jpg
+ delete mode 120000 incoming/5d/jmg_2066_mo.jpg
+ delete mode 120000 incoming/5d/jmg_2066_raw.jpg
+ create mode 120000 incoming/5d/jmg_2090.jpg
+ create mode 120000 incoming/5d/jmg_2093.jpg
+ create mode 120000 incoming/5d/jmg_2100.cr2
+ create mode 120000 incoming/5d/jmg_2103.jpg
+ create mode 120000 incoming/5d/jmg_2107.jpg
+ create mode 120000 incoming/5d/jmg_2108.jpg
+ create mode 120000 incoming/5d/jmg_2112.jpg
+ create mode 120000 incoming/5d/jmg_2118.jpg
+ create mode 120000 incoming/5d/jmg_2119.jpg
+ create mode 120000 incoming/5d/jmg_2122.jpg
+ create mode 120000 incoming/5d/jmg_2125.jpg
+ create mode 120000 incoming/5d/jmg_2137.jpg
+ create mode 120000 incoming/5d/jmg_2149.jpg
+ create mode 120000 incoming/5d/jmg_2150.jpg
+ create mode 120000 incoming/5d/jmg_2158.cr2
+ create mode 120000 incoming/5d/jmg_2160.jpg
+ create mode 120000 incoming/5d/jmg_2165.jpg
+ create mode 120000 incoming/5d/jmg_2188.jpg
+ create mode 120000 incoming/5d/jmg_2189.jpg
+ create mode 120000 incoming/5d/jmg_2193.jpg
+ create mode 120000 incoming/5d/jmg_2194.cr2
+ create mode 120000 incoming/5d/jmg_2200.jpg
+ create mode 120000 incoming/5d/jmg_2201.cr2
+ create mode 120000 incoming/5d/jmg_2201.jpg
+ create mode 120000 incoming/5d/jmg_2210.jpg
+ create mode 120000 incoming/5d/jmg_2215.cr2
+ create mode 120000 incoming/5d/jmg_2216.cr2
+ create mode 120000 incoming/5d/jmg_2216.jpg
+ create mode 120000 incoming/5d/jmg_2224.jpg
+ create mode 120000 incoming/5d/jmg_2235.jpg
+ create mode 120000 incoming/5d/jmg_2238.jpg
+ create mode 120000 incoming/5d/jmg_2239.cr2
+ create mode 120000 incoming/5d/jmg_2239.jpg
+ create mode 120000 incoming/5d/jmg_2240.jpg
+ create mode 120000 incoming/5d/jmg_2244.jpg
+ create mode 120000 incoming/5d/jmg_2247.jpg
+ create mode 120000 incoming/5d/jmg_7250.cr2
+ create mode 120000 incoming/5d/jmg_7250.jpg
+ create mode 120000 incoming/5d/jmg_7256.jpg
+ create mode 120000 incoming/5d/jmg_7257.cr2
+ create mode 120000 incoming/5d/jmg_7259.cr2
+ create mode 120000 incoming/5d/jmg_7263.jpg
+ create mode 120000 incoming/5d/jmg_7265.cr2
+ create mode 120000 incoming/5d/jmg_7269.cr2
+ create mode 120000 incoming/5d/jmg_7270.cr2
+ create mode 120000 incoming/5d/jmg_7279.cr2
+ create mode 120000 incoming/5d/jmg_7286.cr2
+ create mode 120000 incoming/5d/jmg_7286.jpg
+ create mode 120000 incoming/5d/jmg_7290.cr2
+ create mode 120000 incoming/5d/jmg_7290.jpg
+ create mode 120000 incoming/5d/jmg_7293.cr2
+ create mode 120000 incoming/5d/jmg_7296.cr2
+ create mode 120000 incoming/5d/jmg_7299.jpg
+ create mode 120000 incoming/5d/jmg_7300.cr2
+ create mode 120000 incoming/5d/jmg_7300.jpg
+ create mode 120000 incoming/5d/jmg_7305_raw.jpg
+ create mode 120000 incoming/5d/jmg_8532.cr2
+ create mode 120000 incoming/5d/jmg_8533.cr2
+ create mode 120000 incoming/5d/jmg_8534.cr2
+ create mode 120000 incoming/5d/jmg_8536.jpg
+ create mode 120000 incoming/5d/jmg_8538.cr2
+ create mode 120000 incoming/5d/jmg_8549.cr2
+ create mode 120000 incoming/5d/jmg_8549.jpg
+ create mode 120000 incoming/5d/jmg_8552.cr2
+ create mode 120000 incoming/5d/jmg_8557.cr2
+ create mode 120000 incoming/5d/jmg_8560.cr2
+ create mode 120000 incoming/5d/jmg_8565.cr2
+ create mode 120000 incoming/5d/jmg_8566.cr2
+ create mode 120000 incoming/5d/jmg_8569.jpg
+ create mode 120000 incoming/5d/jmg_8575.jpg
+ create mode 120000 incoming/5d/jmg_8576.jpg
+ create mode 120000 incoming/5d/jmg_8578.cr2
+ create mode 120000 incoming/5d/jmg_8579.cr2
+ create mode 120000 incoming/5d/jmg_8580.jpg
+ create mode 120000 incoming/5d/jmg_8583.cr2
+ create mode 120000 incoming/5d/jmg_8588.cr2
+ create mode 120000 incoming/5d/jmg_8589.cr2
+ create mode 120000 incoming/5d/jmg_8595.jpg
+ create mode 120000 incoming/5d/jmg_8597.jpg
+ create mode 120000 incoming/5d/jmg_8599.jpg
+ create mode 120000 incoming/5d/jmg_8602.cr2
+ create mode 120000 incoming/5d/jmg_8603.cr2
+ create mode 120000 incoming/5d/jmg_8606.cr2
+ create mode 120000 incoming/5d/jmg_8606.jpg
+ create mode 120000 incoming/5d/jmg_8609.jpg
+ create mode 120000 incoming/5d/jmg_8613.jpg
+ create mode 120000 incoming/5d/jmg_8615.cr2
+ create mode 120000 incoming/5d/jmg_8617.jpg
+ create mode 120000 incoming/5d/jmg_8619.cr2
+ create mode 120000 incoming/5d/jmg_8620.jpg
+ create mode 120000 incoming/5d/jmg_8625.jpg
+ create mode 120000 incoming/5d/jmg_8627.jpg
+ create mode 120000 incoming/5d/jmg_8628.jpg
+ create mode 120000 incoming/5d/jmg_8632.cr2
+ create mode 120000 incoming/5d/jmg_8636.cr2
+ create mode 120000 incoming/5d/jmg_8636.jpg
+ create mode 120000 incoming/5d/jmg_8637.cr2
+ create mode 120000 incoming/5d/jmg_8639.jpg
+ create mode 120000 incoming/5d/jmg_8640.cr2
+ create mode 120000 incoming/5d/jmg_8655.jpg
+ create mode 120000 incoming/5d/jmg_8657.jpg
+ create mode 120000 incoming/5d/jmg_8670.cr2
+ create mode 120000 incoming/5d/jmg_8673.jpg
+ create mode 120000 incoming/5d/jmg_8674.cr2
+ create mode 120000 incoming/5d/jmg_8676.cr2
+ create mode 120000 incoming/5d/jmg_8676.jpg
+ create mode 120000 incoming/5d/jmg_8677.cr2
+ create mode 120000 incoming/5d/jmg_8681.jpg
+ create mode 120000 incoming/5d/jmg_8682.cr2
+ create mode 120000 incoming/5d/jmg_8702.cr2
+ create mode 120000 incoming/5d/jmg_8702.jpg
+ create mode 120000 incoming/5d/jmg_8707.jpg
+ create mode 120000 incoming/5d/jmg_8714.jpg
+ create mode 120000 incoming/5d/jmg_8716.jpg
+ create mode 120000 incoming/5d/jmg_8717.cr2
+ create mode 120000 incoming/5d/jmg_8719.jpg
+ create mode 120000 incoming/5d/jmg_8721.jpg
+ create mode 120000 incoming/5d/jmg_8727.cr2
+ create mode 120000 incoming/5d/jmg_8730.jpg
+ create mode 120000 incoming/5d/jmg_8736.cr2
+ create mode 120000 incoming/5d/jmg_8737.cr2
+ create mode 120000 incoming/5d/jmg_8742.cr2
+ create mode 120000 incoming/5d/jmg_8742.jpg
+ create mode 120000 incoming/5d/jmg_8745.jpg
+ create mode 120000 incoming/5d/jmg_8748.cr2
+ create mode 120000 incoming/5d/jmg_8748.jpg
+ create mode 120000 incoming/5d/jmg_8751.cr2
+ create mode 120000 incoming/5d/jmg_8755.cr2
+ create mode 120000 incoming/5d/jmg_8757.cr2
+ create mode 120000 incoming/5d/jmg_8760.cr2
+ create mode 120000 incoming/5d/jmg_8760.jpg
+ create mode 120000 incoming/5d/jmg_8765.cr2
+ create mode 120000 incoming/5d/jmg_8771.jpg
+ create mode 120000 incoming/5d/jmg_8801.jpg
+ create mode 120000 incoming/5d/jmg_8803.cr2
+ create mode 120000 incoming/5d/jmg_8803.jpg
+ create mode 120000 incoming/5d/jmg_8804.jpg
+ create mode 120000 incoming/5d/jmg_8805.jpg
+ create mode 120000 incoming/5d/jmg_8813.jpg
+ create mode 120000 incoming/5d/jmg_8816.cr2
+ create mode 120000 incoming/5d/jmg_8823.jpg
+ create mode 120000 incoming/5d/jmg_8827.cr2
+ create mode 120000 incoming/5d/jmg_8829.cr2
+ create mode 120000 incoming/5d/jmg_8832.jpg
+ create mode 120000 incoming/5d/jmg_8833.cr2
+ create mode 120000 incoming/5d/jmg_8837.cr2
+ create mode 120000 incoming/5d/jmg_8838.jpg
+ create mode 120000 incoming/5d/jmg_8840.jpg
+ create mode 120000 incoming/5d/jmg_8842.jpg
+ create mode 120000 incoming/5d/jmg_8844.cr2
+ create mode 120000 incoming/5d/jmg_8850.cr2
+ create mode 120000 incoming/5d/jmg_8850.jpg
+ create mode 120000 incoming/5d/jmg_8852.cr2
+ create mode 120000 incoming/5d/jmg_8853.cr2
+ create mode 120000 incoming/5d/jmg_8853.jpg
+ create mode 120000 incoming/5d/jmg_8856.cr2
+ create mode 120000 incoming/5d/jmg_8859.jpg
+ create mode 120000 incoming/5d/jmg_8863.jpg
+ create mode 120000 incoming/5d/jmg_8870.jpg
+ create mode 120000 incoming/5d/jmg_8871.cr2
+ create mode 120000 incoming/5d/jmg_8871.jpg
+ create mode 120000 incoming/5d/jmg_8881.jpg
+ create mode 120000 incoming/5d/jmg_8883.jpg
+ create mode 120000 incoming/5d/jmg_8886.jpg
+ create mode 120000 incoming/5d/jmg_8887.cr2
+ create mode 120000 incoming/5d/jmg_8889.cr2
+ create mode 120000 incoming/5d/jmg_8894.cr2
+ create mode 120000 incoming/5d/jmg_8897.cr2
+ create mode 120000 incoming/5d/jmg_8898.cr2
+ create mode 120000 incoming/5d/jmg_8900.jpg
+ create mode 120000 incoming/5d/jmg_8901.cr2
+ create mode 120000 incoming/5d/jmg_8902.cr2
+ create mode 120000 incoming/5d/jmg_8904.cr2
+ create mode 120000 incoming/5d/jmg_8906.jpg
+ create mode 120000 incoming/5d/jmg_8908.cr2
+ create mode 120000 incoming/5d/jmg_8920.cr2
+ create mode 120000 incoming/5d/jmg_8920.jpg
+ create mode 120000 incoming/5d/jmg_8922.cr2
+ create mode 120000 incoming/5d/jmg_8922.jpg
+ create mode 120000 incoming/5d/jmg_8923.cr2
+ create mode 120000 incoming/5d/jmg_8924.jpg
+ create mode 120000 incoming/5d/jmg_8925.cr2
+ create mode 120000 incoming/5d/jmg_8929.jpg
+ create mode 120000 incoming/5d/jmg_8930.jpg
+ create mode 120000 incoming/5d/jmg_8937.cr2
+ create mode 120000 incoming/5d/jmg_8939.cr2
+ create mode 120000 incoming/5d/jmg_8940.jpg
+ create mode 120000 incoming/5d/jmg_8941.jpg
+ create mode 120000 incoming/5d/jmg_8943.cr2
+ create mode 120000 incoming/5d/jmg_8944.jpg
+ create mode 120000 incoming/5d/jmg_8950.cr2
+ create mode 120000 incoming/5d/jmg_8951.jpg
+ create mode 120000 incoming/5d/jmg_8955.jpg
+ create mode 120000 incoming/5d/jmg_8959.cr2
+ create mode 120000 incoming/5d/jmg_8960.jpg
+ create mode 120000 incoming/5d/jmg_8962.cr2
+ create mode 120000 incoming/5d/jmg_8964.cr2
+ create mode 120000 incoming/5d/jmg_8965.jpg
+ create mode 120000 incoming/5d/jmg_8966.jpg
+ create mode 120000 incoming/5d/jmg_8971.jpg
+ create mode 120000 incoming/5d/jmg_8976.jpg
+ create mode 120000 incoming/5d/jmg_8978.cr2
+ create mode 120000 incoming/5d/jmg_8981.jpg
+ create mode 120000 incoming/5d/jmg_8982.jpg
+ create mode 120000 incoming/5d/jmg_8985.jpg
+ create mode 120000 incoming/5d/jmg_8988.cr2
+ create mode 120000 incoming/5d/jmg_8988.jpg
+ create mode 120000 incoming/5d/jmg_8992.cr2
+ create mode 120000 incoming/5d/jmg_8995.jpg
+ create mode 120000 incoming/5d/jmg_8996.cr2
+ create mode 120000 incoming/5d/jmg_8997.cr2
+ create mode 120000 incoming/5d/jmg_8999.cr2
+ create mode 120000 incoming/5d/jmg_9000.cr2
+ create mode 120000 incoming/5d/jmg_9015.cr2
+ create mode 120000 incoming/5d/jmg_9017.cr2
+ create mode 120000 incoming/5d/jmg_9019.cr2
+ create mode 120000 incoming/5d/jmg_9021.cr2
+ create mode 120000 incoming/5d/jmg_9021.jpg
+ create mode 120000 incoming/5d/jmg_9022.cr2
+ create mode 120000 incoming/5d/jmg_9027.cr2
+ create mode 120000 incoming/5d/jmg_9028.jpg
+ create mode 120000 incoming/5d/jmg_9031.cr2
+ create mode 120000 incoming/5d/jmg_9035.cr2
+ create mode 120000 incoming/5d/jmg_9043.jpg
+ create mode 120000 incoming/5d/jmg_9057.cr2
+ create mode 120000 incoming/5d/jmg_9064.cr2
+ create mode 120000 incoming/5d/jmg_9077.jpg
+ create mode 120000 incoming/5d/jmg_9078.jpg
+ create mode 120000 incoming/5d/jmg_9081.jpg
+ create mode 120000 incoming/5d/jmg_9082.cr2
+ create mode 120000 incoming/5d/jmg_9083.jpg
+ create mode 120000 incoming/5d/jmg_9086.cr2
+ create mode 120000 incoming/5d/jmg_9088.jpg
+ create mode 120000 incoming/5d/jmg_9308.jpg
+ create mode 120000 incoming/5d/jmg_9312.cr2
+ create mode 120000 incoming/5d/jmg_9313.jpg
+ create mode 120000 incoming/5d/jmg_9319.jpg
+ create mode 120000 incoming/5d/jmg_9521.cr2
+ create mode 120000 incoming/5d/jmg_9522.cr2
+ create mode 120000 incoming/5d/jmg_9533.jpg
+ create mode 120000 incoming/5d/jmg_9534.jpg
+ create mode 120000 incoming/5d/jmg_9535.cr2
+ create mode 120000 incoming/5d/jmg_9538.cr2
+ create mode 120000 incoming/5d/jmg_9538.jpg
+ create mode 120000 incoming/5d/jmg_9540.jpg
+ create mode 120000 incoming/5d/jmg_9542.cr2
+ create mode 120000 incoming/5d/jmg_9545.jpg
+ create mode 120000 incoming/5d/jmg_9554.jpg
+ create mode 120000 incoming/5d/jmg_9555.jpg
+ create mode 120000 incoming/5d/jmg_9558.jpg
+ create mode 120000 incoming/5d/jmg_9561.cr2
+ create mode 120000 incoming/5d/jmg_9585.cr2
+ create mode 120000 incoming/5d/jmg_9587.jpg
+ create mode 120000 incoming/5d/jmg_9591.jpg
+ create mode 120000 incoming/5d/jmg_9595.jpg
+ create mode 120000 incoming/5d/jmg_9598.cr2
+ create mode 120000 incoming/5d/jmg_9600.jpg
+ create mode 120000 incoming/5d/jmg_9604.jpg
+ create mode 120000 incoming/5d/jmg_9610.jpg
+ create mode 120000 incoming/5d/jmg_9613.cr2
+ create mode 120000 incoming/5d/jmg_9613.jpg
+ create mode 120000 incoming/5d/jmg_9614.cr2
+ create mode 120000 incoming/5d/jmg_9618.jpg
+ create mode 120000 incoming/5d/jmg_9619.jpg
+ create mode 120000 incoming/5d/jmg_9620.jpg
+ create mode 120000 incoming/5d/jmg_9621.jpg
+ create mode 120000 incoming/5d/jmg_9623.cr2
+ create mode 120000 incoming/5d/jmg_9746.jpg
+ create mode 120000 incoming/5d/jmg_9763.cr2
+ create mode 120000 incoming/5d/jmg_9763.jpg
+ create mode 120000 incoming/5d/jmg_9764.cr2
+ create mode 120000 incoming/5d/jmg_9772.jpg
+ create mode 120000 incoming/5d/jmg_9773.jpg
+ create mode 120000 incoming/5d/jmg_9781.jpg
+ create mode 120000 incoming/5d/jmg_9790.jpg
+ create mode 120000 incoming/5d/jmg_9800.jpg
+ create mode 120000 incoming/5d/jmg_9808.jpg
+ create mode 120000 incoming/5d/jmg_9830.jpg
+ create mode 120000 incoming/5d/jmg_9834.cr2
+ create mode 120000 incoming/5d/jmg_9843.jpg
+ create mode 120000 incoming/5d/jmg_9848.jpg
+ create mode 120000 incoming/5d/jmg_9849.jpg
+ create mode 120000 incoming/5d/jmg_9853.cr2
+ create mode 120000 incoming/5d/jmg_9856.jpg
+ create mode 120000 incoming/5d/jmg_9857.cr2
+ create mode 120000 incoming/5d/jmg_9859.cr2
+ create mode 120000 incoming/5d/jmg_9860.jpg
+ create mode 120000 incoming/5d/jmg_9917.jpg
+ create mode 120000 incoming/5d/jmg_9923.jpg
+ create mode 120000 incoming/5d/jmg_9926.jpg
+ create mode 120000 incoming/5d/jmg_9975.cr2
+ create mode 120000 incoming/5d/jmg_9976.cr2
+ create mode 120000 incoming/5d/jmg_9978.jpg
+ create mode 120000 incoming/5d/jmg_9988.jpg
+ create mode 120000 incoming/5d/jmg_9997.cr2
+ create mode 120000 incoming/5d/jmg_9998.jpg
+ create mode 120000 incoming/5d/jmg_9999.jpg
+ delete mode 120000 list_5d_repoB
+ create mode 120000 only_on_repoB
+ delete mode 120000 dir/2012/dir2/jmg_0128.cr2
+ delete mode 120000 dir/2012/dir2/jmg_0128.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0129.cr2
+ delete mode 120000 dir/2012/dir2/jmg_0129.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0353.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0354.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0375.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0376.jpg
+ delete mode 120000 dir/2012/dir2/jmg_0378.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8707.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8707.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8727.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8727.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8728.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8728.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8729.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8729.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8740.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8740.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8742.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8742.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8825.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8825.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8991.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8991.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8992.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8992.jpg
+ delete mode 120000 dir/2012/dir2/jmg_8993.cr2
+ delete mode 120000 dir/2012/dir2/jmg_8993.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9059.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9059.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9060.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9060.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9064.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9064.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9065.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9065.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9081.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9081.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9082.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9082.jpg
+ delete mode 120000 dir/2012/dir2/jmg_9083.cr2
+ delete mode 120000 dir/2012/dir2/jmg_9083.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0132.cr2
+ delete mode 120000 dir/2012/dir1/jmg_0132.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0133.cr2
+ delete mode 120000 dir/2012/dir1/jmg_0133.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0347.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0351.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0352.jpg
+ delete mode 120000 dir/2012/dir1/jmg_0374.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8714.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8714.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8716.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8716.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8734.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8734.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8735.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8735.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8736.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8736.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8743.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8743.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8746.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8746.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8828.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8828.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8984.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8984.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8985.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8985.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8986.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8986.jpg
+ delete mode 120000 dir/2012/dir1/jmg_8988.cr2
+ delete mode 120000 dir/2012/dir1/jmg_8988.jpg
+ delete mode 120000 dir/2012/dir1/jmg_9057.cr2
+ delete mode 120000 dir/2012/dir1/jmg_9057.jpg
+ delete mode 120000 dir/2012/dir1/jmg_9058.cr2
+ delete mode 120000 dir/2012/dir1/jmg_9058.jpg
+ delete mode 120000 dir/2012/dir1/jmg_9086.cr2
+ delete mode 120000 dir/2012/dir1/jmg_9086.jpg
+ delete mode 120000 dir/2012/dir1/jmg_9087.cr2
+ delete mode 120000 dir/2012/dir1/jmg_9087.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0477.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0477.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0478.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0478.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0479.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0479.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0604.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0604.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0605.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0605.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0606.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0606.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0607.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0607.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0608.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0608.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0708.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0708.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0709.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0709.jpg
+ delete mode 120000 dir/2013/dir2/jmg_0710.cr2
+ delete mode 120000 dir/2013/dir2/jmg_0710.jpg
+ delete mode 120000 dir/2013/dir1/jmg_0475.cr2
+ delete mode 120000 dir/2013/dir1/jmg_0475.jpg
+ delete mode 120000 dir/2013/dir1/jmg_0476.cr2
+ delete mode 120000 dir/2013/dir1/jmg_0476.jpg
+ delete mode 120000 dir/2013/dir1/jmg_0718.cr2
+ delete mode 120000 dir/2013/dir1/jmg_0718.jpg
+ delete mode 120000 dir/2013/dir1/jmg_0719.cr2
+ delete mode 120000 dir/2013/dir1/jmg_0719.jpg
+Already up-to-date.
+[2013-10-27 18:36:44 CET] Committer: Committing changes to git
+[2013-10-27 18:36:44 CET] Pusher: Syncing with repoB
+Already up-to-date.
+fatal: Unable to create '/media/srv/img/.git/refs/heads/synced/git-annex.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.
+fatal: The remote end hung up unexpectedly
+fatal: The remote end hung up unexpectedly
+From repoB:/media/srv/img
+ 276f659..5eba12c synced/git-annex -> repoB/synced/git-annex
+Everything up-to-date
+[2013-10-27 18:36:50 CET] Committer: Committing changes to git
+[2013-10-27 18:36:51 CET] Pusher: Syncing with repoB
+[2013-10-27 18:36:52 CET] Transferrer: Downloaded only_on_repoB
+[2013-10-27 18:36:53 CET] Transferrer: Downloaded jmg_9077.jpg
+[2013-10-27 18:36:58 CET] Committer: Committing changes to git
+[2013-10-27 18:36:58 CET] Transferrer: Downloaded jmg_8676.cr2
+[2013-10-27 18:36:59 CET] Committer: Committing changes to git
+[2013-10-27 18:37:02 CET] Transferrer: Downloaded jmg_0021.jpg
+[2013-10-27 18:37:02 CET] Committer: Committing changes to git
+[2013-10-27 18:37:04 CET] Transferrer: Downloaded jmg_0025.jpg
+[2013-10-27 18:37:04 CET] Committer: Committing changes to git
+[2013-10-27 18:37:06 CET] Transferrer: Downloaded jmg_0026.jpg
+[2013-10-27 18:37:06 CET] Committer: Committing changes to git
+[2013-10-27 18:37:07 CET] Transferrer: Downloaded jmg_0027.jpg
+[2013-10-27 18:37:07 CET] Committer: Committing changes to git
+[2013-10-27 18:37:10 CET] Transferrer: Downloaded jmg_0034.jpg
+[2013-10-27 18:37:10 CET] Committer: Committing changes to git
+[2013-10-27 18:37:12 CET] Transferrer: Downloaded jmg_0035.jpg
+[2013-10-27 18:37:12 CET] Committer: Committing changes to git
+[2013-10-27 18:37:15 CET] Transferrer: Downloaded jmg_0036.jpg
+[2013-10-27 18:37:15 CET] Committer: Committing changes to git
+[2013-10-27 18:37:17 CET] Transferrer: Downloaded jmg_0130.jpg
+[2013-10-27 18:37:17 CET] Committer: Committing changes to git
+[2013-10-27 18:37:18 CET] Transferrer: Downloaded jmg_0131.jpg
+[2013-10-27 18:37:18 CET] Committer: Committing changes to git
+[2013-10-27 18:37:20 CET] Transferrer: Downloaded jmg_0155.jpg
+[2013-10-27 18:37:20 CET] Committer: Committing changes to git
+[2013-10-27 18:37:23 CET] Transferrer: Downloaded jmg_0156.jpg
+[2013-10-27 18:37:23 CET] Committer: Committing changes to git
+[2013-10-27 18:37:27 CET] Transferrer: Downloaded jmg_0158.cr2
+[2013-10-27 18:37:27 CET] Committer: Committing changes to git
+[2013-10-27 18:37:32 CET] Transferrer: Downloaded jmg_0165.cr2
+[2013-10-27 18:37:32 CET] Committer: Committing changes to git
+[2013-10-27 18:37:37 CET] Transferrer: Downloaded jmg_0166.cr2
+[2013-10-27 18:37:37 CET] Committer: Committing changes to git
+To repoB:/media/srv/img/
+ 276f659..5eba12c git-annex -> synced/git-annex
+To repoB:/media/srv/img/
+ 5eba12c..f00ee07 git-annex -> synced/git-annex
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(merging repoB/git-annex into git-annex...)
+
+
+(Recording state in git...)
+
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+# End of transcript or log.
+"""]]
+
+> [[done]], seems this was caused by the bug I alread fixed. --[[Joey]]
diff --git a/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_1_ae4a13ff121d27f78904eee9bf5e716b._comment b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_1_ae4a13ff121d27f78904eee9bf5e716b._comment
new file mode 100644
index 000000000..88b293284
--- /dev/null
+++ b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_1_ae4a13ff121d27f78904eee9bf5e716b._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-28T22:02:30Z"
+ content="""
+So this sounds like [[bugs/direct_mode_assistant_in_subdir_confusion]], which was fixed in 4.20131024. Is there a possibility that you started the git-annex assistant (or webapp) from within `incoming/5d` ?
+
+I'm not sure if the bug could also cause the removal of directories to happen in the wrong location.
+
+
+----
+
+It should be possible to revert these changes and get your files back.
+
+1. `git annex indirect`
+2. `git log --stat` (find the commit that deleted files)
+3. `git revert $commit`
+4. `git annex direct`
+"""]]
diff --git a/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_2_32e360cd7b100ddb9a526e7833fc55e1._comment b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_2_32e360cd7b100ddb9a526e7833fc55e1._comment
new file mode 100644
index 000000000..1a7e4e16c
--- /dev/null
+++ b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_2_32e360cd7b100ddb9a526e7833fc55e1._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnh6wz0pMA3NLPFg2j_I3S5JeinaOVqnng"
+ nickname="Felix"
+ subject="comment 2"
+ date="2013-10-30T22:55:36Z"
+ content="""
+It's quite possible that I have started the assistant (on the armhf machine) or the webapp (on the amd64 machine) in one of the subfolders, so yes it looks like that specific bug hit me.
+
+Having looked at the logs, I'm pretty sure that the removal of the original directory was caused by removing the suddenly occuring \"mirror\" folders in a subdirectory.
+***
+Reverting proves to be difficult. I created a full copy of the git-annex repo and switched to indirect mode. There are around 500 commits that need to be reverted and about 6 of them are merges which I haven't been able to revert. I have only reverted the non-merge commits and after going back to direct mode there are now around 200 broken symlinks. I'm now assuming that those 200 are the ones that are lost and I need to restore from a backup. Can I rely on that? It's extremely difficult for me to do a full check.
+***
+How should I proceed to get this repo (after further repairs) again in sync with the second repo and have the second repo adopt the \"repaired\" state?
+
+"""]]
diff --git a/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_3_650dc9ede4e16ef668d96840f63dad47._comment b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_3_650dc9ede4e16ef668d96840f63dad47._comment
new file mode 100644
index 000000000..4e7d6491c
--- /dev/null
+++ b/doc/bugs/During_synchronisation_top-level_folder_suddenly_appear_in_sub-sub-folder/comment_3_650dc9ede4e16ef668d96840f63dad47._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T20:03:33Z"
+ content="""
+I don't understand why there are so many commits that need to be reverted. I'd have thought that it would have only made one bad commit due to the bug, and reverting that would do. Or even just adding back any symlinks removed by any of the bad commits, without an explicit revert would accomplish the same.
+
+You should be able to check with `git annex whereis --not --in .` what git-annex thinks about the 200 broken symlinks. Clearly their content is not in the local repisitory; it may be present elsewhere, or you might have to restore those files from backup.
+
+Once you have the git tree of the repository back in good shape, assuming you did it by committing changes, and possibly committing git reverts, you should be able to just use normal git annex syncing to sync those changes to the second repo. Ie, `git annex sync` in both, or running the assistant.
+"""]]
diff --git a/doc/bugs/Endless_SSH_password_prompts.mdwn b/doc/bugs/Endless_SSH_password_prompts.mdwn
new file mode 100644
index 000000000..26def613f
--- /dev/null
+++ b/doc/bugs/Endless_SSH_password_prompts.mdwn
@@ -0,0 +1,15 @@
+### Please describe the problem.
+Yesterday I installed git-annex on two computers and paired their repos. Today I logged back in to one of them, and as soon as the webapp loaded (autostarted in the background), it popped up an OpenSSH prompt wanting my key's password. I typed it in, and it popped up another. This went on several times. When I hit Cancel instead, it popped up a prompt wanting the password for the user account on my other computer. Even with that, once wasn't enough.
+
+This is bad enough, but worse is that the password prompt captures the keyboard input so I can't even open my Yakuake console to kill git-annex. Well, it's difficult and requires hitting Escape rapidly over and over until I can squeeze in a keystroke to the rest of the system.
+
+I don't understand why this is happening.
+
+1. Shouldn't git-annex have installed a passwordless key on my paired system? It did that for my remote repo.
+
+2. The prompt it's using has no option to remember the pasword. I use ssh-agent, but usually by running ssh-add in a terminal. Maybe if it would use a prompt that works with the agent it wouldn't ask for the password multiple times.
+
+3. I think it's opening multiple SSH connections at once, before I've entered the password even once, so even after I enter the password, it will keep asking for it until I've entered it for every SSH process that was already started.
+
+### What version of git-annex are you using? On what operating system?
+1 Nov 2013 Linux tarball on Ubuntu Raring 13.04
diff --git a/doc/bugs/Endless_SSH_password_prompts/comment_1_b3a32d7a53c30478f409a47f856282ab._comment b/doc/bugs/Endless_SSH_password_prompts/comment_1_b3a32d7a53c30478f409a47f856282ab._comment
new file mode 100644
index 000000000..b1ea71526
--- /dev/null
+++ b/doc/bugs/Endless_SSH_password_prompts/comment_1_b3a32d7a53c30478f409a47f856282ab._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-03T00:29:14Z"
+ content="""
+Pairing sets up the same kind of dedicated passwordless ssh key that is used when adding a ssh server.
+
+It's not clear from your description what program is asking for the password, or even if it's asking for the password for a ssh key. You need to provide more details.
+"""]]
diff --git a/doc/bugs/Endless_SSH_password_prompts/comment_2_0a1fc4b4580d8be4c37064e0a16de99b._comment b/doc/bugs/Endless_SSH_password_prompts/comment_2_0a1fc4b4580d8be4c37064e0a16de99b._comment
new file mode 100644
index 000000000..fec729ddb
--- /dev/null
+++ b/doc/bugs/Endless_SSH_password_prompts/comment_2_0a1fc4b4580d8be4c37064e0a16de99b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-11-03T00:39:38Z"
+ content="""
+I'm not sure which program is doing the asking either. The title bar says \"OpenSSH\". It is asking for the SSH key password, but if I dismiss the dialog without entering the password, it will open another dialog asking for the user account's password, e.g. me@laptop, indicating it's SSH falling back to password auth.
+"""]]
diff --git a/doc/bugs/Endless_SSH_password_prompts/comment_3_46210f7745b8c7c237fc8b08309390fe._comment b/doc/bugs/Endless_SSH_password_prompts/comment_3_46210f7745b8c7c237fc8b08309390fe._comment
new file mode 100644
index 000000000..aacf1cc01
--- /dev/null
+++ b/doc/bugs/Endless_SSH_password_prompts/comment_3_46210f7745b8c7c237fc8b08309390fe._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlHNJ7FpiXJNwSmojlwKwXhhF5QvwpNPmI"
+ nickname="Colin"
+ subject="Confirmed"
+ date="2013-11-14T17:57:23Z"
+ content="""
+I am seeing the same problem. It happened on a machine running git-annex on Debian Testing some weeks ago, and I eventually disabled the offending repository for my sanity (incidentally - it seems to have vanished so I don't know how to re-enable it apart from adding it again).
+
+It has just very recently (some days) started on this machine running Debian Unstable.
+
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__.mdwn b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__.mdwn
new file mode 100644
index 000000000..a44ecc82e
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__.mdwn
@@ -0,0 +1,28 @@
+### Please describe the problem.
+When I try to add a box.com cloud repository with the encryption option selected, I get an error that says "internal server error".
+
+### What steps will reproduce the problem?
+Anytime I try to set up a cloud repository with box.com (and presumably others, since this seems to be a problem with gpg (see log)) that is encrypted, I get this error.
+
+
+### What version of git-annex are you using? On what operating system?
+The operating system is Mac OS X 10.8.4, and the version of git-annex is 4.20130801-gc88bbc4.
+
+
+### 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
+
+(encryption setup) gpg: /Users/adamliter/.gnupg/gpg.conf:233: invalid auto-key-locate list
+30/Aug/2013:02:27:11 -0400 [Error#yesod-core] user error (gpg ["--quiet","--trust-model","always","--gen-random","--armor","1","512"] exited 2) @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+
+# End of transcript or log.
+"""]]
+
+[[!meta title="OSX bundled gpg does not work with gpg.conf created by MacGPG"]]
+
+> [[done]]; I have updated the gpg to version 1.4.14 which
+> manages to build with the missing features.
+> --[[Joey]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_1_9be1b577fa4d5fe9754845073fdf5d32._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_1_9be1b577fa4d5fe9754845073fdf5d32._comment
new file mode 100644
index 000000000..ec0234c2d
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_1_9be1b577fa4d5fe9754845073fdf5d32._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 1"
+ date="2013-08-30T11:39:51Z"
+ content="""
+gpg complains about an invalid parameter for the `auto-key-locate` option, which is not passed by git-annex but found in your gpg.conf.
+
+What is on line 233 of `/Users/adamliter/.gnupg/gpg.conf`?
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_2_0da0d68b646f2b38be6ecf7c0fe13743._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_2_0da0d68b646f2b38be6ecf7c0fe13743._comment
new file mode 100644
index 000000000..c8a1db228
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_2_0da0d68b646f2b38be6ecf7c0fe13743._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkgH7oNEqNbh3g-N1-UHXuqleXaRYDgj1U"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-08-30T15:39:16Z"
+ content="""
+\"auto-key-locate cert pka ldap hkp://keys.gnupg.net\" is on line 233
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_3_09c56f5574931f2ebe903069f0731160._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_3_09c56f5574931f2ebe903069f0731160._comment
new file mode 100644
index 000000000..3cfa9a829
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_3_09c56f5574931f2ebe903069f0731160._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 3"
+ date="2013-08-30T16:09:58Z"
+ content="""
+Hmm, it looks like a perfectly valid list. Interesting.
+But regardless, gpg doesn't seem to like that line; what gpg version
+are you using? Also, does it work directly on the command-line
+(`gpg -a --gen-random 1 1`)?
+
+Have you tried to setup the remote without that line in the gpg.conf? Of
+course it wouldn't solve the core of the issue, but it's irrelevant for
+random data generation anyway (the same goes for `--trust-model`);
+perhaps this very command should be run with `--no-options`.
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_4_0c127396e682ca6ced43aec7deeb0335._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_4_0c127396e682ca6ced43aec7deeb0335._comment
new file mode 100644
index 000000000..6d2bb451a
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_4_0c127396e682ca6ced43aec7deeb0335._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkgH7oNEqNbh3g-N1-UHXuqleXaRYDgj1U"
+ nickname="Adam"
+ subject="comment 4"
+ date="2013-08-30T21:39:26Z"
+ content="""
+`gpg -a --gen-random 1 1` on the command line seems to work. At least, when I just ran it it returned `Xg==`. I'm not super familiar with running gpg on the command line, so I'm not sure if that is the desired result when running that.
+
+The version of gpg is GnuPG/MacGPG2 version 2.0.20.
+
+I just tried deleting that line from the config file, and now it worked. Would I be able to replace the line after setting up the repository, or is that going to create problems? I'm not entirely sure what that line does, and I'm a little wary about messing with it in case it breaks the functionality of any of the other things that I use gpg for, like email encryption.
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_5_6bc3eadefde4750eec67a55de6651b2d._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_5_6bc3eadefde4750eec67a55de6651b2d._comment
new file mode 100644
index 000000000..998d67055
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_5_6bc3eadefde4750eec67a55de6651b2d._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 5"
+ date="2013-08-30T22:51:56Z"
+ content="""
+OK (you just generated 1 byte of base64-encoded random data).
+No, I'm afraid git-annex will croak for each operation using gpg on your remote (which includes get, push, fsck, ...).
+
+This lines specifies how gpg automatically retrieves public keys when you get a signed message for instance. If you don't want to mix configurations, it is easy to create a git-annex-specific GnuPG home directory, but it requires you to point the `GNUPGHOME` to this alternative directory before starting git-annex.
+
+That said, other MacOSX users have encountered the same problem, and it was [[reported_to_be_solved_recently|/bugs/internal_server_error_when_choosing_encrypted_rsync_repo_option/]].
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_6_263ab9c1483438b1717c8061ac81a2fa._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_6_263ab9c1483438b1717c8061ac81a2fa._comment
new file mode 100644
index 000000000..65e6275da
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_6_263ab9c1483438b1717c8061ac81a2fa._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.140"
+ subject="comment 6"
+ date="2013-09-05T16:30:52Z"
+ content="""
+I have verified the gpg build I am currently using on OSX fails with that line. MacGPG doesn't but I had problems including it in the build before.
+If you remove the \"cert\" and the \"pkg\" from the line it will work. It seems I need to update the gpg build to support these DNS based key finding methods.
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_7_eccc10990dff37584f8e60cd481a7140._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_7_eccc10990dff37584f8e60cd481a7140._comment
new file mode 100644
index 000000000..35d9c71e8
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_7_eccc10990dff37584f8e60cd481a7140._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.140"
+ subject="comment 7"
+ date="2013-09-05T16:54:36Z"
+ content="""
+./configure says:
+
+<pre>
+checking whether the resolver is usable... no
+checking whether I can make the resolver usable with BIND_8_COMPAT... no
+
+configure:7918: gcc -o conftest -g -O2 conftest.c >&5
+Undefined symbols for architecture x86_64:
+ \"_res_9_dn_expand\", referenced from:
+ _main in ccsJFrZc.o
+ \"_res_9_dn_skipname\", referenced from:
+ _main in ccsJFrZc.o
+ \"_res_9_query\", referenced from:
+ _main in ccsJFrZc.o
+ld: symbol(s) not found for architecture x86_64
+collect2: ld returned 1 exit status
+</pre>
+
+So no DNS stuff until I can find a way to build a gpg for OSX that supports it.
+"""]]
diff --git a/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_8_f897d20cbe5e0f3f58ce1a0bacad3d71._comment b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_8_f897d20cbe5e0f3f58ce1a0bacad3d71._comment
new file mode 100644
index 000000000..741c5342f
--- /dev/null
+++ b/doc/bugs/Error_creating_encrypted_cloud_repository:___34__internal_server_error__34__/comment_8_f897d20cbe5e0f3f58ce1a0bacad3d71._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkgH7oNEqNbh3g-N1-UHXuqleXaRYDgj1U"
+ nickname="Adam"
+ subject="comment 8"
+ date="2013-09-05T17:30:07Z"
+ content="""
+Hmm, thanks for looking into it. I appreciate it.
+"""]]
diff --git a/doc/bugs/Failed_to_make_repository___40__calling_nonexistant_shell__41__.mdwn b/doc/bugs/Failed_to_make_repository___40__calling_nonexistant_shell__41__.mdwn
index c25f6b3ba..634f3e501 100644
--- a/doc/bugs/Failed_to_make_repository___40__calling_nonexistant_shell__41__.mdwn
+++ b/doc/bugs/Failed_to_make_repository___40__calling_nonexistant_shell__41__.mdwn
@@ -24,3 +24,5 @@ Ubuntu 10.04 on both desktop and server.
### Please provide any additional information below.
The problem seems to be runshell trying to call /home/annex/sh, which does not exist. Why would it do that?
+
+> [[done]]
diff --git a/doc/bugs/Feature_request:___34__quvi__34___flag.mdwn b/doc/bugs/Feature_request:___34__quvi__34___flag.mdwn
new file mode 100644
index 000000000..950aad0fc
--- /dev/null
+++ b/doc/bugs/Feature_request:___34__quvi__34___flag.mdwn
@@ -0,0 +1,14 @@
+### Please describe the problem.
+git-annex v4.20130827 can't be built on ARM. Technically it's vector that can't be built due to a lack of Template Haskell compilers for this architecture. Vector is a dependency of aeson, which is a dependency of git-annex, which therefore fails to compile.
+
+The only functionality that relies on aeson is, to my knowledge, quvi. Thus my feature request: If you were to introduce a flag to switch quvi support on or off, ARM users like me could circumvent the aeson dependency at build time. In this case we weren't stuck with 4.20130815 (the latest version to not depend on aeson) and could use current and future versions of git-annex. I would appreciate it.
+
+
+### What steps will reproduce the problem?
+See above.
+
+
+### What version of git-annex are you using? On what operating system?
+I'm running Raspbian Wheezy on a Raspberry Pi. The git-annex version to be built is 4.20130827.
+
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Feature_request:___34__quvi__34___flag/comment_1_908c38024fd252328566034608c2dec3._comment b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_1_908c38024fd252328566034608c2dec3._comment
new file mode 100644
index 000000000..a5668f664
--- /dev/null
+++ b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_1_908c38024fd252328566034608c2dec3._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T05:25:39Z"
+ content="""
+Sorry, I didn't consider this dependency chain.
+
+FWIW, it is possible to build aeson without TH. See `standalone/android/haskell-patches/aeson_0.6.1.0_0001-disable-TH.patch` in the git-annex source tree.
+
+However, I will add a flag.
+"""]]
diff --git a/doc/bugs/Feature_request:___34__quvi__34___flag/comment_2_4b6822fe91aa865f2ac1297a3daa3fca._comment b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_2_4b6822fe91aa865f2ac1297a3daa3fca._comment
new file mode 100644
index 000000000..ab4494c19
--- /dev/null
+++ b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_2_4b6822fe91aa865f2ac1297a3daa3fca._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 2"
+ date="2013-09-09T05:44:48Z"
+ content="""
+Also, note that libghc-aeson-dev is available for arm in Debian.
+"""]]
diff --git a/doc/bugs/Feature_request:___34__quvi__34___flag/comment_3_c72ef77e76b1c99b5e0c78d0742080e7._comment b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_3_c72ef77e76b1c99b5e0c78d0742080e7._comment
new file mode 100644
index 000000000..bbbd5b597
--- /dev/null
+++ b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_3_c72ef77e76b1c99b5e0c78d0742080e7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="91.213.8.236"
+ subject="comment 3"
+ date="2013-09-09T05:52:48Z"
+ content="""
+Thanks for the quick answer, I will give these two options a try. A flag will be even better, though.
+"""]]
diff --git a/doc/bugs/Feature_request:___34__quvi__34___flag/comment_4_6092695d6afb1608447afe6f86e6fb83._comment b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_4_6092695d6afb1608447afe6f86e6fb83._comment
new file mode 100644
index 000000000..10a84afda
--- /dev/null
+++ b/doc/bugs/Feature_request:___34__quvi__34___flag/comment_4_6092695d6afb1608447afe6f86e6fb83._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="96.44.189.102"
+ subject="comment 4"
+ date="2013-09-09T19:31:44Z"
+ content="""
+That was fast!
+"""]]
diff --git a/doc/bugs/Finding_an_Unused_file.mdwn b/doc/bugs/Finding_an_Unused_file.mdwn
new file mode 100644
index 000000000..211755829
--- /dev/null
+++ b/doc/bugs/Finding_an_Unused_file.mdwn
@@ -0,0 +1,152 @@
+### Please describe the problem.
+
+SHA256E makes it difficult or impossible to find the original filename
+
+### What steps will reproduce the problem?
+
+I have these unused files:
+
+ $ git annex unused
+ unused . (checking for unused data...) (checking master...) (checking backupbook/HEAD...) (checking b
+ aster...) (checking lang/a-...) (checking lang/master...)
+ Some annexed data is no longer used by any files:
+ NUMBER KEY
+ 1 SHA256-s9107031--2611c08c9822179c443f001f0bd7ecadf29adcd28edfa4cd1d8938d289cd3950
+ 2 SHA256E-s31131336--58c48adad8e5f091981549dfbb2d9ec1003c8c46d1a660673fabefe722358f9b.flac
+ 3 SHA256-s9941549--db12950459ba039e6e6f6102a0811213c11a717d140d6e2f169049b958a5e047
+ 4 SHA256-s11544438--174514684e03035cc741fa397a1b46f925899bd29189a98173f8f2a136d95ace
+ 5 SHA256E-s23445007--4659fae3eda6db7c528af6439fafab1496c740d02bdb67892450a8a2208fb29b.flac
+ 6 SHA256E-s47080709--7d331788ae7fee16bccce060c62cafa3cdafc9e0a2b387c0843cfe5871f51fa6.flac
+ 7 SHA256E-s33262563--3280607d6d397f84a02542c5ab2e5a9c44d60256b330e3d075078694f0c7f709.flac
+ 8 SHA256-s6522640--a1fa374afd62e8c85a115f18f78e679722f63980191c1e11ef84a49ae86f5b4f
+ 9 SHA256E-s29266138--27e792d64b6d4a4d44bdafe6867ca25ba79480d1b650cf385e67ff28a1fc5c31.flac
+ 10 SHA256-s14568326--023eb9fcefc063ee3ea495f4d382a8feac795d0e1a81c585781f5d369db2e00c
+ 11 SHA256-s11907175--73b66220bdbf0ca92209605b93d95d5f9e8247745f9c4367ff20cb53e11c24ac
+ 12 SHA256-s9193267--e159038b78c1b239d4cb8eeb892c7acf0e7b82feac7f5b5808dad477605e8478
+ 13 SHA256E-s39329047--880ffab99c4b4c48224f409acb0cd797737e4ee70eacdba9bc7d7628ba3d05d7.flac
+ 14 SHA256E-s31400468--17ad7b13757d4e4d6e5d193d8295a30f566e00eea82bc19f50dc14b2bbf79ef3.flac
+ 15 SHA256E-s51514687--f83eb092ddcdf35e7f729bfa2cc0914b404de60f0b42f69f207cf01766061f16.flac
+ 16 SHA256E-s36235648--54e3f893b498b205b0b96bd87d5f14c71712e891c518070a0e1c730d92b3b0ac.flac
+ 17 SHA256-s10001177--35afb0b91c8b9f711b2d3b0fe7433ecc3bb13aece78c6170a47323c94233133d
+ 18 SHA256-s11830142--3dabe97ccbb68045d9ea82036ddf7211a3925a1bf682e05a32bcdf9b07bec676
+ 19 SHA256E-s23102994--f848ed216e6ba17e6b539f31caa5af36266c367ed55dcff243445848b01fbeef.flac
+ 20 SHA256E-s38505547--967763ddd42daf782afa9299e67cb5c834153cb20242b50115dda566b24a68c4.flac
+ 21 SHA256-s11874975--14774a404526c4b68ede146f527202c59a4bee88376707c93df7da3bdb5345f2
+ 22 SHA256-s10188700--18fd4ee62c2b3b1d8944eae528b59de2a45d493a291440edc9b30881ba10ece3
+ 23 SHA256E-s53024109--eba924a26f7c602b60a83f208b2204ef3b570fd92ff39fbc067eeaec7c443ab6.flac
+ 24 SHA256-s11315225--0a8d2165166995e819e8c78302c45b1eeca9b79a5d77a3574885cbf8e18f265a
+ 25 SHA256-s12249573--79b9e551051232079f24902078e1fe5b7daed684e8acaa7cf29c191404a7c3c7
+ 26 SHA256E-s47991289--79cfd8db5b3cbe7f50c335bfe0d148c38ff36dbc97b17ea3aff23d642bd5d167.flac
+ 27 SHA256E-s76961343--80e91f73e2f3ae6790d752d380118b3fadc223f9f1449354daa0095b5713986c.flac
+ 28 SHA256E-s44706648--ce782096aa5c0d58a12f7cbd6dbfe032fa7b0b4810219e23f906bd7fa0d96336.flac
+ 29 SHA256-s9393784--1e0e0190030352b3583ce515cd6dfb0db9f2ae39809a462099482947193bfd0f
+ 30 SHA256E-s11534608--bfcc0fdcb1ed112b1737d4fe7d2aa88511187d4c1c132bf1b7ab2cda9a7d90ad.flac
+ 31 SHA256E-s27916580--1f196e1b6312421f9d9bcd227a3885a5dec299fc47748cd34d5e59fe26374187.flac
+ 32 SHA256-s12099941--0a33af0293acb7cffa1727cc04efa4d7abb29a39e8f2165bfd565e2b18879430
+ 33 SHA256E-s35578262--01d6f6022161bcaa825cb353012f85bacf3dcb930337ba506fc94b663b0d8043.flac
+ 34 SHA256E-s38880984--fa326bd0db5c9e400a4256e77acd488fede23ec714aeab7deb6952091a09e318.flac
+ 35 SHA256E-s27784704--a426f885d79d88d8b42b8a23ce267fb1c1855e8f7ff6833ec9ea61860b3c6819.flac
+ 36 SHA256-s11827390--17c1e84815805ea7e01555fdfa038a643a97621b84073679d5c649c020750652
+ 37 SHA256E-s16632423--9735e37261624360f6a54fd1bc8a893cb5344afdc910e6b9e00c5791036759b0.flac
+ 38 SHA256-s10809006--7dd7ff078bdf4571bee6ab06213df970f427a8a2af476d4511a9c08ed0fb814d
+ 39 SHA256E-s33043364--3603942143fa4b1c0082ab7ba1db9b536621402eea3ac94e08ef0197062a2ef6.flac
+ 40 SHA256E-s33278052--62e1038e26894c6c014af4e77d2d9f79074ff4fc1ca9ca8c16fcc98eee5277c7.flac
+ 41 SHA256E-s47299134--0b604bff3ce12d077691d6e6428648da879c021537c094c72633209d5302fd97.flac
+ 42 SHA256E-s14882445--16c6aa4aaf8e60da617701281dfdfa372cb049636ae0f10f5aefcd8ce6c472af.flac
+ 43 SHA256E-s18168736--dfd7bfe9a433daef89f6f0015dfddaf7ac3611dd31813b0aed049171ac008323.flac
+ 44 SHA256-s10060170--9e3b638c4f397d8dbaa2fa9fc2bfacf6f9e93f00c80ee1fdd26971d25aff86ce
+ 45 SHA256E-s25630107--26fedc816dee58cb999cd2be8a58f3e8726ff056ba9c2abfbb9d149e7a92a230.flac
+ 46 SHA256-s9148609--3f29a2ae1ebd2e4857bb5c92aefb2f50f39a5a984e14645f658d15795a7c72a5
+ 47 SHA256-s10576861--7d95469441ef205616ed795012d8a4c59acc00be00aca66bcacd8b041c2499c5
+ 48 SHA256E-s23806802--8725d04f04925f4cd456bdb2108a48682cf51a498d97af9f71c58a412b8db9ab.flac
+ 49 SHA256E-s43187837--e83648296fa4553556596464efd4ab313529c0062071c9a40113fecede7a5de6.flac
+ 50 SHA256-s10384945--055a01b7e06f3165dddd10beb3e98ba4ca47b35abf9d5b2f26187bf07b9aa401
+ 51 SHA256E-s54253300--b011eea8ec7ea51f22e0fe09645ffe83183e9589a9784ebc2d6dd0c559f07322.flac
+ 52 SHA256-s10335583--008c17c1a994884c6b9c52e10d17373b9160136ffab940992ef0f9d08eac45c1
+ 53 SHA256-s9769970--b36fcb01d9df7627106e3a3c283944457f3e282ab62878c186162d465530cfbc
+ 54 SHA256-s10329964--dc4d82e085af3ade48d33cf828f8e7eecc27d4c33c448965e1b8bb59832ec473
+ 55 SHA256-s10625243--2494e2ef2c64fc77dcb063f7b58079ad668cf46862b7f11eb28943d45f21b8dd
+ 56 SHA256E-s44585111--e35b0774729ccf547cd62e652425579781e3cbd76b33a17a0127bdbedb90606a.flac
+ 57 SHA256E-s42060728--9e0a533e640086fadefad7167d37d5b3c5de899e1ac5890bfd7a88524701ff14.flac
+ 58 SHA256E-s30013479--ae34a897e2f0e1124f04396e75dd41749511ce9930a2891ae3a066597ad518c5.flac
+ 59 SHA256E-s38896704--ca6211442c33d9c44b997bef8f1079f07cdd2eb0e9e3c1de1eda9ae8a705f137.flac
+ 60 SHA256-s13044938--8714a1db8781daa9f3993128dcda5a5ca904e075723cf38a11bc5e3695cf126f
+ 61 SHA256-s8814622--ba374e92c53ddb83605e2b500647117a00e4c6c463653cb0dd0311b76627c2ec
+ 62 SHA256E-s14900839--e94089b89629561ebf771543236f31439af1e6fcdce7ff56b9a183041e95e7ea.flac
+ 63 SHA256E-s27370218--a4717cf0615cda099ea5740194da8b4e349f2f38f6ebbf5f6111ced7f56d1736.flac
+ 64 SHA256E-s57686070--6d02689ccf91317bdfa4d8694ccbf7a9ccf00a7e00b92733769194908b4087d9.flac
+ 65 SHA256-s8707306--7f05e3e3dc4336eb7012d5bbb6d3d65047552901858ee4967e4a70d100fd1deb
+ 66 SHA256E-s42482194--bb7a968ec9bc0a8813974af9173c38cb39a43aa7d0c2aec203ddb358119e1f25.flac
+ 67 SHA256E-s31951334--b19789a9bbb98cb25df7b8a1b6d8856256bc2851cd892c91dddba7cf736542c5.flac
+ 68 SHA256E-s35901187--8eae2684aa3566b632a1797bd09d112dd5f438c98b649c000d71640983a549f2.flac
+ 69 SHA256E-s40659631--f6ca3227b14c7c050877ce4cc1218fea7582426649cd68fc82a74cae5d6962b4.flac
+ 70 SHA256E-s41415180--9c6f0000da119bd70422fe9529c41efb3103ca943697bdfb685f119f6b5ae6fd.flac
+ 71 SHA256E-s52313976--e4a59c65e05bd9450ef595b3c08365810205731952e45a68ee0c89bc76fbd9fc.flac
+ 72 SHA256E-s44925214--eabc5f7172d5c2e094ff84a5ecce784c172b175c8eeca861aa3996749668ea42.flac
+ (To see where data was previously used, try: git log --stat -S'KEY')
+
+ To remove unwanted data: git-annex dropunused NUMBER
+
+ ok
+
+And running:
+
+ $ git log --stat -S'SHA256-s13044938--8714a1db8781daa9f3993128dcda5a5ca904e075723cf38a11bc5e3695cf126f'
+ commit 767a63a54784139f13d69d12fcfbee8f6ca3df41
+ Author: Matthew Forrester <matt@keyboardwritescode.com>
+ Date: Fri Aug 23 21:38:31 2013 +0100
+
+ Remove Roger Shah - Openminded! as there is another copy in Unsorted with correct? filenames
+
+ Amazon/Roger Shah/Openminded!/1114 - Shine (Album Mix).mp3 | 1 -
+ 1 file changed, 1 deletion(-)
+
+ commit 6b04002c03287fb8918bdcdeaae393e862bebd4e
+ Author: Matthew Forrester <matt@keyboardwritescode.com>
+ Date: Thu Aug 8 21:30:14 2013 +0100
+
+ Initial checkin
+
+ Amazon/Roger Shah/Openminded!/1114 - Shine (Album Mix).mp3 | 1 +
+ 1 file changed, 1 insertion(+)
+
+Works but I cannot find out how to get the `.flac` files working:
+
+
+`$ git log --stat -S'SHA256E-s38896704--ca6211442c33d9c44b997bef8f1079f07cdd2eb0e9e3c1de1eda9ae8a705f137.flac'`
+
+`$ git log --stat -S'SHA256E-s38896704--ca6211442c33d9c44b997bef8f1079f07cdd2eb0e9e3c1de1eda9ae8a705f137'`
+
+`$ git log --stat -S'SHA256-s38896704--ca6211442c33d9c44b997bef8f1079f07cdd2eb0e9e3c1de1eda9ae8a705f137'`
+
+
+None of which give answers. I don't know if I'm doing it wrong (though I __think__ I'm doing what the instructions say), but I can't make it work.
+
+
+### What version of git-annex are you using? On what operating system?
+
+$ uname -a
+Linux fozz-desktop 3.8.0-31-generic #46-Ubuntu SMP Tue Sep 10 19:56:49 UTC 2013 i686 i686 i686 GNU/Linux
+
+$ git annex version
+git-annex version: 3.20121112ubuntu2
+local repository version: 3
+default repository version: 3
+supported repository versions: 3
+upgrade supported from repository versions: 0 1 2
+
+### 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.
+"""]]
+
+> If `git log -S` does not find the key, then it was not used for any
+> commit currently in the git repository. Which is certianly possible;
+> for example `git annex add file; git rm file`.
+>
+> This is a dup of [[todo/wishlist: option to print more info with 'unused']]; [[done]] --[[Joey]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__.mdwn b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__.mdwn
new file mode 100644
index 000000000..d66196acd
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__.mdwn
@@ -0,0 +1,44 @@
+### Please describe the problem.
+Using the webapp to generate a new (local) repository instantly takes it to the following state:
+[[!format sh """
+user@local:~/Annex$ git status
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# deleted: uuid.log
+#
+user@local:~/Annex$ git branch
+ git-annex
+* master
+user@local:~/Annex$ git log
+commit 90bfcaf17b0576d8ecdc48ae44dda22d41464acc
+Author: local <user>
+Date: Sun Nov 3 15:30:17 2013 +0100
+
+ created repository
+user@local:~/Annex$ git show HEAD
+commit 90bfcaf17b0576d8ecdc48ae44dda22d41464acc
+Author: local <user>
+Date: Sun Nov 3 15:30:17 2013 +0100
+
+ created repository
+
+diff --git a/uuid.log b/uuid.log
+new file mode 100644
+index 0000000..9df3670
+--- /dev/null
++++ b/uuid.log
+@@ -0,0 +1 @@
++987e7b9a-aa9d-41db-ae92-23fcae7f6187 user@local:~/Annex timestamp=1383489017.181
+user@local:~/Annex$
+"""]]
+
+I'm new to git-annex, so I'm not quite sure, but looking at [[internals]] this file should only exist in the git-annex branch, not in master. Furthermore, from this state it seems impossible to get "sync with your other devices" to work, because of a merge conflict on this change.
+
+Perhaps some sort of a race-condition with the annex-assistant picking up the uuid.log file while the repository is being initialized?
+
+### What version of git-annex are you using? On what operating system?
+Ubuntu 13.10 with git-annex 4.20130815
+
+> [[fixed|done]]; see comments. (This fix needs to be backported to Ubuntu.) --[[Joey]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_1_6441dd04adc158df22589c81746108a9._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_1_6441dd04adc158df22589c81746108a9._comment
new file mode 100644
index 000000000..6080e88e4
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_1_6441dd04adc158df22589c81746108a9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-03T16:48:25Z"
+ content="""
+I can't reproduce this at all. What version of git do you have installed? Did you install git-annex from ubuntu's repository? Does the same thing happen if you install the standalone linux tarball and use it to make a new repository?
+
+git-annex never creates a file named uuid.log on disk, so it's quite strange that it shows up in the initial commit to the master branch. It sort of looks like somehow git-annex's normal use of a separate index file to stage the uuid.log to the git-annex branch is failing. Since I have never seen any problem with that, I have to suspect that the ubuntu build is somehow badly broken. Or that the git in Ubuntu is for some reason ignoring `GIT_INDEX_FILE`.
+"""]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_2_d1c5d7642284a375f9c455dbf76efa5c._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_2_d1c5d7642284a375f9c455dbf76efa5c._comment
new file mode 100644
index 000000000..50bff5f41
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_2_d1c5d7642284a375f9c455dbf76efa5c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 2"
+ date="2013-11-03T17:02:47Z"
+ content="""
+I made an Ubuntu saucy chroot, apt-get installed git-annex from universe, and ran the webapp in there. I did not reproduce this problem.
+
+The cause of the problem, it seems, must be something local to your system. Perhaps you have an environment variable set that is messing up git. Or perhaps you have a different, broken version of git installed.
+
+Can you \"git show git-annex\" in the repository? It should show a commit made to the git-annex branch that adds the uuid.log there.
+"""]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_3_4b863da1c8ba73ad54da20f7d2ec6e5c._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_3_4b863da1c8ba73ad54da20f7d2ec6e5c._comment
new file mode 100644
index 000000000..7acab1c37
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_3_4b863da1c8ba73ad54da20f7d2ec6e5c._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="tanen"
+ ip="83.128.159.25"
+ subject="comment 3"
+ date="2013-11-03T17:35:00Z"
+ content="""
+Very strange: this is on a machine that I wiped and reinstalled just a few hours ago, it's a completely fresh Ubuntu 13.10 install with barely anything installed but the defaults. Git version is 1.8.3.2-1
+
+I initially just pulled git-annex from the Ubuntu repo. After that I grabbed a more recent version from https://launchpad.net/ubuntu/+source/git-annex/4.20131101/+build/5189754 which is showing the same behavior.
+
+\"git show git-annex\" indeed shows the commit creating the uuid.log file on the git-annex branch. master has just one commit, with description \"created repository\" and creates a \"uuid.log\" file. The contents of the master uuid.log are identical to the one in the git-annex branch.
+
+I'm currently in the middle of trying out a git-annex setup so I can't switch versions again right now, but given the above I imagine a fresh 13.10 VM should show the same behavior.
+"""]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_4_8e0f489305ce30ad578b9f8526e86416._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_4_8e0f489305ce30ad578b9f8526e86416._comment
new file mode 100644
index 000000000..c020fc3a8
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_4_8e0f489305ce30ad578b9f8526e86416._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 4"
+ date="2013-11-06T15:09:19Z"
+ content="""
+Intriguing -- I was able to reproduce this bug after installing the Ubuntu server ISO in a VM.
+
+Which is really strange, the only difference between this and my debootstrapped chroot should be the kernel..
+"""]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_5_c699034c8e02b2354516414d0ab73aab._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_5_c699034c8e02b2354516414d0ab73aab._comment
new file mode 100644
index 000000000..e8a5f8cdd
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_5_c699034c8e02b2354516414d0ab73aab._comment
@@ -0,0 +1,53 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 5"
+ date="2013-11-06T16:27:49Z"
+ content="""
+Running the prebuilt tarball build of git-annex, the bug does not occur.
+
+However, if I remove the git shipped with the prebuilt tarball, so it uses the system git, I do see the bug. So, it's apparently git version dependent.
+
+Also, I was able to reproduce it in a amd64 chroot. My other chroot was i386. Somehow architecture specific bug?
+
+---
+
+Instrumenting all calls to git to be logged with the full environment and command, I found this:
+
+<pre>
+GIT_INDEX_FILE='/home/foo/annex/.git/annex/index'
+--git-dir=/home/foo/annex/.git --work-tree=/home/foo/annex commit --quiet --allow-empty -m created repository
+</pre>
+
+This certianly looks like the index file setting for the git-annex branch is somehow leaking out past the branch commit operations. It continued setting that while setting up `gc.auto`; the next call to git after that stopped setting the index file.
+
+The only way I can see offhand this could possibly happen is due to an exception. It may be that on ubuntu an exception is thrown by code that runs a git command with the index file set, for whatever reason, and this causes the code that normally resets it back to not run.
+
+----
+
+Ok, found it!
+
+<pre>
+\"withIndex entered\"
+
+*** Please tell me who you are.
+
+Run
+
+ git config --global user.email \"you@example.com\"
+ git config --global user.name \"Your Name\"
+
+to set your account's default identity.
+Omit --global to set the identity only in this repository.
+
+fatal: unable to auto-detect email address (got 'foo@darkstar.(none)')
+\"withIndex entered\"
+\"withIndex cleaned up\"
+</pre>
+
+Note lack of clean up after the first withIndex call. Thus leaving the environment passed to git polluted for further calls.
+
+This also explains why it's only happening on some systems, or with some versions of git. git's got all kinds of complexity around its username and email handling code.
+
+I have fixed this in git.
+"""]]
diff --git a/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_6_786cb7e643811dfd2496ceeff8f34f44._comment b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_6_786cb7e643811dfd2496ceeff8f34f44._comment
new file mode 100644
index 000000000..ea3e97e8e
--- /dev/null
+++ b/doc/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/comment_6_786cb7e643811dfd2496ceeff8f34f44._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 6"
+ date="2013-11-06T16:40:57Z"
+ content="""
+Ubuntu bug report about this: <https://bugs.launchpad.net/ubuntu/+source/git-annex/+bug/1248623>
+
+It should be pretty easy to backport the fix to the version in Ubuntu. The relevant git commits are ee23be55fd3e7e202bc721c124f78b79d1aba6df and 81117e8a9d19d4739d3773d0515006e1ea41c266
+"""]]
diff --git a/doc/bugs/GPG_can__39__t_handle_some_files.mdwn b/doc/bugs/GPG_can__39__t_handle_some_files.mdwn
new file mode 100644
index 000000000..6c29a95b8
--- /dev/null
+++ b/doc/bugs/GPG_can__39__t_handle_some_files.mdwn
@@ -0,0 +1,23 @@
+### Please describe the problem.
+
+It looks like GPG is being used in text mode, or at least isn't overriding the GPG config.
+
+### What steps will reproduce the problem?
+
+Have a binary file with long lines, and attempt to copy it into git-annex.
+
+This will happen:
+
+ $ git-annex copy 09\ Into\ The\ Dissonance.mp3 -t rsync.net_annex
+ copy 09 Into The Dissonance.mp3 (gpg) (checking rsync.net_annex...) (to rsync.net_annex...) gpg: can't handle text lines longer than 19995 characters
+ failed
+ git-annex: copy: 1 failed
+
+A workaround is to remove "textmode" from your gpg.conf, but git-annex should force this.
+
+### What version of git-annex are you using? On what operating system?
+
+7ae625363bcb6e1fc8b3733c1d7814aca05a2368 on Ubuntu 13.04 x86_64
+
+> The sheer number of ways gpg offers of shooting yourself in the foot..
+> Ok [[done]] --[[Joey]]
diff --git a/doc/bugs/GPG_can__39__t_handle_some_files/comment_1_4388c971e991dbc0326e69c49994df1e._comment b/doc/bugs/GPG_can__39__t_handle_some_files/comment_1_4388c971e991dbc0326e69c49994df1e._comment
new file mode 100644
index 000000000..60c363fd9
--- /dev/null
+++ b/doc/bugs/GPG_can__39__t_handle_some_files/comment_1_4388c971e991dbc0326e69c49994df1e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~eythian"
+ nickname="eythian"
+ subject="comment 1"
+ date="2013-09-06T23:37:10Z"
+ content="""
+I also had a huge bunch of files come across corrupted, but the one that came after I made this change wasn't. This might be a sign that GPG is corrupting things on the way past.
+"""]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android.mdwn b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android.mdwn
new file mode 100644
index 000000000..bf68208da
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android.mdwn
@@ -0,0 +1,280 @@
+### Please describe the problem.
+git add hangs.
+Maybe because of encrypted sdcard?
+
+
+
+
+
+### What steps will reproduce the problem?
+
+ app_30@android:/sdcard $ mkdir annex;cd annex
+ app_30@android:/sdcard/annex $ git init
+ Initialized empty Git repository in /mnt/sdcard/annex/.git/
+ app_30@android:/sdcard/annex $ git annex init
+ init
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ ok
+ (Recording state in git...)
+ app_30@android:/sdcard/annex $ touch lala
+ git annex add lala --debug <
+ [2013-10-13 22:05:17 CEST] read: git ["--git-dir=/mnt/sdcard/annex/.git","--work-tree=/mnt/sdcard/annex","ls-files","--others","--exclude-standard","-z","--","lala"]
+ [2013-10-13 22:05:17 CEST] read: git ["--git-dir=/mnt/sdcard/annex/.git","--work-tree=/mnt/sdcard/annex","ls-files","--modified","-z","--","lala"]
+ [2013-10-13 22:05:17 CEST] chat: git ["--git-dir=/mnt/sdcard/annex/.git","--work-tree=/mnt/sdcard/annex","cat-file","--batch"]
+ add lala [2013-10-13 22:05:17 CEST] chat: git ["--git-dir=/mnt/sdcard/annex/.git","--work-tree=/mnt/sdcard/annex","check-attr","-z","--stdin","annex.backend","annex.numcopies","--"]
+ ** HANGS **
+
+
+
+The same will happen when just running and asking assistant to create annex for camera.
+
+ps aux | grep -i git:
+
+ app_30 9870 8950 2512 464 c009cd2c 400456a4 S git
+ app_30 9871 9870 64900 7552 ffffffff 40108a38 S git-annex
+ app_30 9876 9871 0 0 ffffffff 00000000 Z git
+ app_30 9877 9871 0 0 ffffffff 00000000 Z git
+ app_30 9878 9871 2512 608 c0114a4c 400b2878 S git
+ app_30 9879 9871 2512 556 c0114a4c 40074878 S git
+
+lsof | grep git:
+
+ 1|app_30@android:/sdcard $ lsof | grep git
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/__properties__ (deleted)
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-res.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/framework/com.htc.resources.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-htc-res.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework.jar
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/etc/system_fonts.xml
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/etc/fallback_fonts.xml
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/Roboto-Regular.ttf
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/framework/core.jar
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/urandom
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/tasks
+ 9870 /data/data/ga.androidterm/lib/lib.git.so socket:[1172354]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/bg_non_interactive/tasks
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/app/Aluminum.apk
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172380]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172381]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /data/data/ga.androidterm/fifo
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172382]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/DroidSansMono.ttf
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177783]
+ 9870 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177784]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/pts/2
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/pts/2
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/pts/2
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/main
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/radio
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/events
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/system
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so anon_inode:[eventpoll]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184035]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/__properties__ (deleted)
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184035]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so anon_inode:[eventfd]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184036]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184036]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so anon_inode:[eventfd]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184039]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184043]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184044]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184046]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1184047]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/framework/framework-res.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/framework/com.htc.resources.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/framework/framework-htc-res.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/framework/framework.jar
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/etc/system_fonts.xml
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/etc/fallback_fonts.xml
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/fonts/Roboto-Regular.ttf
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/framework/core.jar
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/urandom
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/main
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/radio
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/events
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/log/system
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/cpuctl/tasks
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so socket:[1172354]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172355]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172355]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/cpuctl/bg_non_interactive/tasks
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172358]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172358]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so anon_inode:[eventpoll]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/ashmem
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/ashmem
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /data/app/ga.androidterm-1.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /data/app/ga.androidterm-1.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/app/Aluminum.apk
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172380]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172381]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /data/data/ga.androidterm/fifo
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172382]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/pts/2
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /system/fonts/DroidSansMono.ttf
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172407]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1172407]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so anon_inode:[eventpoll]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so /dev/ashmem
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1177783]
+ 9871 /data/data/ga.androidterm/lib/lib.git-annex.so pipe:[1177784]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1184043]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1184044]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/__properties__ (deleted)
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-res.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/framework/com.htc.resources.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-htc-res.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework.jar
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/etc/system_fonts.xml
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/etc/fallback_fonts.xml
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/Roboto-Regular.ttf
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/framework/core.jar
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/urandom
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/tasks
+ 9878 /data/data/ga.androidterm/lib/lib.git.so socket:[1172354]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/bg_non_interactive/tasks
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/app/Aluminum.apk
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172380]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172381]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /data/data/ga.androidterm/fifo
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172382]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/DroidSansMono.ttf
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177783]
+ 9878 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177784]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1184046]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1184047]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/__properties__ (deleted)
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-res.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/framework/com.htc.resources.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework-htc-res.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/framework/framework.jar
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/etc/system_fonts.xml
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/etc/fallback_fonts.xml
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/Roboto-Regular.ttf
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/framework/core.jar
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/urandom
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/main
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/radio
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/events
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/log/system
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/tasks
+ 9879 /data/data/ga.androidterm/lib/lib.git.so socket:[1172354]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172355]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/cpuctl/bg_non_interactive/tasks
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172358]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /data/app/ga.androidterm-1.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/app/Aluminum.apk
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172380]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172381]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /data/data/ga.androidterm/fifo
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172382]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/pts/2
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /system/fonts/DroidSansMono.ttf
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1172407]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so anon_inode:[eventpoll]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so /dev/ashmem
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177783]
+ 9879 /data/data/ga.androidterm/lib/lib.git.so pipe:[1177784]
+
+
+vfat/sdcard entry:
+ /dev/block/dm-2 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702, \
+ allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
+ tmpfs /mnt/sdcard/.android_secure tmpfs ro,relatime,size=0k,mode=000 0 0
+
+
+
+### What version of git-annex are you using? On what operating system?
+Version from git annex version:
+2a8136b6bd60a17d687eb800594ec7c37b872b3d
+
+I tried both daily build and most recent 'stable' with the same effect.
+
+Android 4.0.3 (Htc One V)
+
+The same happens on my another android device; Samsung tablet with... also 4.0.3.
+Tried to gather strace information on git, but couldn't. If anything more is necessary,
+please let me know.
+
+The same happens when I git annex add in /data/data/ga.androidterm/anntmp - so it's not sdcard nor vfat.
+
+### 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.
+"""]]
+
+> I have updated git-annex to work with the new git, which will be 1.8.5.
+> This fix should appear in the android autobuild within an hour if you
+> want to try it. [[done]] --[[Joey]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_1_2fc435d1c741f9fc422401f682e7c8b7._comment b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_1_2fc435d1c741f9fc422401f682e7c8b7._comment
new file mode 100644
index 000000000..19b8ae1a6
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_1_2fc435d1c741f9fc422401f682e7c8b7._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="I can reproduce this! (with 4.20130923-g78e9013)"
+ date="2013-10-15T19:57:19Z"
+ content="""
+Comparing straces from Android and Linux, it seems to be due to git check-attr outputting something different:
+
+<pre>
+read(16, \"andro\0annex.backend\0unspecified\0\"..., 8096) = 66
+read(10, \"linux: annex.backend: unspecifie\"..., 8096) = 70
+</pre>
+
+So, this is not actually Android specific, thankfully. It's just a breakage caused by a change in a newish version of git! I think it's not yet released, just Android is building from git head right now.
+
+I have reverted the Android stable build to the last version I think won't be affected by this.
+"""]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_2_b73fb99a75aef912f8286626c5bde66d._comment b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_2_b73fb99a75aef912f8286626c5bde66d._comment
new file mode 100644
index 000000000..12b0f9f6e
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_2_b73fb99a75aef912f8286626c5bde66d._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="bla"
+ ip="91.121.95.205"
+ subject="Testing"
+ date="2013-10-15T21:24:35Z"
+ content="""
+Last autobuild (installed by replacing existing)
+annex 89345b7 with git 1.8.4.474.g128a96c - also hangs on add in the same manner (in previously created tmp git in /data/data/ga.androidterm/anntmp). Not sure if I did something wrong.
+
+Current stable release - works just fine (deinstalled, installed again - replace failed somehow)
+
+
+
+"""]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_3_b7115f2c658439ff59a029f500697fc1._comment b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_3_b7115f2c658439ff59a029f500697fc1._comment
new file mode 100644
index 000000000..eb3c993a8
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_3_b7115f2c658439ff59a029f500697fc1._comment
@@ -0,0 +1,57 @@
+[[!comment format=mdwn
+ username="bla"
+ ip="91.121.95.205"
+ subject="More info on latest autobuild"
+ date="2013-10-15T21:42:52Z"
+ content="""
+Using adb shell, su app_30, runshell:
+
+ app_30@android:/data/data/ga.androidterm/anntmp $ head -n 3 /sdcard/git-annex.>
+ Installation starting to /data/data/ga.androidterm
+ 89345b7108f5c18eba0845f84780a26d069d011d
+ installing busybox
+
+ app_30@android:/data/data/ga.androidterm/anntmp $ git version
+ git version 1.8.4.474.g128a96c
+ app_30@android:/data/data/ga.androidterm/anntmp $ git annex version
+ git-annex version: 4.20131015-g89345b7
+ build flags: Assistant Webapp Testsuite S3 WebDAV Inotify 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 glacier hook
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+ git init; git annex init; touch lala
+ 130|app_30@android:/data/data/ga.androidterm/anntmp $ git annex add lala --deb>
+ [2013-10-15 23:37:20 CEST] read: git [\"--git-dir=/data/data/ga.androidterm/anntmp/.git\",\"--work-tree=/data/data/ga.androidterm/anntmp\",\"ls-files\",\"--others\",\"--exclude-standard\",\"-z\",\"--\",\"lala\"]
+ [2013-10-15 23:37:20 CEST] read: git [\"--git-dir=/data/data/ga.androidterm/anntmp/.git\",\"--work-tree=/data/data/ga.androidterm/anntmp\",\"diff\",\"--name-only\",\"--diff-filter=T\",\"-z\",\"--\",\"lala\"]
+ add lala [2013-10-15 23:37:20 CEST] chat: git [\"--git-dir=/data/data/ga.androidterm/anntmp/.git\",\"--work-tree=/data/data/ga.androidterm/anntmp\",\"check-attr\",\"-z\",\"--stdin\",\"annex.backend\",\"annex.numcopies\",\"--\"]
+ *hangs*
+
+
+
+ echo lala | git check-attr -z --stdin annex.backend annex.numcopies | hexdump -C
+ 00000000 6c 61 6c 61 0a 00 61 6e 6e 65 78 2e 62 61 63 6b |lala..annex.back|
+ 00000010 65 6e 64 00 75 6e 73 70 65 63 69 66 69 65 64 00 |end.unspecified.|
+ 00000020 6c 61 6c 61 0a 00 61 6e 6e 65 78 2e 6e 75 6d 63 |lala..annex.numc|
+ 00000030 6f 70 69 65 73 00 75 6e 73 70 65 63 69 66 69 65 |opies.unspecifie|
+ 00000040 64 00 |d.|
+ 00000042
+
+While on my laptop (git 1.8.4.rc3)
+
+ feather annex % echo lala | git check-attr -z --stdin annex.backend annex.numcopies | hexdump -C
+ 00000000 22 6c 61 6c 61 5c 6e 22 3a 20 61 6e 6e 65 78 2e |\"lala\n\": annex.|
+ 00000010 62 61 63 6b 65 6e 64 3a 20 75 6e 73 70 65 63 69 |backend: unspeci|
+ 00000020 66 69 65 64 0a 22 6c 61 6c 61 5c 6e 22 3a 20 61 |fied.\"lala\n\": a|
+ 00000030 6e 6e 65 78 2e 6e 75 6d 63 6f 70 69 65 73 3a 20 |nnex.numcopies: |
+ 00000040 75 6e 73 70 65 63 69 66 69 65 64 0a |unspecified.|
+ 0000004c
+
+So in fact very different indeed.
+
+
+Hope it helps - assuming i didn't do some weird mistake. I'll happily use stable version for now. GREAT THANKS!
+"""]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_4_67de7a56ddb06fc0e31cc011d281c633._comment b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_4_67de7a56ddb06fc0e31cc011d281c633._comment
new file mode 100644
index 000000000..4456e2cef
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_4_67de7a56ddb06fc0e31cc011d281c633._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 4"
+ date="2013-10-16T16:16:02Z"
+ content="""
+Thanks for testing that. I had a fencepost error, which I've fixed, and actually tested with problimatic git version now.
+"""]]
diff --git a/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_5_58fdb2a00f1737746cdbc804f831a0e7._comment b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_5_58fdb2a00f1737746cdbc804f831a0e7._comment
new file mode 100644
index 000000000..7bbef0fdd
--- /dev/null
+++ b/doc/bugs/Git_annex_hangs_after_git_annex_add_on_vfat__47__sdcard__47__android/comment_5_58fdb2a00f1737746cdbc804f831a0e7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://adamspiers.myopenid.com/"
+ nickname="Adam"
+ subject="any chance of a new release?"
+ date="2013-10-22T13:33:57Z"
+ content="""
+I just upgraded via cabal install to 4.20131002, which (unsurprisingly, I guess) still exhibits this issue. Would be great if a new release could be cut for this ...
+"""]]
diff --git a/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path.mdwn b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path.mdwn
new file mode 100644
index 000000000..3f58bd889
--- /dev/null
+++ b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path.mdwn
@@ -0,0 +1,63 @@
+Hi,
+I already have told about that in a comment here <http://git-annex.branchable.com/bugs/submodule_path_problem/#comment-e86330d15b714a41a07b6548fbc79bb2>, but I am not sure it will be seen.
+
+Then here is an official bug report.
+### Please describe the problem.
+
+I have a problem with submodules when the git repository is not a submodule everywhere.
+
+For instance, if A is a git annexed repository and B another git repository. If B adds A as submodules. The symlinks added in A as submodule won't work in the original A.
+
+### What steps will reproduce the problem?
+
+ # creating the master repository
+ mkdir annex_master
+ cd annex_master/
+ git init
+ # hack: adding a file to create the master branch
+ touch start
+ git add start
+ git commit -m "start"
+ cd ..
+ # create another repository
+ mkdir annex_sub
+ cd annex_sub/
+ git init
+ # hack: adding a file to create the master branch
+ touch start
+ git add start
+ git commit -m "start"
+ # it is a annexed repository
+ git annex init sub
+ # add the other repository as submodule of the master one
+ cd ../annex_master/
+ git submodule add ../annex_sub/ module
+ cd module/
+ git annex init sub_module
+ git annex sync origin
+ # add an annexed file
+ echo test > test
+ git annex add
+ git annex sync
+ # go back to the origin repository
+ cd ../../annex_sub/
+ git annex sync
+ ls -l
+This returns test -> ../.git/modules/module/annex/objects/w8/pv/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
+
+Actually, the file committed is correct. But the fact it points to '../.git/modules/module/...' makes the link work only if the repository is also a submodule and if this submodule is also located in the modules folder in the parent git repository.
+
+I tried playing with making the repository direct and then indirect, hoping that would fix the symlinks, but it did not work.
+### What version of git-annex are you using? On what operating system?
+
+ $ git-annex version
+ git-annex version: 4.20130802
+ ...
+
+ $ git --version
+ git version 1.8.3.2
+
+ $ uname -a
+ Linux konixwork 3.9-1-amd64 #1 SMP Debian 3.9.8-1 x86_64 GNU/Linux
+
+### Please provide any additional information below.
diff --git a/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_1_b3197993dbdfaf2db5e4651ac54a896e._comment b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_1_b3197993dbdfaf2db5e4651ac54a896e._comment
new file mode 100644
index 000000000..8ff232159
--- /dev/null
+++ b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_1_b3197993dbdfaf2db5e4651ac54a896e._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T18:49:18Z"
+ content="""
+git-annex assumes that it can make a stable symlink from a file in the working tree to a file in the .git directory. There are several ways to break this. One, as noted, is sometimes using a repository as a submodule, and sometimes not. Another would be to play around with `GIT_DIR`.
+
+I don't see a way git-annex can support those use cases, at least in indirect mode.
+
+It does seem like, in direct mode, it should just work. git-annex will commit various symlinks to git, but these symlinks will never be followed to get at the content of a file, since direct mode arranges for the content to be directly present in the working tree.
+"""]]
diff --git a/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_2_1fbbd02e61ef524597dafd69460b00b4._comment b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_2_1fbbd02e61ef524597dafd69460b00b4._comment
new file mode 100644
index 000000000..b7aa61f17
--- /dev/null
+++ b/doc/bugs/Git_annexed_files_symlink_are_wrong_when_submodule_is_not_in_the_same_path/comment_2_1fbbd02e61ef524597dafd69460b00b4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="konubinix"
+ ip="82.243.233.186"
+ subject="Thanks"
+ date="2013-08-26T06:25:19Z"
+ content="""
+Thanks for the reply.
+
+Also thanks for this great tool (Though I am not sure I truelly realize the true power of git annex yet).
+"""]]
diff --git a/doc/bugs/Hangs_on_creating_repository_when_using_--listen/comment_2_dc128eeddeaaf3f84e71aca0fb7d341f._comment b/doc/bugs/Hangs_on_creating_repository_when_using_--listen/comment_2_dc128eeddeaaf3f84e71aca0fb7d341f._comment
new file mode 100644
index 000000000..55d7efa1c
--- /dev/null
+++ b/doc/bugs/Hangs_on_creating_repository_when_using_--listen/comment_2_dc128eeddeaaf3f84e71aca0fb7d341f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-24T18:52:11Z"
+ content="""
+This also affects creating a second repository in the webapp, not just the repository creation at first startup.
+"""]]
diff --git a/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__.mdwn b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__.mdwn
new file mode 100644
index 000000000..69b0c4116
--- /dev/null
+++ b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__.mdwn
@@ -0,0 +1,295 @@
+### Please describe the problem.
+
+I use both the assistant and the command line. Unfortunately I often end up
+in a state where I cannot do a "git annex sync" (it fails as described below)
+and I have to use the assistant to synchronize things to make the sync work. I
+would like to know how to do the same thing using only the command line.
+
+### What steps will reproduce the problem?
+
+This problem involves two repos: a local, indirect mode, manual group, repo, and
+a ssh remote archive group bare repo (with full git annex available
+remotely). The local repo is "top" and the remote one is "mini_archive".
+
+I start with the assistant not running, and the two repos in sync. Note that the
+remote server cannot directly contact the local repo.
+
+local:
+
+ schmitta@top ~/D/annex (master)> git annex sync
+ commit
+ ok
+ pull mini_archive
+ ok
+
+remote:
+
+ schmitta@mini ~/a/archive> git annex sync
+ commit
+ ok
+
+I then add a file locally and try to sync, getting a problem on mini_archive:
+
+ schmitta@top ~/D/annex (master)> git annex add videos/Minecraft/Icy\ and\ FlowerChild\ Play\ -\ Better\ Than\ Wolves\ 3-qg6LVTcDl4Y.mp4
+ add videos/Minecraft/Icy and FlowerChild Play - Better Than Wolves 3-qg6LVTcDl4Y.mp4 (checksum...) ok
+ (Recording state in git...)
+ schmitta@top ~/D/annex (master)> git annex sync
+ commit
+ ok
+ pull mini_archive
+ ok
+ push mini_archive
+ Counting objects: 15, done.
+ Delta compression using up to 4 threads.
+ Compressing objects: 100% (10/10), done.
+ Writing objects: 100% (10/10), 1.01 KiB | 0 bytes/s, done.
+ Total 10 (delta 4), reused 0 (delta 0)
+ remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+ To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ a5b002b..dde2626 master -> synced/master
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+ error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+ failed
+ git-annex: sync: 1 failed
+
+I try to merge and sync on the remote (I assume sync also does merge, but I'm
+not sure).
+
+ schmitta@mini ~/a/archive> git annex merge
+ merge git-annex ok
+ schmitta@mini ~/a/archive> git annex sync
+ commit
+ ok
+
+Back on the local machine, I still have the conflict.
+
+ schmitta@top ~/D/annex (master) [1]> git annex sync
+ commit
+ ok
+ pull mini_archive
+ ok
+ push mini_archive
+ Counting objects: 7, done.
+ Delta compression using up to 4 threads.
+ Compressing objects: 100% (5/5), done.
+ Writing objects: 100% (5/5), 513 bytes | 0 bytes/s, done.
+ Total 5 (delta 1), reused 0 (delta 0)
+ remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+ To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+ error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+ failed
+ git-annex: sync: 1 failed
+
+From this state, the only way to resolve things is to launch the web app. It
+tells me "synced with mini_archive" (and it starts uploading the new file). Then
+on the server there is something to merge. (I haven't waited for the file to
+finish uploading in this case.)
+
+ schmitta@mini ~/a/archive> git annex merge
+ merge git-annex (merging refs/synced/1cdfb490-0660-41fb-b7ce-74b89abb9aac/git-annex into git-annex...)
+ ok
+ schmitta@mini ~/a/archive> git annex sync
+ commit
+ ok
+
+and I can then sync on the local repo:
+
+ schmitta@top ~/D/annex (master) [1]> git annex sync
+ commit
+ ok
+ pull mini_archive
+ From ssh://git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive
+ 8f39d4c..cb7f6c3 git-annex -> mini_archive/git-annex
+ ok
+
+Note that I need to do the remote merge for things to work. After the file has
+finished uploading, I get back in a conflict:
+
+ schmitta@top ~/D/annex (master)> git annex sync
+ commit
+ ok
+ pull mini_archive
+ ok
+ push mini_archive
+ Total 0 (delta 0), reused 0 (delta 0)
+ remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+ To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+ error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+ failed
+ git-annex: sync: 1 failed
+
+If I disable and re-enable the sync on the server (forcing a sync), I still have
+a conflict locally:
+
+ schmitta@top ~/D/annex (master) [1]> git annex sync
+ commit
+ ok
+ pull mini_archive
+ ok
+ push mini_archive
+ Total 0 (delta 0), reused 0 (delta 0)
+ remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+ To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+ error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+ failed
+ git-annex: sync: 1 failed
+
+It only get solved by doing a merge on the server:
+
+ schmitta@mini ~/a/archive> git annex merge
+ merge git-annex (merging refs/synced/1cdfb490-0660-41fb-b7ce-74b89abb9aac/git-annex into git-annex...)
+ (Recording state in git...)
+ ok
+
+ schmitta@top ~/D/annex (master) [1]> git annex sync
+ commit
+ ok
+ pull mini_archive
+ remote: Counting objects: 13, done.
+ remote: Compressing objects: 100% (5/5), done.
+ remote: Total 5 (delta 3), reused 0 (delta 0)
+ Unpacking objects: 100% (5/5), done.
+ From ssh://git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive
+ cb7f6c3..d177e1a git-annex -> mini_archive/git-annex
+ ok
+ (merging mini_archive/git-annex into git-annex...)
+
+
+### What version of git-annex are you using? On what operating system?
+
+Current version available on cabal:
+
+ schmitta@top ~/D/annex (master)> git annex version
+ git-annex version: 4.20131002
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi
+ 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 glacier hook
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+ schmitta@mini ~/a/archive> git annex version
+ git-annex version: 4.20131002
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi
+ 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 glacier hook
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+
+### Please provide any additional information below.
+
+Here is daemon.log. It mentions another repo which is an external
+hard drive not plugged it at the moment. I'm skipping the file transmission
+(...).
+
+[[!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
+
+[2013-10-23 14:02:05 CEST] main: starting assistant version 4.20131002
+[2013-10-23 14:02:05 CEST] TransferScanner: Syncing with hole, mini_archive
+Already up-to-date.
+fatal: '/Volumes/hole/annex/' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+
+(scanning...) [2013-10-23 14:02:06 CEST] Watcher: Performing startup scan
+Already up-to-date.
+Already up-to-date.
+fatal: '/Volumes/hole/annex/' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+fatal: '/Volumes/hole/annex/' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+fatal: '/Volumes/hole/annex/' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+fatal: '/Volumes/hole/annex/' does not appear to be a git repository
+fatal: Could not read from remote repository.
+
+Please make sure you have the correct access rights
+and the repository exists.
+[2013-10-23 14:02:10 CEST] Committer: Committing changes to git
+[2013-10-23 14:02:10 CEST] Pusher: Syncing with mini_archive
+
+
+(Recording state in git...)
+(started...) To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ 8f39d4c..cb7f6c3 git-annex -> refs/synced/1cdfb490-0660-41fb-b7ce-74b89abb9aac/git-annex
+ a5b002b..dde2626 master -> refs/synced/1cdfb490-0660-41fb-b7ce-74b89abb9aac/master
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+Everything up-to-date
+(gpg)
+
+
+SHA256E-s608232213--d4d6e02e651b1d265ff1c041ee8e8c23db9d880140816d62b8cc82cee4db3a54.mp4
+
+...
+
+sent 608306626 bytes received 42 bytes 5133389.60 bytes/sec
+total size is 608232213 speedup is 1.00
+[2013-10-23 14:04:13 CEST] Transferrer: Uploaded Icy and F..cDl4Y.mp4
+[2013-10-23 14:04:13 CEST] Pusher: Syncing with mini_archive
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ cb7f6c3..927cc1c git-annex -> refs/synced/1cdfb490-0660-41fb-b7ce-74b89abb9aac/git-annex
+[2013-10-23 14:05:35 CEST] main: Syncing with mini_archive
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+remote: error: denying non-fast-forward refs/heads/synced/git-annex (you should pull first)
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+error: failed to push some refs to 'ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/'
+Everything up-to-date
+
+
+# End of transcript or log.
+"""]]
+
+> So, receive.denyNonFastforwards was the problem. It turns out that
+> `git init --bare --shared` sets that by default, and the webapp
+> uses that to create repositories on ssh server. I have made the webapp
+> unset receive.denyNonFastforwards when setting up such a repository.
+>
+> Also added something to the assistant release notes about this
+> to handle existing repositories. [[done]] --[[Joey]]
diff --git a/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_1_0ddcbe0ccecdec1012964dfa436a3eee._comment b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_1_0ddcbe0ccecdec1012964dfa436a3eee._comment
new file mode 100644
index 000000000..ef2399d81
--- /dev/null
+++ b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_1_0ddcbe0ccecdec1012964dfa436a3eee._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-23T15:21:34Z"
+ content="""
+<pre>
+To ssh://schmitta@git-annex-**.**.**.**-schmitta_annex.2Farchive/~/annex/archive/
+ ! [remote rejected] git-annex -> synced/git-annex (non-fast-forward)
+</pre>
+
+Since version 4.20130909, git-annex is supposed to have avoided this problem by forcing the push of the git-annex branch. If you run `git annex sync --debug`, you should see:
+
+[2013-10-23 11:12:54 EDT] call: git [\"--git-dir=annex/.git\",\"--work-tree=annex\",\"push\",\"foo\",\"+git-annex:synced/git-annex\",\"master:synced/master\"]
+
+The \"+\" flag before the branch name forces git push to update the remote branch even if it's not a fast-forward.
+
+You should be able to verify if git-annex is doing that, and run the same git push command manually to investigate why it might not be working. I have not seen this problem since putting in that fix, and I saw it before. Perhaps your server has an old or broken version of git that ignores this flag, or some git configuration setting I am not aware of that prevents it from working.
+"""]]
diff --git a/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_2_5765b849bcf045ead9f007bd50b2cfbd._comment b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_2_5765b849bcf045ead9f007bd50b2cfbd._comment
new file mode 100644
index 000000000..44ccfe00b
--- /dev/null
+++ b/doc/bugs/How_can_I_solve_a_non-fast-forward_push_without_using_the_assistant__63__/comment_2_5765b849bcf045ead9f007bd50b2cfbd._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="comment 2"
+ date="2013-10-23T16:21:30Z"
+ content="""
+I think I found the problem, after much googling.
+
+The command line you suggest is indeed tried, and rejected by the server.
+
+The answer came from [here](http://stackoverflow.com/questions/253055/how-do-i-push-amended-commit-to-the-remote-git-repo) where it says (speaking of a forced push)
+
+> Even this may not work as git allows remote repositories to refuse non-fastforward pushes at the far end by using the config variable 'receive.denynonfastforwards'.
+
+Indeed this is set in my annex repository. Note that this is a local setting, and that repository was created by the assistant.
+
+I removed this setting, and I can now push. Could the setting of this bit be a bug in the assistant?
+
+In any case, thanks a lot for indicating where to look at.
+"""]]
diff --git a/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status.mdwn b/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status.mdwn
index fcb9fead9..07d6f3eb3 100644
--- a/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status.mdwn
+++ b/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status.mdwn
@@ -1,5 +1,7 @@
### Please describe the problem.
+[[!tag moreinfo]]
+
I added a lot of files to my annex in direct mode. Now I want to switch to indirect mode. git-annex status and indirect create an out-of-memory error.
### What steps will reproduce the problem?
@@ -59,3 +61,9 @@ commit git-annex: out of memory (requested 985661440 bytes)
# End of transcript or log.
"""]]
+
+> [[fixed|done]]. However, if you saw this behavior,
+> you have large files checked directly into git. You may
+> want to examine your repository and use git filter-branch to clean
+> it up.
+> --[[Joey]]
diff --git a/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status/comment_3_a07105226ef3488b97731db004651976._comment b/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status/comment_3_a07105226ef3488b97731db004651976._comment
new file mode 100644
index 000000000..e4795e5a8
--- /dev/null
+++ b/doc/bugs/Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status/comment_3_a07105226ef3488b97731db004651976._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 3"
+ date="2013-09-19T18:59:42Z"
+ content="""
+It turns out that if you are using direct mode and you manually `git commit some-file` that is really big, that file is checked directly into git. Which is why direct mode's docs say not to do that.
+
+Once you've got an enormous file in git, either on purpose on by mistake, it turns out that git-annex tries to buffer the whole file content in some situations. I am in the process of fixing those memory leaks.
+"""]]
diff --git a/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp.mdwn b/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp.mdwn
new file mode 100644
index 000000000..4a8006f06
--- /dev/null
+++ b/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp.mdwn
@@ -0,0 +1,21 @@
+### Please describe the problem.
+As described earlier in [[tips/fully_encrypted_git_repositories_with_gcrypt]]
+
+### What steps will reproduce the problem?
+- A: use the webapp to create a new repository
+- A: add a remote server to the repository using the 'gcrypt' method
+- A: add a jabber account
+
+- B: use the webapp to create a new repository
+- B: add the jabber account
+- B: see the previously created 'cloud repository' with status 'not enabled'
+- B: click enable, see that the stored credentials are correct, and press "verify this server"
+- B: enter the ssh password twice
+- B: get redirected to a blank screen (on the url /config/repository/enable/gcrypt/UUID "x"?auth=y)
+
+The assistent logfiles show nothing after the "Your public key has been saved in", the server shows that no public key for B was added to the account.
+
+This is with git-annex installed on the remote server; without it the process gets stuck after clicking "encrypt repository" in step 2, it will just indefinitely keep prompting for the SSH password.
+
+### What version of git-annex are you using? On what operating system?
+Latest nightly build on ubuntu 13.10
diff --git a/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp/comment_1_17814787e333d15da3ab4e57c7d31d4b._comment b/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp/comment_1_17814787e333d15da3ab4e57c7d31d4b._comment
new file mode 100644
index 000000000..5bd45d686
--- /dev/null
+++ b/doc/bugs/Impossible_to_enable_an_existing_gcrypt_repo_in_the_webapp/comment_1_17814787e333d15da3ab4e57c7d31d4b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-13T16:51:40Z"
+ content="""
+I've tried to reproduce this, and cannot; it enabled the repository without trouble.
+
+Also, I have never seen the webapp fail with a blank screen, so that's strange.
+
+I think you need to show your `~/annex/.git/annex/daemon.log` from B.
+"""]]
diff --git a/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn
new file mode 100644
index 000000000..46a07ee6a
--- /dev/null
+++ b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__.mdwn
@@ -0,0 +1,42 @@
+### Please describe the problem.
+Incorrect merge of direct repos.
+
+### What steps will reproduce the problem?
+
+[[!format sh """
+# setting up stuff
+test/a$ git init
+test/a$ git annex init
+test/a$ git annex direct
+test/a$ touch firstfile
+test/a$ git annex add firstfile
+$ git clone test/a
+$ mv a test/b
+test/b$ git annex direct
+
+# actual scenario
+test/b$ echo bbbb > f
+test/b$ git annex add f
+test/b$ git annex sync
+test/a$ mkdir f
+test/a$ echo aaaa > f/f
+test/a$ git annex add f/f
+test/a$ git annex sync
+test/b$ git annex sync
+test/b$ rm f
+test/b$ git annex sync
+test/b$ ls
+test/b$ firstfile
+test/b$ f.variant-SHA256E-s5--4551db5fd4d56e27be71a8a943070cfaa4342b8e960a326e2d6427b3aa0a5a48.variant-43f5
+test/a$ git annex sync # A's f/f is no longer to be found
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+[[!format sh """
+git-annex version: 4.20131031-g7d99d14
+build flags: Assistant Webapp 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 glacier hook
+
+Linux ceilingcat 3.11.6-1-ARCH #1 SMP PREEMPT Fri Oct 18 23:22:36 CEST 2013 x86_64 GNU/Linux
+"""]]
diff --git a/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__/comment_1_15c354c4841d364e78882d2b46a0a764._comment b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__/comment_1_15c354c4841d364e78882d2b46a0a764._comment
new file mode 100644
index 000000000..53c9f7915
--- /dev/null
+++ b/doc/bugs/Incorrect_merge__44___direct_repos___40__2__41__/comment_1_15c354c4841d364e78882d2b46a0a764._comment
@@ -0,0 +1,66 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-14T17:06:50Z"
+ content="""
+I verify this bug. And it's specific to direct mode as you say. Here is a shell script which automates the proccess:
+
+[[!format sh \"\"\"
+#!/bin/sh
+set -e
+mkdir test
+cd test
+git init a
+
+cd a
+git annex init
+git annex direct
+touch firstfile
+git annex add firstfile
+git annex sync # think this was left out of recipe
+
+cd ..
+
+git clone a b
+cd b
+git annex direct
+echo bbbb > f
+git annex add f
+git annex sync || true
+cd ..
+cd a
+mkdir f
+echo aaaa > f/f
+git annex add f/f
+git annex sync || true
+cd ..
+cd b
+git annex sync
+echo \"after merge:\"
+ls
+\"\"\"]]
+
+At this point, b only has the file version of f; the directory form has been removed. (Syncing to a of course then does the same thing there.)
+
+And from the trascript, we can see what's going on:
+
+<pre>
+Adding f/f
+CONFLICT (directory/file): There is a directory with name f in HEAD. Adding f as f~refs_heads_synced_master
+Automatic merge failed; fix conflicts and then commit the result.
+(Recording state in git...)
+f: needs merge
+[master 0600854] git-annex automatic merge conflict fix
+
+ Merge conflict was automatically resolved; you may want to examine the result.
+</pre>
+
+The problem seems to be that direct mode merge does not find the `f~refs_heads_synced_master` created by the merge, so fails to copy it from the temp merge tree into the work tree.
+
+`Command.Sync.cleanConflictCruft` is relevant, but was only made to work in indirect mode, it seems.
+
+----
+
+Obviously, if someone runs into this bug and seems to lose data, they can get the data back by reverting the changes from the automatic merge. Direct mode does preserve file contents when removing them from the work tree in a merge.
+"""]]
diff --git a/doc/bugs/Incorrect_merge___40__a_special_case__41__.mdwn b/doc/bugs/Incorrect_merge___40__a_special_case__41__.mdwn
new file mode 100644
index 000000000..5b817e214
--- /dev/null
+++ b/doc/bugs/Incorrect_merge___40__a_special_case__41__.mdwn
@@ -0,0 +1,45 @@
+### Please describe the problem.
+(Minor issue.)
+
+Incorrect merge of direct repos in the special case where at repo A a symlink to a file whose contents aren't yet available, are overwritten, while at repo B the file is deleted.
+
+Result: file is deleted on both side.
+
+Expected: B.f is gone, A.f is still present
+
+### What steps will reproduce the problem?
+
+[[!format sh """
+# setting up stuff
+test/a$ git init
+test/a$ git annex init
+test/a$ git annex direct
+test/a$ touch firstfile
+test/a$ git annex add firstfile
+$ git clone test/a
+$ mv a test/b
+test/b$ git annex direct
+
+# actual scenario
+test/b$ echo bbbb > f
+test/b$ git annex add f
+test/b$ git annex sync
+test/a$ git annex sync
+test/a$ echo aaaa > f
+test/a$ git annex add f
+test/a$ git annex sync
+test/b$ rm f
+test/b$ git annex sync
+test/a$ git annex sync
+# test/a/f is now gone, lost
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+[[!format sh """
+git-annex version: 4.20131031-g7d99d14
+build flags: Assistant Webapp 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 glacier hook
+
+Linux ceilingcat 3.11.6-1-ARCH #1 SMP PREEMPT Fri Oct 18 23:22:36 CEST 2013 x86_64 GNU/Linux
+"""]]
diff --git a/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_1_c80418d76b501c688e3a9fb4831520fd._comment b/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_1_c80418d76b501c688e3a9fb4831520fd._comment
new file mode 100644
index 000000000..0594ddabe
--- /dev/null
+++ b/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_1_c80418d76b501c688e3a9fb4831520fd._comment
@@ -0,0 +1,41 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-14T17:10:55Z"
+ content="""
+I suspect this might be the same underlying problem as [[bugs/Incorrect merge, direct repos (2)]]. However, I cannot reproduce it using the recipe given.. perhaps something was left out?
+
+I wrote this shell script to try to codify the recipe in a runnable form:
+
+[[!format sh \"\"\"
+#!/bin/sh
+set -e
+mkdir test
+cd test
+git init a
+
+cd a
+git annex init
+git annex direct
+touch firstfile
+git annex add firstfile
+git annex sync # think this was left out of recipe
+
+cd ..
+
+git clone a b
+cd b
+git annex direct
+echo bbbb > f
+git annex add f
+git annex sync || true
+cd ..
+cd a
+echo aaaa > f
+git annex add f
+git annex sync
+\"\"\"]]
+
+At this point, a has 2 variants of f, and no amount of syncing in either repo will cause either variant to go away.
+"""]]
diff --git a/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_2_8b2a188696f46819f6e3f0e9660362d2._comment b/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_2_8b2a188696f46819f6e3f0e9660362d2._comment
new file mode 100644
index 000000000..39bb90877
--- /dev/null
+++ b/doc/bugs/Incorrect_merge___40__a_special_case__41__/comment_2_8b2a188696f46819f6e3f0e9660362d2._comment
@@ -0,0 +1,45 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlWskoNgUB7r70OXglR-4iKI4bOuPJb-xg"
+ nickname="Tim"
+ subject="comment 2"
+ date="2013-11-14T18:06:55Z"
+ content="""
+You were missing a: test/a$ git annex sync
+
+This did the trick on my system
+[[!format sh \"\"\"
+#!/bin/sh
+set -e
+mkdir test
+cd test
+git init a
+
+cd a
+git annex init
+git annex direct
+touch firstfile
+git annex add firstfile
+git annex sync # think this was left out of recipe # indeed it was
+
+cd ..
+
+git clone a b
+cd b
+git annex direct
+echo bbbb > f
+git annex add f
+git annex sync || true # why add a || true?
+cd ../a
+git annex sync
+echo aaaa > f
+git annex add f
+git annex sync
+cd ../b
+rm f
+git annex sync
+ls
+cd ../a
+git annex sync
+ls
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/Internal_Server_Error:_Unknown_UUID/comment_9_ced3516c3e7161e4d7e599232f62a511._comment b/doc/bugs/Internal_Server_Error:_Unknown_UUID/comment_9_ced3516c3e7161e4d7e599232f62a511._comment
new file mode 100644
index 000000000..4a99ee3ad
--- /dev/null
+++ b/doc/bugs/Internal_Server_Error:_Unknown_UUID/comment_9_ced3516c3e7161e4d7e599232f62a511._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="Tilde did it for me"
+ date="2013-10-06T21:59:43Z"
+ content="""
+I had exactly the same error message, \"Internal Server Error: Unknown UUID\", when I used a path starting with a tilde. Absolute path for home directory worked.
+"""]]
diff --git a/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss.mdwn b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss.mdwn
index 630db722b..2629a7d56 100644
--- a/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss.mdwn
+++ b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss.mdwn
@@ -48,3 +48,10 @@ For this reason, it seems likely this is due to some sort of race condition.
This is on Ubuntu 12.04 with git-annex revision a1e2bc4.
+> There was no good soluton to this, so I picked a bad one that
+> will not have users complainging git-annex ate their data.
+> They will complain that `git annex unannex` is slow since it now copies
+> the file, and perhaps instead use --fast, and hopefully avoid destroying
+> their own data by editing the resulting hard links.
+>
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_10_52364dc5b1b43b51748453d1896e35c6._comment b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_10_52364dc5b1b43b51748453d1896e35c6._comment
new file mode 100644
index 000000000..c0b286a2b
--- /dev/null
+++ b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_10_52364dc5b1b43b51748453d1896e35c6._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmVV_nBwlsyCv53BXoJt8YpCX_wZPfzpyo"
+ nickname="Peter"
+ subject="Progress"
+ date="2013-10-10T01:17:08Z"
+ content="""
+Is there any type of script / tool / patch which does the --fast but with a copy instead of only a hard link? Can someone point me towards how I'm supposed to do this? I'm a technical user, however I don't really fancy having try to go learn the source code of git-annex to fix this really bad flaw :-/
+"""]]
diff --git a/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_11_99b4db1841f8630a9c5efd08910e87a3._comment b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_11_99b4db1841f8630a9c5efd08910e87a3._comment
new file mode 100644
index 000000000..4e55bd020
--- /dev/null
+++ b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_11_99b4db1841f8630a9c5efd08910e87a3._comment
@@ -0,0 +1,104 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmVV_nBwlsyCv53BXoJt8YpCX_wZPfzpyo"
+ nickname="Peter"
+ subject="Productive Annoyance"
+ date="2013-10-10T04:30:47Z"
+ content="""
+Ok, so I'm annoyed by this enough (and desperate enough to want to get my data back) that I wrote up a few scripts to help with this. I make no claims regarding how well these will work, but they seem to work with some minimal testing on a Fedora 17 machine.
+
+READ THROUGH THESE SCRIPTS BEFORE RUNNING THEM TO MAKE SURE YOU ARE OK WITH WHAT THEY ARE DOING!!!
+
+First, a script to create a bad git-annex: one with missing files (with a few corner case names) after a git unannex. Specify the directory you'd like to make the annex at the top of the file. ALL CONTENTS OF THIS DIRECTORY WILL BE REMOVED!!!
+
+ #!/bin/bash
+
+ #This is the folder you'd like to create and unannex
+ FOLDERTOUNANNEX='/tmp/badAnnex'
+
+ pushd .
+
+ if [ ! -d \"$FOLDERTOUNANNEX\" ] ; then
+ mkdir \"$FOLDERTOUNANNEX\"
+ fi
+
+ cd \"$FOLDERTOUNANNEX\"
+
+ rm -rf *
+
+ mkdir subdir
+ echo \"hi\" > 1one.txt
+ echo \"hi\" > 2two.txt
+ echo \"hi\" > \"3thr re ee.boo\"
+ echo \"hi\" > \"4f o u r.boo\"
+ echo \"hi\" > 5
+ echo \"hi\" > \"6\"
+ echo \"hi\" > \"subdir/7\"
+ echo \"hi\" > \"subdir/8.cat\"
+ echo \"hi\" > \"subdir/9.cat\"
+
+ echo \"* annex.backend=SHA512E\" > .gitattributes
+
+ chmod g-r 5 6
+ chmod o-r 6
+
+ ls -la
+
+ git init
+ git annex init \"stupid\"
+ git annex add *
+ ls -la
+ git annex unannex *
+ ls -la
+
+ popd
+
+
+Then, a script to recover the files left missing by the above script. Note this might be very slow as it has to generate SHA512 hashes for all the files in your annex. Again, change the paths at the top of this file to work in your environment:
+
+ #!/bin/bash
+
+ #Set this to some place outside your annex, where we can store our hashes while we search for them
+ #It will be fastest if this is on a different physical disk than the annexed folder
+ #You can manually delete the file afterwards
+ HASHFILE='/backup3/tmp.sha'
+ #This is the folder you'd like to unannex
+ FOLDERTOUNANNEX='/tmp/badAnnex'
+
+
+
+
+ HASHLEN=128
+
+ pushd .
+ cd \"$FOLDERTOUNANNEX\"
+
+ find \"$FOLDERTOUNANNEX\" ! -path '*.git*' -exec sha512sum \{\} \; > \"$HASHFILE\"
+
+ find -L \"$FOLDERTOUNANNEX\" -type l | while read BROKENFILE; do
+ POINTSTO=`file \"$BROKENFILE\" | sed -r 's/^.*broken symbolic link to .(.*).$/\1/g'`
+
+ HASH=`echo \"$POINTSTO\" | sed -r \"s/^.*--([^-\/.]{$HASHLEN}).*$/\1/g\"`
+
+ EXT=`echo \"$POINTSTO\" | sed -r \"s/^.*--[^-\/.]{$HASHLEN}(.[^.]+)?$/\1/g\"`
+
+ echo \"-\"
+ echo \"FILE:$BROKENFILE\"
+ echo \"POINTSTO:$POINTSTO\"
+ echo \"HASH:$HASH\"
+ echo \"EXT:$EXT\"
+
+ SOURCEFILE=`grep $HASH $HASHFILE | grep -m 1 \"$EXT\" | sed -r \"s/^.{$HASHLEN} (.*)$/\1/g\"`
+
+ echo \"SOURCEFILE:$SOURCEFILE\"
+ if [ -f \"$SOURCEFILE\" ];
+ then
+ cp --backup --suffix=\"~GIT_ANNEX_IS_DANGEROUS~\" -a \"$SOURCEFILE\" \"$BROKENFILE\"
+ else
+ echo \"ERROR: Cant find sourcefile\"
+ fi
+ done;
+
+ popd
+
+I have not yet run this repair script on my rather large broken annex. I cannot seem to figure out how to restore file ownership and permissions which seem to have been lost when the second file is just linked to the matching previously annexed file (note: this is visible after \"fixing\" the bad annex created by the first script above in that after \"fixing\" file \"6\" is readable by other, whereas originally he was NOT readable by other. The permissions of 6 have been copied from 5.) Any thoughts or improvements on this are appreciated.
+"""]]
diff --git a/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_9_e53148a9efa061a825f668a9492182f7._comment b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_9_e53148a9efa061a825f668a9492182f7._comment
new file mode 100644
index 000000000..74aaa1e56
--- /dev/null
+++ b/doc/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/comment_9_e53148a9efa061a825f668a9492182f7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 9"
+ date="2013-08-30T05:59:28Z"
+ content="""
+I'll chime in and say that the non-fast behavior being the default seems wrong, and making hard-link invisibly seems wrong. What Joey proposed -- copying a file if there are multiple hard-links -- seems like the right solution.
+
+Just recently I tried to unannex a large repository and was bitten by now-dangling symlinks to files that I couldn't locate anymore. The fact is that the current unannex operation is too dangerous to be useful.
+"""]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop.mdwn b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop.mdwn
new file mode 100644
index 000000000..63f423e2c
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop.mdwn
@@ -0,0 +1,39 @@
+### Please describe the problem.
+Pairing over my local network doesn't work. The pairing process never finishes. The log shows that the same PairMsg messages are repeated endlessly.
+
+### What steps will reproduce the problem?
+
+
+### What version of git-annex are you using? On what operating system?
+I'm on Ubuntu Raring 13.04. I installed git-annex 4.20131024 from the Precise PPA. It is working fine with a remote ssh repo, just not local pairing.
+
+### 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
+[2013-11-01 16:55:21 CDT] main: Pairing in progress
+[2013-11-01 16:55:55 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"Onyx\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBT0Y6TTzTg8nWwonmgUPPwJmPIaJzfEoJl8DbuylpgXqGCQ4doJXuvBODHIehPfyMr1xCWqNlNNLkcWg/a/eHFceyt3IlcD9XaZ1aKPzPmpjYKKf5amiYd6mAssw8zFaZUvwaXkNuHZpXVZyg6C6TkT6kdfln+6fOJZpSGQzksy0jka/Rzx0KXjsp3oqO4tQJbC7AX0nvmD0zvLtyCURzfGV+n2IqQxpPf2nP75Evt8jamcuqm6pWoe+hj9zjGytIXpSKe35wzRwUAUrjgmZ9NweuWfi2uMPJlDv8/n+Q3HyjygA+GzixBGuYXDt1CD8ISZvuoygS+9+jeY9uYH8b me@Onyx\\n\", pairUUID = UUID \"834b4f39-ca66-4baf-9323-57ef7058d7d0\"},IPv4Addr 2281744576), verifiableDigest = \"8d5d380542f7377f09a4584a38b0dbcea9ea215c\"})"
+[2013-11-01 16:55:56 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"kubbie\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvBEWT+AiAmehOFyTQWlSdwDs7DDbkw7rfZ4W/IeG5awZjMgT5BefIv9cmar8vGIIEFMZLpf8cL3xIargDz0xE2wuqj5CLkdz+DKp5f2FGs11Ax/62DZr+eCiVtPnwijFw0Cz0wMRzkN93uedrvzP/KkNRcczgWh3aZqn8WxlkCia1fyykm/pP3W80MNkiJYX5vXpu1NCV5KLu+UXQzKhM2njOauJ3W5wsMvSl8faZIpEmKVCD3BMDDruxTIxggA3kt9GCGvIbPawy+fGOpp/j6pHqnX3GB2kkT47RIZKYEv99HuLyvea+oY5R11FsC2yYY3ujIdUU0fXnV8pvrqSv me@kubbie\\n\", pairUUID = UUID \"fd6a6858-76c9-4eea-b733-9359c7313e72\"},IPv4Addr 1879091392), verifiableDigest = \"cbd8197c3d78c8c68bb30f63aa974cd88dd0fb13\"})"
+[2013-11-01 16:55:57 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"Onyx\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBT0Y6TTzTg8nWwonmgUPPwJmPIaJzfEoJl8DbuylpgXqGCQ4doJXuvBODHIehPfyMr1xCWqNlNNLkcWg/a/eHFceyt3IlcD9XaZ1aKPzPmpjYKKf5amiYd6mAssw8zFaZUvwaXkNuHZpXVZyg6C6TkT6kdfln+6fOJZpSGQzksy0jka/Rzx0KXjsp3oqO4tQJbC7AX0nvmD0zvLtyCURzfGV+n2IqQxpPf2nP75Evt8jamcuqm6pWoe+hj9zjGytIXpSKe35wzRwUAUrjgmZ9NweuWfi2uMPJlDv8/n+Q3HyjygA+GzixBGuYXDt1CD8ISZvuoygS+9+jeY9uYH8b me@Onyx\\n\", pairUUID = UUID \"834b4f39-ca66-4baf-9323-57ef7058d7d0\"},IPv4Addr 2281744576), verifiableDigest = \"8d5d380542f7377f09a4584a38b0dbcea9ea215c\"})"
+[2013-11-01 16:55:58 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"kubbie\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvBEWT+AiAmehOFyTQWlSdwDs7DDbkw7rfZ4W/IeG5awZjMgT5BefIv9cmar8vGIIEFMZLpf8cL3xIargDz0xE2wuqj5CLkdz+DKp5f2FGs11Ax/62DZr+eCiVtPnwijFw0Cz0wMRzkN93uedrvzP/KkNRcczgWh3aZqn8WxlkCia1fyykm/pP3W80MNkiJYX5vXpu1NCV5KLu+UXQzKhM2njOauJ3W5wsMvSl8faZIpEmKVCD3BMDDruxTIxggA3kt9GCGvIbPawy+fGOpp/j6pHqnX3GB2kkT47RIZKYEv99HuLyvea+oY5R11FsC2yYY3ujIdUU0fXnV8pvrqSv me@kubbie\\n\", pairUUID = UUID \"fd6a6858-76c9-4eea-b733-9359c7313e72\"},IPv4Addr 1879091392), verifiableDigest = \"cbd8197c3d78c8c68bb30f63aa974cd88dd0fb13\"})"
+[2013-11-01 16:55:59 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"Onyx\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBT0Y6TTzTg8nWwonmgUPPwJmPIaJzfEoJl8DbuylpgXqGCQ4doJXuvBODHIehPfyMr1xCWqNlNNLkcWg/a/eHFceyt3IlcD9XaZ1aKPzPmpjYKKf5amiYd6mAssw8zFaZUvwaXkNuHZpXVZyg6C6TkT6kdfln+6fOJZpSGQzksy0jka/Rzx0KXjsp3oqO4tQJbC7AX0nvmD0zvLtyCURzfGV+n2IqQxpPf2nP75Evt8jamcuqm6pWoe+hj9zjGytIXpSKe35wzRwUAUrjgmZ9NweuWfi2uMPJlDv8/n+Q3HyjygA+GzixBGuYXDt1CD8ISZvuoygS+9+jeY9uYH8b me@Onyx\\n\", pairUUID = UUID \"834b4f39-ca66-4baf-9323-57ef7058d7d0\"},IPv4Addr 2281744576), verifiableDigest = \"8d5d380542f7377f09a4584a38b0dbcea9ea215c\"})"
+[2013-11-01 16:56:00 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"kubbie\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvBEWT+AiAmehOFyTQWlSdwDs7DDbkw7rfZ4W/IeG5awZjMgT5BefIv9cmar8vGIIEFMZLpf8cL3xIargDz0xE2wuqj5CLkdz+DKp5f2FGs11Ax/62DZr+eCiVtPnwijFw0Cz0wMRzkN93uedrvzP/KkNRcczgWh3aZqn8WxlkCia1fyykm/pP3W80MNkiJYX5vXpu1NCV5KLu+UXQzKhM2njOauJ3W5wsMvSl8faZIpEmKVCD3BMDDruxTIxggA3kt9GCGvIbPawy+fGOpp/j6pHqnX3GB2kkT47RIZKYEv99HuLyvea+oY5R11FsC2yYY3ujIdUU0fXnV8pvrqSv me@kubbie\\n\", pairUUID = UUID \"fd6a6858-76c9-4eea-b733-9359c7313e72\"},IPv4Addr 1879091392), verifiableDigest = \"cbd8197c3d78c8c68bb30f63aa974cd88dd0fb13\"})"
+[2013-11-01 16:56:01 CDT] PairListener: received "PairMsg (Verifiable {verifiableVal = (PairReq,PairData {remoteHostName = Just \"Onyx\", remoteUserName = \"me\", remoteDirectory = \"~/annex\", remoteSshPubKey = \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBT0Y6TTzTg8nWwonmgUPPwJmPIaJzfEoJl8DbuylpgXqGCQ4doJXuvBODHIehPfyMr1xCWqNlNNLkcWg/a/eHFceyt3IlcD9XaZ1aKPzPmpjYKKf5amiYd6mAssw8zFaZUvwaXkNuHZpXVZyg6C6TkT6kdfln+6fOJZpSGQzksy0jka/Rzx0KXjsp3oqO4tQJbC7AX0nvmD0zvLtyCURzfGV+n2IqQxpPf2nP75Evt8jamcuqm6pWoe+hj9zjGytIXpSKe35wzRwUAUrjgmZ9NweuWfi2uMPJlDv8/n+Q3HyjygA+GzixBGuYXDt1CD8ISZvuoygS+9+jeY9uYH8b me@Onyx\\n\", pairUUID = UUID \"834b4f39-ca66-4baf-9323-57ef7058d7d0\"},IPv4Addr 2281744576), verifiableDigest = \"8d5d380542f7377f09a4584a38b0dbcea9ea215c\"})"
+...and so on and so on...
+# End of transcript or log.
+"""]]
+
+> I was able to reproduce something very like this by starting
+> pairing separately on both computers under poor network conditions (ie,
+> weak wifi on my front porch).
+>
+> So, I've made a new PairReq message that has not been seen before
+> always make the alert pop up, even if the assistant thinks it is
+> in the middle of its own pairing process (or even another pairing process
+> with a different box on the LAN).
+>
+> (This shouldn't cause a rogue PairAck to disrupt a pairing process part
+> way through.)
+>
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_1_b8c485bafd98be8c21595597af361255._comment b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_1_b8c485bafd98be8c21595597af361255._comment
new file mode 100644
index 000000000..39587ee90
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_1_b8c485bafd98be8c21595597af361255._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 1"
+ date="2013-11-01T23:10:12Z"
+ content="""
+Also, when I initiate the pairing process on one computer only, I can see the PairMsg being constantly received in the other computer's log, but the prompt to finish pairing never appears.
+"""]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_2_bc63489334f44a423645021415ffe196._comment b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_2_bc63489334f44a423645021415ffe196._comment
new file mode 100644
index 000000000..f10b16f3c
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_2_bc63489334f44a423645021415ffe196._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-11-01T23:27:24Z"
+ content="""
+Well I installed the 1 Nov release from the tarball and then it picked up the pair request from the other system. I don't know if it was a bug in the previous version or something to do with the PPA. It's weird that the assistant just wasn't doing anything about the pair request it received.
+
+Thanks for your work on git-annex assistant.
+"""]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_3_6345b174d04b6613c2c55a6ec9e50c21._comment b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_3_6345b174d04b6613c2c55a6ec9e50c21._comment
new file mode 100644
index 000000000..a7eff6744
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_3_6345b174d04b6613c2c55a6ec9e50c21._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T19:02:55Z"
+ content="""
+There is something a little strange in the logs. It shows both Onyx and kubbie are sending PairReqs. Probably one of those is the local computer, logging its own broadcast messages which loop back to it. But normally in pairing, one side starts the pairing process with a PairReq, and the other side pops up an alert and continues the process with a PairAck. It's not normal for both sides to request that pairing start.
+
+Is it possible that you started pairing on both computers separately?
+
+I tried doing that with gnu and darkstar. First I started pairing on gnu. darkstar saw the pair request, but I ignored the alert message about that, and went and started a separate pairing process on darkstar. gnu never showed an alert message for that; it ignored darkstar's PairReqs since it was sending its own.
+
+It's unlikely you'd ignore the alert, but the same thing could happen if the two computers were not able to communicate over the network initially, and pairing were started on both separately. So neither gets a chance to see the other's PairReq and show the alert. Even when they came into communication, they'd each ignore the other's PairReq.
+
+So, that seems like a bug..
+"""]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_4_f39ec6c3d5a016b3c5260162c0b42177._comment b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_4_f39ec6c3d5a016b3c5260162c0b42177._comment
new file mode 100644
index 000000000..cacbad03f
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_4_f39ec6c3d5a016b3c5260162c0b42177._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 4"
+ date="2013-11-02T22:52:31Z"
+ content="""
+I did indeed try to pair from both systems. What happened was, after I started the pair request, I went to the other system, and there was no pair request listed. So I misunderstood the directions and thought I was supposed to go ahead and enter the same password into the other system. (It says that pairing will complete as soon as the password is entered on the other system, so it seems reasonable to try that.) Then both systems were constantly issuing pair requests, but neither system was responding to the requests, even though it was receiving them.
+
+Both systems were always on the network and always able to communicate over it. The bug went away when I upgraded to the 1 Nov release...but then I had some very confusing issues with partially-paired repos from different git-annex versions...I ended up having to start git-annex over from scratch on both systems with the 1 Nov build.
+
+So I'm not sure where to go from here with this bug. Thanks for your help.
+"""]]
diff --git a/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_5_ca0c5ef6e6a6d2c4b64430ac68370b6a._comment b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_5_ca0c5ef6e6a6d2c4b64430ac68370b6a._comment
new file mode 100644
index 000000000..413ca952e
--- /dev/null
+++ b/doc/bugs/Local_pairing_fails:_received_PairMsg_loop/comment_5_ca0c5ef6e6a6d2c4b64430ac68370b6a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 5"
+ date="2013-11-02T22:55:42Z"
+ content="""
+Oh, now I see your comment up there that you fixed it. Awesome. :)
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo.mdwn b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo.mdwn
new file mode 100644
index 000000000..b217b0a3e
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo.mdwn
@@ -0,0 +1,20 @@
+### Please describe the problem.
+
+Creating a USB repo fails with a GPG error.
+
+### What steps will reproduce the problem?
+
+ * Build git-annex and git-annex assistant using the instructions at https://gist.github.com/calmyournerves/7144127
+ * Run git-annex app to launch web interface
+ * Create local repo using web interface
+ * Try to create USB repo using web interface
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version 4.20131105-g136b030 on Mac OS 10.9 Mavericks.
+
+### Please provide any additional information below.
+
+[[!format sh """
+07/Nov/2013:06:51:07 +1100 [Error#yesod-core] user error (gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--with-colons","--list-secret-keys","--fixed-list-mode"] exited 5) @(yesod-core-1.2.4.5:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_1_0b4dcedc58e5071733e1239490aed2ea._comment b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_1_0b4dcedc58e5071733e1239490aed2ea._comment
new file mode 100644
index 000000000..34d8d94b1
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_1_0b4dcedc58e5071733e1239490aed2ea._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="Updated version 4.20131105-g136b030 seems to work"
+ date="2013-11-07T20:28:55Z"
+ content="""
+I've updated to the latest version as of 12 hours ago and I was able to create a USB repo on two computers. 4.20131105-g136b030 showing on the web app but 20131106 on the command line.
+
+Is there an easy way of checking the repo is correctly encrypted? I didn't see anything about encrypting (now the previous error has disappeared) when creating the repo - is this what I should expect?
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_2_1cb1ef0292a3357874b461a77c13373e._comment b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_2_1cb1ef0292a3357874b461a77c13373e._comment
new file mode 100644
index 000000000..83e0b2317
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_2_1cb1ef0292a3357874b461a77c13373e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 2"
+ date="2013-11-08T17:36:53Z"
+ content="""
+USB repos are not set up encryption unless you explicitly request it.
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_3_e5ec1e3ab304d738e3b0847287a47af4._comment b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_3_e5ec1e3ab304d738e3b0847287a47af4._comment
new file mode 100644
index 000000000..0b3a804b9
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_erro_when_creating_USB_repo/comment_3_e5ec1e3ab304d738e3b0847287a47af4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="Yes, I just figured that out"
+ date="2013-11-08T22:09:40Z"
+ content="""
+I figured it out a couple of hours ago when I was able to use the existing USB repo on a new computer that doesn't have any of my private keys on it.
+
+I didn't see an option in the web interface to use encryption - is it command line only?
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo.mdwn b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo.mdwn
new file mode 100644
index 000000000..a08737040
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo.mdwn
@@ -0,0 +1,25 @@
+### Please describe the problem.
+
+Creating a remote S3 repository using the git-annex assistant web interface fails with a GPG error. (I'm also getting a GPG error trying to create a USB repo but it's slightly different so I'll post a different bug.)
+
+### What steps will reproduce the problem?
+
+ * Build git-annex and git-annex assistant using the instructions at https://gist.github.com/calmyournerves/7144127
+ * Run git-annex app to launch web interface
+ * Create local repo using web interface
+ * Try to create encrypted S3 remote repo using web interface
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version 4.20131105-g136b030 on MacOS 10.9 Mavericks.
+
+### Please provide any additional information below.
+
+[[!format sh """
+
+(encryption setup) dyld: Library not loaded: @rpath/libz.1.2.8.dylib
+ Referenced from: /Applications/git-annex.app/Contents/MacOS/bundle/gpg
+ Reason: image not found
+07/Nov/2013:06:38:27 +1100 [Error#yesod-core] user error (gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--gen-random","--armor","1","512"] exited 5) @(yesod-core-1.2.4.5:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_1_d95accb43bd18cc9acbbf1d4069f86b3._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_1_d95accb43bd18cc9acbbf1d4069f86b3._comment
new file mode 100644
index 000000000..0f1e34e31
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_1_d95accb43bd18cc9acbbf1d4069f86b3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="S3 works without encryption"
+ date="2013-11-06T21:09:26Z"
+ content="""
+Not surprisingly, S3 repos work without encryption.
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_2_452a3c524974832f0742efb00df4d576._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_2_452a3c524974832f0742efb00df4d576._comment
new file mode 100644
index 000000000..6b3ca2a0b
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_2_452a3c524974832f0742efb00df4d576._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="Still fails with git-annex version 4.20131105-g136b030"
+ date="2013-11-07T20:32:09Z"
+ content="""
+Updating seems to have fixed my other problem with creating a USB repo but still fails when trying to create an encrypted S3 repo.
+
+ (encryption setup) dyld: Library not loaded: @rpath/libz.1.2.8.dylib
+ Referenced from: /Applications/git-annex.app/Contents/MacOS/bundle/gpg
+ Reason: image not found
+ 08/Nov/2013:07:30:11 +1100 [Error#yesod-core] user error (gpg [\"--batch\",\"--no-tty\",\"--use-agent\",\"--quiet\",\"--trust-model\",\"always\",\"--gen-random\",\"--armor\",\"1\",\"512\"] exited 5) @(yesod-core-1.2.4.5:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_3_f8f6d1e0065e5ba56cd405b1c021ca09._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_3_f8f6d1e0065e5ba56cd405b1c021ca09._comment
new file mode 100644
index 000000000..e2ae9c3dc
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_3_f8f6d1e0065e5ba56cd405b1c021ca09._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 3"
+ date="2013-11-08T17:38:40Z"
+ content="""
+Looks like it failed to include libz.1.2.8.dylib in the bundle for some reason despite gpg needing it.
+
+I don't really see the point in building an app bundle if you're going to install it back to the same machine you built it on. It's much easier to just `cabal install git-annex` in this case.
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_4_b524649cee751532d20a4894d71c5cf3._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_4_b524649cee751532d20a4894d71c5cf3._comment
new file mode 100644
index 000000000..8c7450ca6
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_4_b524649cee751532d20a4894d71c5cf3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="Maybe I'm missing something..."
+ date="2013-11-08T22:12:04Z"
+ content="""
+But does cabal install git-annex install the assistant? On the Mac, I use the app bundle to launch the web interface from my applications folder.
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_5_8312ba868ef616ec00563446c9c3464f._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_5_8312ba868ef616ec00563446c9c3464f._comment
new file mode 100644
index 000000000..f94f2d9c8
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_5_8312ba868ef616ec00563446c9c3464f._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="To answer my own question - &quot;git annex webapp&quot;"
+ date="2013-11-09T00:10:28Z"
+ content="""
+Will open the web app from the command line.
+
+But now I get a different error trying to create an encrypted S3 repo.
+
+ (encryption setup) 09/Nov/2013:11:08:56 +1100 [Error#yesod-core] user error (gpg [\"--quiet\",\"--trust-model\",\"always\",\"--gen-random\",\"--armor\",\"1\",\"512\"] exited 127) @(yesod-core-1.2.4.5:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+"""]]
diff --git a/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_6_1af75c691d27c97397f1901f7c2483b0._comment b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_6_1af75c691d27c97397f1901f7c2483b0._comment
new file mode 100644
index 000000000..19313d9a7
--- /dev/null
+++ b/doc/bugs/Mac_OS_10.9_GPG_error_adding_S3_repo/comment_6_1af75c691d27c97397f1901f7c2483b0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmZgZuUhZlHpd_AbbcixY0QQiutb2I7GWY"
+ nickname="Jimmy"
+ subject="Works with git annex on command line"
+ date="2013-11-09T20:18:38Z"
+ content="""
+git annex initremote cloud type=S3 keyid=key correct creates an encrypted S3 repo and I'm able to upload files.
+"""]]
diff --git a/doc/bugs/OSX_app_issues/comment_13_cb12d419459e5cac766022ee0697fedc._comment b/doc/bugs/OSX_app_issues/comment_13_cb12d419459e5cac766022ee0697fedc._comment
new file mode 100644
index 000000000..c9e199961
--- /dev/null
+++ b/doc/bugs/OSX_app_issues/comment_13_cb12d419459e5cac766022ee0697fedc._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="John"
+ ip="109.242.130.160"
+ subject="runshell typo prevents execution"
+ date="2013-09-22T00:24:10Z"
+ content="""
+Using the latest Mountain Lion build available.
+
+>$ /Applications/git-annex.app/Contents/MacOS/git-annex
+
+>/Applications/git-annex.app/Contents/MacOS/runshell: line 25: syntax error near unexpected token `&'
+
+Line 25:
+>echo \"** runshell loop detected!\"> &2
+
+Fix (obvious but for the sake of completeness):
+>echo \"** runshell loop detected!\" >&2
+"""]]
diff --git a/doc/bugs/OSX_app_issues/comment_14_c966fa549bc73c52034ac9abc49de52a._comment b/doc/bugs/OSX_app_issues/comment_14_c966fa549bc73c52034ac9abc49de52a._comment
new file mode 100644
index 000000000..df45eb601
--- /dev/null
+++ b/doc/bugs/OSX_app_issues/comment_14_c966fa549bc73c52034ac9abc49de52a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.1.250"
+ subject="comment 14"
+ date="2013-09-22T14:15:28Z"
+ content="""
+I have fixed the runshell typo and updated the builds.
+"""]]
diff --git a/doc/bugs/OSX_app_issues/comment_15_10f1df95266f1a8c9ef933183190f6e2._comment b/doc/bugs/OSX_app_issues/comment_15_10f1df95266f1a8c9ef933183190f6e2._comment
new file mode 100644
index 000000000..bdb0b55fa
--- /dev/null
+++ b/doc/bugs/OSX_app_issues/comment_15_10f1df95266f1a8c9ef933183190f6e2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ ip="2a01:240:fe6d:0:8947:cf55:f955:49b9"
+ subject="same typo on Lion build"
+ date="2013-10-23T09:17:58Z"
+ content="""
+Could you please fix this typo on the Lion build?
+"""]]
diff --git a/doc/bugs/OSX_app_issues/comment_16_064e151da121f9c2ef13c19ecb4e7458._comment b/doc/bugs/OSX_app_issues/comment_16_064e151da121f9c2ef13c19ecb4e7458._comment
new file mode 100644
index 000000000..8569bda7c
--- /dev/null
+++ b/doc/bugs/OSX_app_issues/comment_16_064e151da121f9c2ef13c19ecb4e7458._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="Remy"
+ ip="83.87.21.84"
+ subject="Crashes on OSX 10.9"
+ date="2013-10-23T20:30:12Z"
+ content="""
+I just installed OSX Mavericks. I also took the latest autobuild and copied it over the old git-annex.app to be sure it doesn't work.
+When I execute \"git-annex status\" I get the following message
+
+
+> dyld: Symbol not found: _objc_debug_taggedpointer_mask
+> Referenced from: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+> Expected in: /Applications/git-annex.app/Contents/MacOS/bundle/I
+> in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+> [1] 1361 trace trap git-annex status
+"""]]
diff --git a/doc/bugs/OSX_app_issues/comment_17_0e6ac5e0a54ce78bdc56c62e6fb92846._comment b/doc/bugs/OSX_app_issues/comment_17_0e6ac5e0a54ce78bdc56c62e6fb92846._comment
new file mode 100644
index 000000000..5d5c0237e
--- /dev/null
+++ b/doc/bugs/OSX_app_issues/comment_17_0e6ac5e0a54ce78bdc56c62e6fb92846._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="calmyournerves"
+ ip="85.3.250.239"
+ subject="comment 17"
+ date="2013-10-24T21:43:37Z"
+ content="""
+For 10.9 Mavericks see http://git-annex.branchable.com/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/#comments
+"""]]
diff --git a/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex.mdwn b/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex.mdwn
new file mode 100644
index 000000000..3860456d2
--- /dev/null
+++ b/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex.mdwn
@@ -0,0 +1,54 @@
+### Please describe the problem.
+
+(small) identical files fail to unannex, leaving broken symlinks, except for the first copy.
+
+### What steps will reproduce the problem?
+
+* Have multiple identical files. For example, run this, which creates four 6-byte files:
+
+> echo Hello>file1.txt && cp file1.txt file2.txt && cp file1.txt file3.txt && cp file1.txt file4.txt
+
+* Run this (git init needs credentials to have been specified though)
+
+> git init && git-annex init && git-annex add
+
+Now there are 4 symlinks, pointing to the same object:
+
+> lrwxrwxrwx 1 186 Aug 16 15:54 file1.txt -> .git/annex/objects/31/XV/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt
+
+* Optionally run "git commit -a". It doesn't affect the outcome.
+
+* Run git-annex unannex
+
+> $ git annex unannex
+> unannex file1.txt ok
+> (Recording state in git...)
+> $
+
+Now file1.txt is a normal 6-byte file again, but 2, 3, and 4 are broken symlinks:
+
+ -rw-r----- 1 6 Aug 16 15:54 file1.txt
+ lrwxrwxrwx 1 186 Aug 16 15:54 file2.txt -> .git/annex/objects/31/XV/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt
+ lrwxrwxrwx 1 186 Aug 16 15:54 file3.txt -> .git/annex/objects/31/XV/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt
+ lrwxrwxrwx 1 186 Aug 16 15:54 file4.txt -> .git/annex/objects/31/XV/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt/SHA256E-s6--66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18.txt
+
+ $ git-annex fsck
+ fsck file2.txt
+ ** No known copies exist of file2.txt
+ failed
+ fsck file3.txt
+ ** No known copies exist of file3.txt
+ failed
+ fsck file4.txt
+ ** No known copies exist of file4.txt
+ failed
+ git-annex: fsck: 3 failed
+
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex 4.20130802 package
+
+on Debian GNU/Linux jessie/sid (testing), amd64.
+
+> [[dup|done]] --[[Joey]]
diff --git a/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex/comment_2_f7149b684a97070cff051b780c73be48._comment b/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex/comment_2_f7149b684a97070cff051b780c73be48._comment
new file mode 100644
index 000000000..ca3ad1229
--- /dev/null
+++ b/doc/bugs/Of_identical_files__44___all_but_the_first_copy_are_lost_on_unannex/comment_2_f7149b684a97070cff051b780c73be48._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://openid.yandex.ru/deletesoftware/"
+ nickname="deletesoftware"
+ subject="duplicate"
+ date="2013-08-16T14:52:23Z"
+ content="""
+It's the same as these:
+
+* [Large unannex operations result in stale symlinks and data loss](http://git-annex.branchable.com/bugs/Large_unannex_operations_result_in_stale_symlinks_and_data_loss/)
+* [unannex removes object even if referred to by others](http://git-annex.branchable.com/bugs/unannex_removes_object_even_if_referred_to_by_others/)
+* [annex unannex/uninit should handle copies](http://git-annex.branchable.com/bugs/annex_unannex__47__uninit_should_handle_copies/)
+
+and (as gernot mentioned) according to those, has a workaround of \"git annex unannex --fast\". Of course, it's not convenient to need to find a workaround, and to notice a potential dataloss issue…
+
+"""]]
diff --git a/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple.mdwn b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple.mdwn
index 96d73f0f4..46ae06f6d 100644
--- a/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple.mdwn
+++ b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple.mdwn
@@ -59,4 +59,6 @@ My .gitconfig is as follows:
"""]]
> Closing this because all autobuilders have been upgraded
-> to a more recent version of git. [[done]] --[[Joey]]
+> to a more recent version of git. done --[[Joey]]
+>> Reopened, because the Linux autobuilds have been downgraded to Debian
+>> stable and have this problem again. --[[Joey]]
diff --git a/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_3_eaed9b5532e30e401f50193a72b98310._comment b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_3_eaed9b5532e30e401f50193a72b98310._comment
new file mode 100644
index 000000000..bee277aa6
--- /dev/null
+++ b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_3_eaed9b5532e30e401f50193a72b98310._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmTNrhkVQ26GBLaLD5-zNuEiR8syTj4mI8"
+ nickname="Juan"
+ subject="Still happening in the linux autobuild (08/22/2013)"
+ date="2013-08-23T02:04:42Z"
+ content="""
+I've seen that git-annex for linux is still coming with git 1.7, which causes problems with my installed git (1.8.1.2).
+Wasn't that corrected in autobuilds?
+Thanks in advance.
+Keep up the good work.
+Regards,
+ Juan
+"""]]
diff --git a/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_4_1fab407f3823ce8cec87f5df55e49f8c._comment b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_4_1fab407f3823ce8cec87f5df55e49f8c._comment
new file mode 100644
index 000000000..2c9c33c8e
--- /dev/null
+++ b/doc/bugs/Older_version_of_git_causes_Internal_Server_Error_when_push.default___61___simple/comment_4_1fab407f3823ce8cec87f5df55e49f8c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 4"
+ date="2013-08-23T17:41:32Z"
+ content="""
+It was done for the autobuilds, but then I switched them to build using Debian stable, which still has git 1.7, and there is not currently a backport of a newer git to stable for me to use.
+"""]]
diff --git a/doc/bugs/On_Windows__44___can__39__t_use_a_USB_disk_annex_created_on_Linux.mdwn b/doc/bugs/On_Windows__44___can__39__t_use_a_USB_disk_annex_created_on_Linux.mdwn
index ea36ac561..b997a8c72 100644
--- a/doc/bugs/On_Windows__44___can__39__t_use_a_USB_disk_annex_created_on_Linux.mdwn
+++ b/doc/bugs/On_Windows__44___can__39__t_use_a_USB_disk_annex_created_on_Linux.mdwn
@@ -14,3 +14,5 @@ On Windows, git-annex is unable to 'annex get' from a repository hosted on an ex
Windows 7: 4.20140627-g8a36ec5 (from the git-annex download page)
Debian Linux: 3.20120629 (from the package manager)
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured.mdwn b/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured.mdwn
index 07f8fa84c..92de1dce3 100644
--- a/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured.mdwn
+++ b/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured.mdwn
@@ -18,3 +18,5 @@ Debian Linux: 3.20120629 (from the package manager)
I experienced this bug several times with a plain git-annex install, and the only workaround was removing the unix-style remotes from remote repos.
After other hackery to get git-annex working on Windows, I can't currently reproduce the issue.
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured/comment_1_95655915ff6ba9fb5d873358ff047496._comment b/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured/comment_1_95655915ff6ba9fb5d873358ff047496._comment
new file mode 100644
index 000000000..d727bcafc
--- /dev/null
+++ b/doc/bugs/On_Windows__44___can__39__t_use_repository_that_has_a_unix-style_local_remote_configured/comment_1_95655915ff6ba9fb5d873358ff047496._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 1"
+ date="2013-09-13T19:14:55Z"
+ content="""
+I don't understand what is meant by a \"unix-style\" remote.
+
+Generally it helps to provide some commands I can run on Windows to replicate the problem.
+"""]]
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
new file mode 100644
index 000000000..e01310336
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone..mdwn
@@ -0,0 +1,230 @@
+### Please describe the problem.
+
+I had set up git-annex on a mac; I had created an initial repository at ~/annex; I had created a second repository on an external drive, at /Volumes/Biblio/annex; I had paired with three other machines on the same network, (two linux, one other mac) and set up a remote server as a backup-type repository. All seemed well. It had finally finished syncing everything to the remote server (my upload speeds are slow).
+
+I closed the firefox window showing the dashboard. I wanted to reopen it, so I ran the git-annex.app again, presuming on a running instance that that just opens the browser back at the webapp. Firefox window opened, but the only repository was the second one I'd made on the external drive.
+
+I restarted, as best as I could work out: git-annex assistant --stop, then because that left behind a process, killall git-annex. Then restarted the app.
+
+Firefox opened on the webapp. I had two repositories: The one on the external drive (now the "Here" repo) and the one on ~/annex but only as if it was paired from a different machine.
+
+ie: I see only "celestia.local (rachel@celestia.local~/annex)". This machine *is* celestia.local.
+
+That's it. Startup scan took a couple of minutes but didn't add anything. Then it decided to sync to celestia.local, which it took a little time over but didn't apparently do anything.
+
+If I drop files into ~/annex they are not synced anywhere. ~/annex still has a .git directory, populated with git files, it looks intact. It's just not being seen.
+
+Is it possible because the user is prompted to create their initial repo at ~/Desktop/annex it will by default only look there, then start looking in external drives for it? So the fact I didn't want it on my desktop, but put it directly in home, meant it got lost on restart?
+
+git-annex vicfg in ~/annex shows me this:
+
+[[!format sh """
+# git-annex configuration
+#
+# Changes saved to this file will be recorded in the git-annex branch.
+#
+# Lines in this file have the format:
+# setting uuid = value
+
+# Repository trust configuration
+# (Valid trust levels: trusted semitrusted untrusted dead)
+# (for web)
+#trust 00000000-0000-0000-0000-000000000001 = semitrusted
+# (for rachel@octavia:~/annex)
+#trust 161dec38-e8be-43b8-86c5-555d35ce3416 = semitrusted
+# (for rachel@celestia.local:~/annex)
+#trust 179fcddf-e247-4577-804b-267feed8abb1 = semitrusted
+# (for 192.168.1.103_annex (rachel@rainbow.local:~/annex))
+#trust 256d5762-150d-4d5d-9340-517de298c874 = semitrusted
+# (for twilight.local_annex (rachel@twilight:~/annex))
+#trust aeef7490-ce27-4255-b800-1947706c4a06 = semitrusted
+# (for rachel@octavia:~/annex)
+#trust c469fbce-f3b4-4e27-a54f-0b747797a7d5 = semitrusted
+# (for annex (Biblio's Copy))
+#trust c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = semitrusted
+# (for luna.strangenoises.org_annex)
+#trust f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = semitrusted
+# (for octavia.local_annex (rachel@octavia:~/annex))
+#trust f748a5ed-d870-48fb-b3ec-811488eb2faa = semitrusted
+# (for rachel@twilight:~/annex)
+#trust fcaba03e-1ba5-11e3-90f1-57fe1467e006 = semitrusted
+
+# Repository groups
+# (Standard groups: client transfer backup incrementalbackup smallarchive archive source manual public unwanted)
+# (Separate group names with spaces)
+# (for rachel@octavia:~/annex)
+group 161dec38-e8be-43b8-86c5-555d35ce3416 = client
+# (for rachel@celestia.local:~/annex)
+group 179fcddf-e247-4577-804b-267feed8abb1 = client
+# (for 192.168.1.103_annex (rachel@rainbow.local:~/annex))
+group 256d5762-150d-4d5d-9340-517de298c874 = client
+# (for twilight.local_annex (rachel@twilight:~/annex))
+group aeef7490-ce27-4255-b800-1947706c4a06 = client
+# (for rachel@octavia:~/annex)
+group c469fbce-f3b4-4e27-a54f-0b747797a7d5 = client
+# (for annex (Biblio's Copy))
+group c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = client
+# (for octavia.local_annex (rachel@octavia:~/annex))
+group f748a5ed-d870-48fb-b3ec-811488eb2faa = client
+# (for rachel@twilight:~/annex)
+group fcaba03e-1ba5-11e3-90f1-57fe1467e006 = client
+# (for luna.strangenoises.org_annex)
+group f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = transfer
+# (for web)
+#group 00000000-0000-0000-0000-000000000001 =
+
+# Repository preferred contents
+# (for rachel@octavia:~/annex)
+content 161dec38-e8be-43b8-86c5-555d35ce3416 = standard
+# (for rachel@celestia.local:~/annex)
+content 179fcddf-e247-4577-804b-267feed8abb1 = standard
+# (for 192.168.1.103_annex (rachel@rainbow.local:~/annex))
+content 256d5762-150d-4d5d-9340-517de298c874 = standard
+# (for twilight.local_annex (rachel@twilight:~/annex))
+content aeef7490-ce27-4255-b800-1947706c4a06 = standard
+# (for rachel@octavia:~/annex)
+content c469fbce-f3b4-4e27-a54f-0b747797a7d5 = standard
+# (for annex (Biblio's Copy))
+content c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = standard
+# (for luna.strangenoises.org_annex)
+content f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = standard
+# (for octavia.local_annex (rachel@octavia:~/annex))
+content f748a5ed-d870-48fb-b3ec-811488eb2faa = standard
+# (for rachel@twilight:~/annex)
+content fcaba03e-1ba5-11e3-90f1-57fe1467e006 = standard
+# (for web)
+#content 00000000-0000-0000-0000-000000000001 =
+"""]]
+
+while the same command in /Volumes/Biblio/annex gives:
+
+[[!format sh """
+# git-annex configuration
+#
+# Changes saved to this file will be recorded in the git-annex branch.
+#
+# Lines in this file have the format:
+# setting uuid = value
+
+# Repository trust configuration
+# (Valid trust levels: trusted semitrusted untrusted dead)
+# (for web)
+#trust 00000000-0000-0000-0000-000000000001 = semitrusted
+# (for rachel@octavia:~/annex)
+#trust 161dec38-e8be-43b8-86c5-555d35ce3416 = semitrusted
+# (for celestia.local (rachel@celestia.local:~/annex))
+#trust 179fcddf-e247-4577-804b-267feed8abb1 = semitrusted
+# (for rachel@rainbow.local:~/annex)
+#trust 256d5762-150d-4d5d-9340-517de298c874 = semitrusted
+# (for rachel@twilight:~/annex)
+#trust aeef7490-ce27-4255-b800-1947706c4a06 = semitrusted
+# (for rachel@octavia:~/annex)
+#trust c469fbce-f3b4-4e27-a54f-0b747797a7d5 = semitrusted
+# (for Biblio's Copy)
+#trust c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = semitrusted
+# (for )
+#trust f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = semitrusted
+# (for rachel@octavia:~/annex)
+#trust f748a5ed-d870-48fb-b3ec-811488eb2faa = semitrusted
+# (for rachel@twilight:~/annex)
+#trust fcaba03e-1ba5-11e3-90f1-57fe1467e006 = semitrusted
+
+# Repository groups
+# (Standard groups: client transfer backup incrementalbackup smallarchive archive source manual public unwanted)
+# (Separate group names with spaces)
+# (for rachel@octavia:~/annex)
+group 161dec38-e8be-43b8-86c5-555d35ce3416 = client
+# (for celestia.local (rachel@celestia.local:~/annex))
+group 179fcddf-e247-4577-804b-267feed8abb1 = client
+# (for rachel@rainbow.local:~/annex)
+group 256d5762-150d-4d5d-9340-517de298c874 = client
+# (for rachel@twilight:~/annex)
+group aeef7490-ce27-4255-b800-1947706c4a06 = client
+# (for rachel@octavia:~/annex)
+group c469fbce-f3b4-4e27-a54f-0b747797a7d5 = client
+# (for Biblio's Copy)
+group c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = client
+# (for rachel@octavia:~/annex)
+group f748a5ed-d870-48fb-b3ec-811488eb2faa = client
+# (for rachel@twilight:~/annex)
+group fcaba03e-1ba5-11e3-90f1-57fe1467e006 = client
+# (for )
+group f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = transfer
+# (for web)
+#group 00000000-0000-0000-0000-000000000001 =
+
+# Repository preferred contents
+# (for rachel@octavia:~/annex)
+content 161dec38-e8be-43b8-86c5-555d35ce3416 = standard
+# (for celestia.local (rachel@celestia.local:~/annex))
+content 179fcddf-e247-4577-804b-267feed8abb1 = standard
+# (for rachel@rainbow.local:~/annex)
+content 256d5762-150d-4d5d-9340-517de298c874 = standard
+# (for rachel@twilight:~/annex)
+content aeef7490-ce27-4255-b800-1947706c4a06 = standard
+# (for rachel@octavia:~/annex)
+content c469fbce-f3b4-4e27-a54f-0b747797a7d5 = standard
+# (for Biblio's Copy)
+content c9e307e2-1189-47ed-8ad4-03b5c1b64e36 = standard
+# (for )
+content f36dbdf8-1bba-11e3-9dbe-f33cfb0e2bed = standard
+# (for rachel@octavia:~/annex)
+content f748a5ed-d870-48fb-b3ec-811488eb2faa = standard
+# (for rachel@twilight:~/annex)
+content fcaba03e-1ba5-11e3-90f1-57fe1467e006 = standard
+# (for web)
+#content 00000000-0000-0000-0000-000000000001 =
+"""]]
+
+### What steps will reproduce the problem?
+
+As above. I have no idea what just happened, but apart from git-annex assistant --stop and having to mop up leftover processes, I didn't use the git-annex commandline for anything.
+
+### What version of git-annex are you using? On what operating system?
+
+Mac OS X 10.8.4
+
+ Version: 4.20130909-ga29f960
+ Build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi
+
+### Please provide any additional information below.
+
+The log on ~/annex/.git/annex/daemon.log is huge and full of transfers of files with my personal filenames. I'd rather not. It appears to end normally.
+
+Now there is a short log in /Volumes/Biblio/annex/.git/annex/daemon.log from, I guess, the time I tried to restart. For some reason therefore, after the successful session finished, on restart it only looks here. This log is appended.
+
+[[!format sh """
+[2013-09-12 21:35:39 BST] main: starting assistant version 4.20130909-ga29f960
+
+[2013-09-12 21:35:39 BST] TransferScanner: Syncing with celestia.local
+Already up-to-date.
+
+(scanning...) [2013-09-12 21:35:39 BST] Watcher: Performing startup scan
+From /Users/rachel/annex
+ * [new branch] git-annex -> celestia.local/git-annex
+ * [new branch] master -> celestia.local/master
+ * [new branch] synced/git-annex -> celestia.local/synced/git-annex
+ * [new branch] synced/master -> celestia.local/synced/master
+Updating 4f974a8..74770d9
+Fast-forward
+Already up-to-date.
+Already up-to-date.
+Already up-to-date.
+[2013-09-12 21:36:39 BST] Pusher: Syncing with celestia.local
+(merging celestia.local/git-annex celestia.local/synced/git-annex into git-annex...)
+(Recording state in git...)
+
+
+
+
+(started...) error: Ref refs/heads/synced/git-annex is at 5b4ed9b3098e936d60b61a1d3915fa29e8c823d0 but expected 792d2a5c14b0b6327d2089e174063c474ba5a764
+remote: error: failed to lock refs/heads/synced/git-annex
+To /Users/rachel/annex
+ 792d2a5..5b4ed9b git-annex -> synced/git-annex
+To /Users/rachel/annex
+ ! [remote rejected] git-annex -> synced/git-annex (failed to lock)
+error: failed to push some refs to '/Users/rachel/annex'
+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.
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_1_3a3891c9d7ee808f6a71780cb628f23d._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_1_3a3891c9d7ee808f6a71780cb628f23d._comment
new file mode 100644
index 000000000..a26db0870
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_1_3a3891c9d7ee808f6a71780cb628f23d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T21:29:39Z"
+ content="""
+The git-annex webapp displays a view from \"inside\" one git repsitory at a time. It seems to me that you have two or more local git repositories; one in ~/annex and one on a removable drive. The webapp is coming up viewing from inside your removable drive's repository. You can change the repository that the webapp views by going to the Repository menu in the upper-right corner and selecting Switch repository. The webapp will remember which repository it viewed last, and come back up showing that same repository.
+
+It's BTW an unusual configuration to have the git-annex assistant directly running on a removable drive as you seem to have done. You must have previously went to the Repository menu and selected \"Add another local repository\", and then added the removable drive, and then connected that repository up to your ~/annex repository. Which would explain why the webapp was last showing the repository on the removable drive. The more usual way to add a removable drive is to use the \"Add another repository\" button and select \"Removable drive\".
+
+I think, but am not sure, that the error \"Ref refs/heads/synced/git-annex is at 5b4ed9b3098e936d60b61a1d3915fa29e8c823d0 but expected 792d2a5c14b0b6327d2089e174063c474ba5a764\" is due to having two git-annex assistants running in these two different repositories and both updating them both at the same time. You might want to stop all git-annex processes, edit `~/.config/git-annex/autostart` and remove the removable drive repository from that list, leaving only `~/annex` in the list.
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_2_2bc6efb1d9e872cc5d4fbfbaaf5cc10e._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_2_2bc6efb1d9e872cc5d4fbfbaaf5cc10e._comment
new file mode 100644
index 000000000..10fad2252
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_2_2bc6efb1d9e872cc5d4fbfbaaf5cc10e._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="I don't know whether I've fixed it or confused things further"
+ date="2013-09-12T21:30:44Z"
+ content="""
+I shut down the daemon that was running from the webapp itself.
+
+Instead of launching by using the app, I did:
+
+[[!format txt \"\"\"
+celestia:~ rachel$ cd annex/
+celestia:annex rachel$ git-annex assistant
+(merging synced/git-annex into git-annex...)
+celestia:annex rachel$ git-annex webapp
+Launching web browser on file:///Users/rachel/annex/.git/annex/webapp.html
+celestia:annex rachel$
+\"\"\"]]
+
+It opened the webapp. I could see all the repos back again.
+
+It also seems to be syncing to everything else, sending the files all over again, even though they haven't changed.
+
+It's just about possible it's completing the job, as I'm not sure I saw the files syncing now, being synced earlier. But... in that earlier session it had run the queue dry, *it* thought it had completed syncing.
+
+What's going on?
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_3_fff1e778a6334258c173a96e6bf7ef6a._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_3_fff1e778a6334258c173a96e6bf7ef6a._comment
new file mode 100644
index 000000000..4d44aaf5c
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_3_fff1e778a6334258c173a96e6bf7ef6a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 3"
+ date="2013-09-12T21:33:18Z"
+ content="""
+See my explanation above. By manually starting the webapp inside your ~/annex repository you forced it to view that repository.
+
+It's not unusual for the webapp to display it syncing some files that have been synced before. This repository may not be up-to-date on which files have been sent where, and it will quickly notice the file has already been transferred and skip doing anything for that file.
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_4_2a86da97a89e28f0a0f5e160d4932ae6._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_4_2a86da97a89e28f0a0f5e160d4932ae6._comment
new file mode 100644
index 000000000..16a5a351f
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_4_2a86da97a89e28f0a0f5e160d4932ae6._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="Last night's comment"
+ date="2013-09-13T10:28:02Z"
+ content="""
+> It's BTW an unusual configuration to have the git-annex assistant directly running on a removable drive as you seem to have done. You must have previously went to the Repository menu and selected \"Add another local repository\", and then added the removable drive, and then connected that repository up to your ~/annex repository. Which would explain why the webapp was last showing the repository on the removable drive. The more usual way to add a removable drive is to use the \"Add another repository\" button and select \"Removable drive\".
+
+That is exactly how I'd added that repository, yes. I didn't notice the dedicated \"removable drive\" option until later. :-) I thought it possibly appropriate to leave it that way because, while Biblio is an external drive and remov*able*, in practice I never remove it; it's a permanent fixture.
+
+After all, this is a mac mini server, originally (no longer running Server) so it has a second *internal* drive. It would have been even more logical for me to have added a second repo on there in the same manner, as it's most definitely not removable without extreme effort; but it still mounts inside /Volumes, and presumably if I'd added it as a non-removable repo, I'd have had the same problem?
+
+> It's not unusual for the webapp to display it syncing some files that have been synced before. This repository may not be up-to-date on which files have been sent where, and it will quickly notice the file has already been transferred and skip doing anything for that file.
+
+Yes, that's probably what happened. It finished pretty quickly, about a minute after sending my previous comment.
+
+Going to bed now, but tomorrow I'll follow the remaining suggestions; basically I'll remove the repo on the external drive then, if I still want it there, I'll add it back in the other way, so it thinks of it as removable.
+
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_5_41b8e8e58025cc8c8f12efb9a51acd29._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_5_41b8e8e58025cc8c8f12efb9a51acd29._comment
new file mode 100644
index 000000000..685d1b024
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_5_41b8e8e58025cc8c8f12efb9a51acd29._comment
@@ -0,0 +1,50 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="And this morning..."
+ date="2013-09-13T10:38:35Z"
+ content="""
+I tried removing the second repo, by deleting it, it seemed to begin normally. Then it just hung, and hung.
+
+Looking at logs, it seemed to be hung on dropping one file - a very small file in fact, but it was probably the most recent file to be added. So the end of the log just looked like:
+
+[[!format txt \"\"\"
+drop annex old stuff/renegade/issue7back.pdf ok
+drop annex old stuff/renegade/issue7fiction.pdf ok
+drop annex postgresql 9.0->9.1 upgrade process
+\"\"\"]]
+
+After a while I started getting problems in other terminal shells where I was doing stuff unrelated to git annex. eg: on trying to open a new terminal window, it would open, then shut immediately, or it would open with just:
+
+[[!format txt \"\"\"
+forkpty: Resource temporarily unavailable
+Could not create a new process and open a pseudo-tty.
+\"\"\"]]
+
+Various other commands that would have resulted in a fork were failing too. In the end I shut down git annex (using the shutdown daemon open in the menu in the webapp), and everything went back to normal.
+
+This is the end of the daemon.log from this morning. I don't want to paste the whole thing, as essentially it lists all my private filenames, and there's a lot. In fact I wonder if the quantity of files may be a factor:
+
+[[!format txt \"\"\"
+drop annex old stuff/renegade/index.html ok
+drop annex old stuff/renegade/issue1.pdf ok
+drop annex old stuff/renegade/issue2.pdf ok
+drop annex old stuff/renegade/issue3.pdf ok
+drop annex old stuff/renegade/issue4.pdf ok
+drop annex old stuff/renegade/issue4coverpic.pdf ok
+drop annex old stuff/renegade/issue6articles.pdf ok
+drop annex old stuff/renegade/issue6cover.pdf ok
+drop annex old stuff/renegade/issue6fiction.pdf ok
+drop annex old stuff/renegade/issue7articles.pdf ok
+drop annex old stuff/renegade/issue7back.pdf ok
+drop annex old stuff/renegade/issue7fiction.pdf ok
+drop annex postgresql 9.0->9.1 upgrade process [2013-09-13 11:25:07 BST] NetWatcherFallback: Syncing with twilight.local_annex, octavia.local_annex, 192.168.1.103_annex, luna.strangenoises.org_annex
+NetWatcherFallback crashed: git: createProcess: resource exhausted (Resource temporarily unavailable)
+[2013-09-13 11:25:07 BST] NetWatcherFallback: warning NetWatcherFallback crashed: git: createProcess: resource exhausted (Resource temporarily unavailable)
+recv: resource vanisrhreeecdcv v:(: C rorenesnsoeoucurtrciceoe n v varanenisiseshthe edbd y ( (CpCoeonennrne)ec
+cttiioonn rreesseett bbyy ppeeeerr))
+
+[2013-09-13 11:26:32 BST] main: warning git-annex has been shut down
+\"\"\"]]
+
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_6_38afcd8e7fb278ca0ee2e9e0c9f6883e._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_6_38afcd8e7fb278ca0ee2e9e0c9f6883e._comment
new file mode 100644
index 000000000..c0923b22a
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_6_38afcd8e7fb278ca0ee2e9e0c9f6883e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="comment 6"
+ date="2013-09-13T10:52:07Z"
+ content="""
+FYI, if there's any relevance to the number of files in the annex, there are 1899 files in the annex at the moment, so that many in the one being deleted. The one it hung on, \"postgresql 9.0->9.1 upgrade process\" was indeed the last one that comes up in a find command, which I think means the most recently added to this dir.
+
+Creating too many threads?
+"""]]
diff --git a/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_7_06de36dcde4c52ab74c8134f3242ac02._comment b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_7_06de36dcde4c52ab74c8134f3242ac02._comment
new file mode 100644
index 000000000..c11630ef7
--- /dev/null
+++ b/doc/bugs/On_restart__44___most_repositories__44___including_original_one__44___gone./comment_7_06de36dcde4c52ab74c8134f3242ac02._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="comment 7"
+ date="2013-09-13T10:54:37Z"
+ content="""
+... and resolved for myself by just deleting (dropping in the trash for now) the annex on the external volume, restarting git-annex assistant and *disabling* that repo from the menu rather than deleting it.
+
+"""]]
diff --git a/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds.mdwn b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds.mdwn
index d63394b02..c127bac15 100644
--- a/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds.mdwn
+++ b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds.mdwn
@@ -77,4 +77,8 @@ Any thoughts on how I can get git-annex (esp. fsck) to complete would be appreci
Thanks
Giovanni
-[[!tag moreinfo]]
+> [[fixed|done]]. However, if you saw this behavior,
+> you have large files checked directly into git. You may
+> want to examine your repository and use git filter-branch to clean
+> it up.
+> --[[Joey]]
diff --git a/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_6_9e3300b223dd54a3f07c650f5cf70ae0._comment b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_6_9e3300b223dd54a3f07c650f5cf70ae0._comment
new file mode 100644
index 000000000..b648eb9a4
--- /dev/null
+++ b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_6_9e3300b223dd54a3f07c650f5cf70ae0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://churchkey.org/author/ian/"
+ ip="2001:470:8a52:67:a800:4ff:fe00:a04"
+ subject="Same problem, different user"
+ date="2013-09-18T22:20:09Z"
+ content="""
+@joey I appear to have run into this same problem through a similar series of repository operations. I began with the assistant, which caused some trouble while trying to set up on multiple machines, so I started using the git-annex commands directly, switched the client to direct mode, and at some point along the way I started getting the \"git-annex: out of memory (requested 1048576 bytes)\" error on my home client any time I try to run a find, whereis, status, or sync operation. On my work client I instead run into a \"fatal: write error: Invalid argument\" error. Both clients are in direct mode and both stop on the same files. I have tried to drop these files and the ones that follow them sequentially to try and clear out the grit from the machine, but to no avail. I'm available for diagnostics to help resolve this. The files in question are not symlinks and running \"echo HEAD:./$filename | git cat-file --batch\" simply produces binary blobs the same size as the original files. Running \"git ls-tree -r git-annex | wc -l\" gives \"41262\" for the client with the \"Out of memory\" error and \"41260\" for the \"write error\" client.
+"""]]
diff --git a/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_7_b91f4a87b6d29ae6b4262922fd65a79d._comment b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_7_b91f4a87b6d29ae6b4262922fd65a79d._comment
new file mode 100644
index 000000000..c7832477c
--- /dev/null
+++ b/doc/bugs/Out_of_memory_error_in_fsck_whereis_find_and_status_cmds/comment_7_b91f4a87b6d29ae6b4262922fd65a79d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 7"
+ date="2013-09-19T19:07:03Z"
+ content="""
+[[Huge_annex_out_of_memory_on_switch_to_indirect_mode_and_status]] is a duplicate of this bug.
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files.mdwn b/doc/bugs/Problem_when_dropping_unused_files.mdwn
new file mode 100644
index 000000000..2c15680b8
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files.mdwn
@@ -0,0 +1,21 @@
+### Please describe the problem.
+
+While dropping 19 unused files from an annex, I got this error:
+
+ error: invalid object 100644 c873416e78db4dd94b6ab40470d6fe99b2ecb8bd for '002/0a6/SHA256E-s427690--03aeabcde841b66168b72de80098d74e047f3ffc832d4bbefa1f2f70ee6c92f8.jpg.log'
+ fatal: git-write-tree: error building trees
+ git-annex: failed to read sha from git write-tree
+
+I've actually seen this before, a few months ago.
+
+### What steps will reproduce the problem?
+
+I have no idea, but once it happens I can't interact with unused files anymore. Also, `git annex fsck` now reports this same problem as well.
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 4.20130815, OS X 10.8.4
+
+> [[done]]; no indication this is anything other than a corrupt git
+> repository, which can be caused by system crash, disk data loss,
+> cosmic rays, etc. This is why we keep backups... --[[Joey]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_10_d4f6bfe8e04560fc661a47b09ed8a5f4._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_10_d4f6bfe8e04560fc661a47b09ed8a5f4._comment
new file mode 100644
index 000000000..9c0e25528
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_10_d4f6bfe8e04560fc661a47b09ed8a5f4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.251.174"
+ subject="comment 10"
+ date="2013-09-07T17:14:36Z"
+ content="""
+Again this error message has nothing to do with git-annex beyond it being a file in the git-annex branch that is corrupt. Your system seems to be repeatedly corrupting git repositories. You need to run `git fsck`, get the git repository in a clean state, and probably check the drive it's on, and run a memory test or otherwise deal with whatever is causing your system to corrupt files in the git repository.
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_1_e1a99bd3eb8b3186653b52a52b1836de._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_1_e1a99bd3eb8b3186653b52a52b1836de._comment
new file mode 100644
index 000000000..0e39a96fc
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_1_e1a99bd3eb8b3186653b52a52b1836de._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 1"
+ date="2013-08-24T05:01:37Z"
+ content="""
+The following command restored some sanity:
+
+ find .git/annex/ -name '*.log' -delete
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_2_dec3e5ffe5cfdc439f418ee00d7d9810._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_2_dec3e5ffe5cfdc439f418ee00d7d9810._comment
new file mode 100644
index 000000000..e0c5a2882
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_2_dec3e5ffe5cfdc439f418ee00d7d9810._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 2"
+ date="2013-08-24T11:40:54Z"
+ content="""
+If I recall, such files being stored in the annex object store is a result of using direct mode?
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_3_d106a87101db52f957da84d90dafcdbb._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_3_d106a87101db52f957da84d90dafcdbb._comment
new file mode 100644
index 000000000..8c739552d
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_3_d106a87101db52f957da84d90dafcdbb._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 3"
+ date="2013-08-24T16:04:21Z"
+ content="""
+Unfortunately, the git error message you pasted suggests very strongly that your git repository has gotten corrupted. You can probably verify that by running `git annex fsck`. Assuming it is corrupted, the best thing to do is to make a new clone and move .git/annex and .git/config over from the corrupted repository to it, and finally run `git annex fsck`
+
+You then seem to have some reason decided to go delete git-annex's .git/annex/journal/*.log files, which are just files that have not yet been committed to the git-annex branch. The only reason this \"restored some sanity\" is that git-annex was trying to commit that data to git, and failing because your git repository is corrupted.
+
+(This has nothing at all to do with direct mode.)
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_4_f28ed0635612693e437e64d872af5c37._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_4_f28ed0635612693e437e64d872af5c37._comment
new file mode 100644
index 000000000..ba2e693ee
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_4_f28ed0635612693e437e64d872af5c37._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 4"
+ date="2013-08-25T05:27:57Z"
+ content="""
+Do you have any thoughts on why it may have gotten corrupted, or why it seems to happen so commonly with large git-annex repositories? I've seen this exact same sort of error while processing log files maybe 5 or 6 times now.
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_5_f0237075653768c84deb702442645f28._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_5_f0237075653768c84deb702442645f28._comment
new file mode 100644
index 000000000..4ad874c08
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_5_f0237075653768c84deb702442645f28._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 5"
+ date="2013-08-25T05:50:35Z"
+ content="""
+I meant to say, in 5 or 6 different repositories. Further, when I see it happen the next time, how do you recommend I track down the real problem, instead of always just cloning and starting over?
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_6_b509006e1590480a104627369bc910f2._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_6_b509006e1590480a104627369bc910f2._comment
new file mode 100644
index 000000000..60f2165e2
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_6_b509006e1590480a104627369bc910f2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 6"
+ date="2013-08-30T04:19:57Z"
+ content="""
+Just saw it happen again today, in a repository that passed \"fsck -A\" multiple times just yesterday. What is going on?
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_7_fe261c074211ccb94bbcb32cfd8ee654._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_7_fe261c074211ccb94bbcb32cfd8ee654._comment
new file mode 100644
index 000000000..6f3e42f5c
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_7_fe261c074211ccb94bbcb32cfd8ee654._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 7"
+ date="2013-08-30T04:25:45Z"
+ content="""
+I tried your suggestion of cloning the repository and moving `.git/config` and `.git/annex`, and got this:
+
+ fsck Astronomy/12_ATM_2.jpg error: invalid object 100644 06f8fe222f052100101e5c2e77640f2ec3efff98 for '002/0a6/SHA256E-s427690--03aeabcde841b66168b72de80098d74e047f3ffc832d4bbefa1f2f70ee6c92f8.jpg.log'
+ fatal: git-write-tree: error building trees
+ git-annex: failed to read sha from git write-tree
+
+What else can I try? Note that I can't even find this `.log` anywhere under my `.git` directory for this repository.
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_8_bc8e4dc7e0d6577ba5fcc98f56627b1f._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_8_bc8e4dc7e0d6577ba5fcc98f56627b1f._comment
new file mode 100644
index 000000000..0b82af2f1
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_8_bc8e4dc7e0d6577ba5fcc98f56627b1f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 8"
+ date="2013-08-30T04:30:14Z"
+ content="""
+The only thing that worked was nuking `.git/annex/index` and letting `git-annex sync` rebuild it.
+"""]]
diff --git a/doc/bugs/Problem_when_dropping_unused_files/comment_9_e9a22aa2ebcde5f6595b49dba9375761._comment b/doc/bugs/Problem_when_dropping_unused_files/comment_9_e9a22aa2ebcde5f6595b49dba9375761._comment
new file mode 100644
index 000000000..b75b3f61b
--- /dev/null
+++ b/doc/bugs/Problem_when_dropping_unused_files/comment_9_e9a22aa2ebcde5f6595b49dba9375761._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 9"
+ date="2013-08-30T06:20:58Z"
+ content="""
+And yet again it happens:
+
+ error: invalid object 100644 3edb1d4a44ffba1ea1491693ae7d9faa82aad717 for '000/4ce/SHA256E-s175006724--a0edc4f880223028b3fa3a27b142c8e027ddf66db973b8272ca845a4a9e01d3e.mp4.log' fatal: git-write-tree: error building trees
+
+This was in a repository that was working perfectly well until I tried to `git-annex get`. The weird thing is that I don't even have any `SHA256E` files anymore.
+
+I think that after my recent migration, none of my repositories can be trusted. This is just happening too often (more than 10 times in the last week, across many repositories on many machines). I will just rebuild them all. But I do wish git-annex was more resilient about this.
+"""]]
diff --git a/doc/bugs/Resource_exhausted.mdwn b/doc/bugs/Resource_exhausted.mdwn
index eae2ba8d3..3f125b08a 100644
--- a/doc/bugs/Resource_exhausted.mdwn
+++ b/doc/bugs/Resource_exhausted.mdwn
@@ -41,5 +41,5 @@ I'm interested in your thoughts.
Best,
Laszlo
-[[!tag /design/assistant moreinfo]]
+[[!tag /design/assistant]]
[[!meta title="assistant can try to add too many files at once in batch add mode"]]
diff --git a/doc/bugs/Resource_exhausted/comment_10_bccf9528ffe963154c92ce49762e7ea6._comment b/doc/bugs/Resource_exhausted/comment_10_bccf9528ffe963154c92ce49762e7ea6._comment
new file mode 100644
index 000000000..da2a15ba2
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_10_bccf9528ffe963154c92ce49762e7ea6._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="comment 10"
+ date="2013-08-26T18:33:40Z"
+ content="""
+@Joey: it was a \"pretty large\" transfer, several hundred gigabytes in perhaps ~100000 files. The copying was going to a GPG-encrypted directory remote.
+The error only happened once or twice so far. Point taken about find in /proc; I'll do that if it happens next time.
+
+"""]]
diff --git a/doc/bugs/Resource_exhausted/comment_5_f55d933bce77fd2185ebd0cc46fe57ec._comment b/doc/bugs/Resource_exhausted/comment_5_f55d933bce77fd2185ebd0cc46fe57ec._comment
new file mode 100644
index 000000000..19bcdb376
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_5_f55d933bce77fd2185ebd0cc46fe57ec._comment
@@ -0,0 +1,64 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="I just reproduced this with the latest version"
+ date="2013-08-11T03:17:11Z"
+ content="""
+At some point during a large copy, there's an ever increasing number of pipes in /proc/git-annex-pid/fd
+As soon as it hits the limit (1023 in my case), copies start failing
+
+ etc
+ r-x------ 1 michael michael 64 Aug 10 20:14 851 -> pipe:[2250609]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 852 -> pipe:[2251549]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 853 -> pipe:[2251550]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 854 -> pipe:[2250612]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 855 -> pipe:[2250613]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 856 -> pipe:[2246639]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 857 -> pipe:[2246640]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 858 -> pipe:[2246642]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 859 -> pipe:[2246643]
+ l-wx------ 1 michael michael 64 Aug 10 20:13 86 -> pipe:[2241378]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 860 -> pipe:[2246645]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 861 -> pipe:[2246646]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 862 -> pipe:[2246648]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 863 -> pipe:[2246649]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 864 -> pipe:[2246653]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 865 -> pipe:[2246654]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 866 -> pipe:[2249407]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 867 -> pipe:[2251789]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 868 -> pipe:[2250627]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 869 -> pipe:[2250628]
+ lr-x------ 1 michael michael 64 Aug 10 20:13 87 -> pipe:[2241379]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 870 -> pipe:[2251778]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 871 -> pipe:[2251779]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 872 -> pipe:[2251781]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 873 -> pipe:[2251782]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 874 -> pipe:[2250635]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 875 -> pipe:[2250636]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 876 -> pipe:[2251575]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 877 -> pipe:[2251576]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 878 -> pipe:[2251785]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 879 -> pipe:[2251786]
+ l-wx------ 1 michael michael 64 Aug 10 20:13 88 -> pipe:[2247853]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 880 -> pipe:[2249430]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 881 -> pipe:[2249431]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 882 -> pipe:[2251581]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 883 -> pipe:[2251582]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 884 -> pipe:[2250653]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 885 -> pipe:[2250654]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 886 -> pipe:[2251790]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 887 -> pipe:[2250670]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 888 -> pipe:[2250663]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 889 -> pipe:[2250664]
+ lr-x------ 1 michael michael 64 Aug 10 20:13 89 -> pipe:[2247854]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 890 -> pipe:[2250668]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 891 -> pipe:[2250669]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 892 -> pipe:[2250671]
+ l-wx------ 1 michael michael 64 Aug 10 20:14 894 -> pipe:[2251601]
+ lr-x------ 1 michael michael 64 Aug 10 20:14 895 -> pipe:[2251602]
+ lr-x------ 1 michael michael 64 Aug 10 20:13 9 -> pipe:[2241268]
+ lr-x------ 1 michael michael 64 Aug 10 20:13 90 -> pipe:[2242273]
+ l-wx------ 1 michael michael 64 Aug 10 20:13 91 -> pipe:[2245776]
+ etc
+
+"""]]
diff --git a/doc/bugs/Resource_exhausted/comment_6_26c98fca45b029a527f9684873db4be5._comment b/doc/bugs/Resource_exhausted/comment_6_26c98fca45b029a527f9684873db4be5._comment
new file mode 100644
index 000000000..b95b6cfa2
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_6_26c98fca45b029a527f9684873db4be5._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="comment 6"
+ date="2013-08-11T03:20:37Z"
+ content="""
+with every
+
+ git annex
+ copy blah/blah/blah (to testremote...)
+ git-annex: runInteractiveProcess: pipe: Too many open files
+ failed
+
+The number of open fd's by git-annex increases by 1.
+
+4.20130802 built with cabal on Ubuntu 13.04
+
+"""]]
diff --git a/doc/bugs/Resource_exhausted/comment_7_8bab413b472f900e04977db2bc3951b6._comment b/doc/bugs/Resource_exhausted/comment_7_8bab413b472f900e04977db2bc3951b6._comment
new file mode 100644
index 000000000..1b050aa33
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_7_8bab413b472f900e04977db2bc3951b6._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="comment 7"
+ date="2013-08-11T03:21:45Z"
+ content="""
+...increases in the failing case, that is. This doesn't happen all the time.
+"""]]
diff --git a/doc/bugs/Resource_exhausted/comment_8_e9bec0b80179b1229b6af0979a21c727._comment b/doc/bugs/Resource_exhausted/comment_8_e9bec0b80179b1229b6af0979a21c727._comment
new file mode 100644
index 000000000..2135211cd
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_8_e9bec0b80179b1229b6af0979a21c727._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="comment 8"
+ date="2013-08-11T20:44:19Z"
+ content="""
+It also looks like the location log has got corrupted (files are actually present, but not recorded in the location log) somewhere along the lines as I was trying to get/drop to figure out what's going on.
+Explicitly dropping files then getting files fixes the location log issue.
+"""]]
diff --git a/doc/bugs/Resource_exhausted/comment_9_419e24e0b91f569294ece28c42daa246._comment b/doc/bugs/Resource_exhausted/comment_9_419e24e0b91f569294ece28c42daa246._comment
new file mode 100644
index 000000000..0e06f5af9
--- /dev/null
+++ b/doc/bugs/Resource_exhausted/comment_9_419e24e0b91f569294ece28c42daa246._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 9"
+ date="2013-08-24T19:10:21Z"
+ content="""
+@Michael how large a copy are you doing? And what kind of remote are you copying the files to?
+It would be helpful if you could be more specific about something I could do to reproduce the problem. Without a test case, I am unlikely to fix the bug. With a test case, I'd be surprised if it took long to fix it.
+
+If you have a process running that is experiencing the problem, you can also narrow it down a *lot* by looking at what these leaking pipe file descriptors are pipes to. For example, if you have:
+
+lr-x------ 1 michael michael 64 Aug 10 20:14 895 -> pipe:[2251602]
+
+You can run `find /proc/ -ls 2251602` and find the process at other end of the pipe, and look its pid up in ps to see what command it is.
+"""]]
diff --git a/doc/bugs/S3_buckets_with_capital_letters_breaks_authentication.mdwn b/doc/bugs/S3_buckets_with_capital_letters_breaks_authentication.mdwn
new file mode 100644
index 000000000..9a67db0c6
--- /dev/null
+++ b/doc/bugs/S3_buckets_with_capital_letters_breaks_authentication.mdwn
@@ -0,0 +1,32 @@
+### Please describe the problem.
+
+As described in [[tips/Internet_Archive_via_S3]], there is a problem using S3 with buckets that have capital letters. The bug lies either in the hS3 library or in archive.org itself.
+
+### What steps will reproduce the problem?
+
+Try to add an [[special_remotes/S3]] remote with capital letters in the bucket name.
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format txt """
+git-annex version: 4.20130921-g434dc22
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+### 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
+anarcat@angela:video$ git annex initremote archive-moglenrepublica type=S3 host=s3.us.archive.org bucket=Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia
+initremote archive-moglenrepublica (Internet Archive mode) git-annex: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. For more information, see REST Authentication and SOAP Authentication for details.
+# End of transcript or log.
+"""]]
+
+Just thought it would be better to have a separate thread for this bug. :)
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/S3_memory_leaks/comment_1_a7268213b090bce6b1f1858a8e23d90e._comment b/doc/bugs/S3_memory_leaks/comment_1_a7268213b090bce6b1f1858a8e23d90e._comment
new file mode 100644
index 000000000..0523fd473
--- /dev/null
+++ b/doc/bugs/S3_memory_leaks/comment_1_a7268213b090bce6b1f1858a8e23d90e._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://schnouki.net/"
+ nickname="Schnouki"
+ subject="comment 1"
+ date="2013-10-18T08:36:45Z"
+ content="""
+Hi Joey,
+
+It looks like your patch hasn't been merged yet. And this bug is quite annoying for me (can't backup files bigger than 1.5 GB from my NAS).
+
+Would it be possible to include this fix in your standalone builds and Debian packages?
+
+Thanks!
+"""]]
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__.txt
new file mode 100644
index 000000000..7eaf2a71b
--- /dev/null
+++ b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__.txt
@@ -0,0 +1,46 @@
+> git annex status
+supported backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+supported remote types: git gcrypt S3 bup directory rsync web webdav glacier hook
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 8
+ 00000000-0000-0000-0000-000000000001 -- web
+ 44AF00F1-511F-4902-8235-DFF741B09400 -- here
+ 44af00f1-511f-4902-8235-dff741b09400 -- chrissy
+ 53499200-CA18-4B51-B6B3-651C18208349 -- stevedave
+ 56C56658-0995-4613-8A1B-B2FA534A834C -- olaf
+ 8FE9B19F-4FC8-4CFA-AD89-4B70EB432EDC -- passport
+ AFC75641-B34A-4644-B566-C8D3127823F7 -- glacier
+ B3238A12-D81B-40EA-BE89-3BDB318AE2B7 -- brodie
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 78.8 gigabytes (+1 gigabyte reserved)
+local annex keys: 3915
+local annex size: 81.37 gigabytes
+known annex keys: 5728
+known annex size: 641.36 gigabytes
+bloom filter size: 16 mebibytes (0.8% full)
+backend usage:
+ SHA256E: 8716
+ URL: 927
+
+> git annex version
+git-annex version: 4.20130909
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+
+> git-annex intentionally treats UUIDs as opaque strings,
+> so it is not going to go to any bother to consider
+> different byte sequences to be the same UUID, sorry.
+> (The standard may be arbitrarily complicated, but I have arbitrarily
+> decided to ignore it.)
+>
+> Since git-annex only ever generates each UUID once, and copies
+> the exact sequence of bytes as necessary, the only way the situation
+> you show above can happen is if you have manually gone in and entered
+> UUIDs in two different cases.
+>
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_1_00b52dba3bc30516e06c44cbfd3a05a2._comment b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_1_00b52dba3bc30516e06c44cbfd3a05a2._comment
new file mode 100644
index 000000000..b1417816f
--- /dev/null
+++ b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_1_00b52dba3bc30516e06c44cbfd3a05a2._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 1"
+ date="2013-09-12T09:44:54Z"
+ content="""
+There does not seem to be an actual bug description in here. Can you provide more info?
+
+To answer the actual question: RFC 4122 clearly answers no:
+
+ Each field is treated as an integer and has its value printed as a
+ zero-filled hexadecimal digit string with the most significant
+ digit first. The hexadecimal values \"a\" through \"f\" are output as
+ lower case characters and are case insensitive on input.
+
+Yes, that means that git-annex prints them wrongly as that's upper case.
+"""]]
diff --git a/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_2_8f5fa659c2ab91b1757bac31cd3b15eb._comment b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_2_8f5fa659c2ab91b1757bac31cd3b15eb._comment
new file mode 100644
index 000000000..f07a7bf9d
--- /dev/null
+++ b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_2_8f5fa659c2ab91b1757bac31cd3b15eb._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="2013-09-12T09:49:56Z"
+ content="""
+What OS are you using?
+
+versions 4.20130827 and 4.20130911 on Debian Sid print UUIDs which are lower case, as should be expected.
+"""]]
diff --git a/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_3_ccf9623d60c58d036d8bf24757e50de3._comment b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_3_ccf9623d60c58d036d8bf24757e50de3._comment
new file mode 100644
index 000000000..76f6c0742
--- /dev/null
+++ b/doc/bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/comment_3_ccf9623d60c58d036d8bf24757e50de3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmRFKwny4rArBaz-36xTcsJYqKIgdDaw5Q"
+ nickname="Andrew"
+ subject="comment 3"
+ date="2013-09-12T16:24:30Z"
+ content="""
+This is on OSX 10.8.4
+
+If you look at the remote \"chrissy\" and \"here\" they are the same uuid, but with different case.
+"""]]
diff --git a/doc/bugs/Stale_lock_files_on_Android.mdwn b/doc/bugs/Stale_lock_files_on_Android.mdwn
index 77ebc0890..b3451a153 100644
--- a/doc/bugs/Stale_lock_files_on_Android.mdwn
+++ b/doc/bugs/Stale_lock_files_on_Android.mdwn
@@ -35,3 +35,10 @@ fatal: Unable to create '/mnt/sdcard/reference/.git/index.lock': File exists.
# End of transcript or log.
"""]]
+
+> The '/mnt/sdcard/reference/.git/index.lock' lock file will now be
+> automatically dealt with. Have not done anything about the refs/remotes
+> lock files yet. --[[Joey]]
+>
+> Now the assistant deals with all stale git lock files on startup.
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Too_much_system_load_on_startup.mdwn b/doc/bugs/Too_much_system_load_on_startup.mdwn
new file mode 100644
index 000000000..fc514ca73
--- /dev/null
+++ b/doc/bugs/Too_much_system_load_on_startup.mdwn
@@ -0,0 +1,24 @@
+### Please describe the problem.
+When I log in, if git annex is monitoring a large repo, my desktop is very sluggish getting started. Git-annex causes moderate CPU load, but keeps the disk IO very busy -delaying the opening of desktop applications.
+
+### What steps will reproduce the problem?
+On Linux, with git-annex set to autostart and monitoring a folder with more than a few hundred files (I have a pdf library of a few thousand journal articles).
+
+### What version of git-annex are you using? On what operating system?
+4.20131002 Ubuntu, from Hess's PPA.
+
+### Please provide any additional information below.
+
+I solved this problem by changing the call to git-annex in /etc/xdg/autostart/git-annex.desktop from:
+
+Exec=/usr/bin/git-annex assistant --autostart
+
+to
+
+Exec=sleep 5 ionice -c 3 /usr/bin/git-annex assistant --autostart
+
+This delays the start of git-annex for 5 seconds, letting the desktop get started, and forces git-annex to yield IO to other programs -preventing it from slowing them down by forcing them to wait for disk access. Since this is a background daemon with potentially high IO usage, but no need for quick responsiveness, perhaps that would make a decent default?
+
+> Added 5 second delay to existing ionice. Provisionally [[done]],
+> although it does occur to me that the startup scan could add some delays
+> in between actions to run more as a batch job. --[[Joey]]
diff --git a/doc/bugs/Too_much_system_load_on_startup/comment_1_4470cddc0965062588acff1bc77285e9._comment b/doc/bugs/Too_much_system_load_on_startup/comment_1_4470cddc0965062588acff1bc77285e9._comment
new file mode 100644
index 000000000..31e735985
--- /dev/null
+++ b/doc/bugs/Too_much_system_load_on_startup/comment_1_4470cddc0965062588acff1bc77285e9._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-26T16:44:59Z"
+ content="""
+git-annex version 4.20131002 *already* ionices itself on startup, assuming it detects a system it can do that on. So the only relevant change you made is delaying it from starting. I have made the assistant wait 5 seconds before running the startup scan when autostarted.
+"""]]
diff --git a/doc/bugs/Transfers_continue_after_daemon_stopped.mdwn b/doc/bugs/Transfers_continue_after_daemon_stopped.mdwn
new file mode 100644
index 000000000..0d9b4f648
--- /dev/null
+++ b/doc/bugs/Transfers_continue_after_daemon_stopped.mdwn
@@ -0,0 +1,5 @@
+After creating a new pairing, I stopped the daemon through the webapp while it was syncing. The webapp shut down and was no longer accessible, but git-annex continued running in the background, along with git-annex-shell, and they continued to run new transfers with new rsync processes. This continued until I killed them all.
+
+I expected that when I stopped the daemon in the webapp, all git-annex processes and all transfers would stop.
+
+Using the 20131101 tarball.
diff --git a/doc/bugs/Transfers_continue_after_daemon_stopped/comment_1_39eb527d64367e6762281246f1d49b1f._comment b/doc/bugs/Transfers_continue_after_daemon_stopped/comment_1_39eb527d64367e6762281246f1d49b1f._comment
new file mode 100644
index 000000000..9d504f743
--- /dev/null
+++ b/doc/bugs/Transfers_continue_after_daemon_stopped/comment_1_39eb527d64367e6762281246f1d49b1f._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-05T16:01:14Z"
+ content="""
+I've checked, and shutting down the daemon does cause it to stop any transfers it is running.
+
+However, this does not stop other transfers initiated by the other paired computer.
+
+I'm ambivilant about whether local pairing should only allow transfers when both daemons are running.
+"""]]
diff --git a/doc/bugs/Unable_to_import_feed.mdwn b/doc/bugs/Unable_to_import_feed.mdwn
new file mode 100644
index 000000000..49dc21bfe
--- /dev/null
+++ b/doc/bugs/Unable_to_import_feed.mdwn
@@ -0,0 +1,27 @@
+Using `git-annex version: 4.20130802` on Debian unstable, when trying to add the feed at <http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml>, I get:
+
+[[!format sh """
+importfeed http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml
+--2013-08-16 09:14:13-- http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml
+Auflösen des Hostnamen »www.ndr.de (www.ndr.de)«... 212.201.100.171, 212.201.100.187
+Verbindungsaufbau zu www.ndr.de (www.ndr.de)|212.201.100.171|:80... verbunden.
+HTTP-Anforderung gesendet, warte auf Antwort... 200 OK
+Länge: 61809 (60K) [application/xml]
+In »»/tmp/feed4404«« speichern.
+
+100%[============================================>] 61.809 --.-K/s in 0,03s
+
+2013-08-16 09:14:13 (2,20 MB/s) - »»/tmp/feed4404«« gespeichert [61809/61809]
+
+failed
+git-annex: importfeed: 1 failed
+"""]]
+
+(Oh, and using `format` with nono-ASCII seems to break down., at least in the preview.)
+
+> I'm going to close this since I've narrowed it down to a bug in the
+> upstream feed library. [[done]]. Of course, if we get a lot of reports of
+> the library not working, I may need to revisit using it, but for now this
+> seems an isolated problem. Also, I tried validating the feed, and it is
+> not 100% valid, and one of the validity problems is a missing enclosure
+> length. --[[Joey]]
diff --git a/doc/bugs/Unable_to_import_feed/comment_1_16230fbbb996e165b84787ed4d5f72ea._comment b/doc/bugs/Unable_to_import_feed/comment_1_16230fbbb996e165b84787ed4d5f72ea._comment
new file mode 100644
index 000000000..7c9c1e129
--- /dev/null
+++ b/doc/bugs/Unable_to_import_feed/comment_1_16230fbbb996e165b84787ed4d5f72ea._comment
@@ -0,0 +1,45 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-23T18:09:27Z"
+ content="""
+When I try this, without the German translation, I get:
+
+<pre>
+joey@gnu:~/tmp/newrepo>git annex importfeed 'http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml'
+(checking known urls...)
+importfeed http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml
+--2013-08-23 13:58:19-- http://www.ndr.de/fernsehen/sendungen/extra_3/videos/zum_mitnehmen/extradrei196_version-hq.xml
+Resolving www.ndr.de (www.ndr.de)... 23.73.180.154, 23.73.180.115
+Connecting to www.ndr.de (www.ndr.de)|23.73.180.154|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 61865 (60K) [application/xml]
+Saving to: ‘/home/joey/tmp/feed31120’
+
+100%[======================================>] 61,865 151KB/s in 0.4s
+
+2013-08-23 13:58:25 (151 KB/s) - ‘/home/joey/tmp/feed31120’ saved [61865/61865]
+
+
+ warning: bad feed content
+</pre>
+
+It seems you left out the last line of the error.
+
+The feed library seems to fail to find any of the enclosures in this feed, although it is able to parse it as far as finding the individual items in the feed:
+
+<pre>
+Prelude Text.Feed.Query Text.Feed.Import> f <- parseFeedFromFile \"extradrei196_version-hq.xml\"
+Prelude Text.Feed.Query Text.Feed.Import> map getItemEnclosure $ feedItems f
+[Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing]
+</pre>
+
+The feed *appears* to contain enclosures, for example:
+
+<pre>
+<enclosure url=\"http://media.ndr.de/progressive/2013/0821/TV-20130821-2329-5942.hq.mp4\" type=\"video/mp4\"/>
+</pre>
+
+It may not be well-formed, or the feed library may have a bug. Assuming the latter, I have filed a bug report on the feed library: https://github.com/sof/feed/issues/3
+"""]]
diff --git a/doc/bugs/Unable_to_use_remotes_with_space_in_the_path.mdwn b/doc/bugs/Unable_to_use_remotes_with_space_in_the_path.mdwn
new file mode 100644
index 000000000..6bb6c0782
--- /dev/null
+++ b/doc/bugs/Unable_to_use_remotes_with_space_in_the_path.mdwn
@@ -0,0 +1,35 @@
+### Please describe the problem.
+
+Git annex can't use remotes with the type "file://" if the path contains spaces
+
+### What steps will reproduce the problem?
+
+- Create one repository with a space in the path (and initialize annex in it)
+- Clone that repo to an other directory (and initialize annex also in that)
+- add a file to the first repository in the annex way
+- chdir to the second repository and try to get that file, it won't work (also after git pull or git sync pull)
+
+Check this typescripts for a more detailed description
+
+<http://uz.sns.it/~enrico/git-annex-bugreport.txt>
+
+<http://pastebin.com/f8wkDNrG> (thanks mhameed for that data)
+
+
+### What version of git-annex are you using? On what operating system?
+
+I'm using debian testing (jessie) on a i386 machine.
+
+`git-annex` version: 4.20130521 (according to apt data and `git annex version`)
+
+`git-annex` build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+
+`git` version: 1.7.10.4
+
+
+### Please provide any additional information below.
+
+I don't use git annex assistant nor the webapp
+
+> Tested and only file:// and not other urls have this problem.
+> guilhem provided a fix. [[done]] --[[Joey]]
diff --git a/doc/bugs/Unfortunate_interaction_with_Calibre/comment_5_fc4d5301797589e92cc9a24697b2155d._comment b/doc/bugs/Unfortunate_interaction_with_Calibre/comment_5_fc4d5301797589e92cc9a24697b2155d._comment
new file mode 100644
index 000000000..a54d53c58
--- /dev/null
+++ b/doc/bugs/Unfortunate_interaction_with_Calibre/comment_5_fc4d5301797589e92cc9a24697b2155d._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://lot-of-stuff.info/"
+ nickname="__DL__"
+ subject="Another solution."
+ date="2013-08-13T16:39:17Z"
+ content="""
+calibre store all the metadata for safekeeping of the metadata
+(author, title...).
+
+If like me you do not like much direct mode (because of its not so
+cool interaction with plain git), you could use the largfiles config
+to let those files in plain git. You will then also need something for
+the database. See [[tips/Git_annex_and_Calibre]] for a full solution.
+
+"""]]
diff --git a/doc/bugs/Unknown_command___39__list__39__.mdwn b/doc/bugs/Unknown_command___39__list__39__.mdwn
new file mode 100644
index 000000000..f08fc6eef
--- /dev/null
+++ b/doc/bugs/Unknown_command___39__list__39__.mdwn
@@ -0,0 +1,15 @@
+### Please describe the problem.
+
+The man page claims there exists a query command 'list' but:
+
+ % git annex list somefile
+ git-annex: Unknown command 'list'
+
+### What version of git-annex are you using? On what operating system?
+
+man page online and git-annex version 4.20130909.
+
+> Your last line explains the problem. The online man page
+> documents the latest release, or in some cases
+> unrelased git version. You have a version 2 releases old installed.
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/Unknown_command___39__list__39__/comment_1_c625d03d1ed2019141ac9202f933466d._comment b/doc/bugs/Unknown_command___39__list__39__/comment_1_c625d03d1ed2019141ac9202f933466d._comment
new file mode 100644
index 000000000..7566dc1ef
--- /dev/null
+++ b/doc/bugs/Unknown_command___39__list__39__/comment_1_c625d03d1ed2019141ac9202f933466d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="News page stopped listing latest releases?"
+ date="2013-09-30T16:08:18Z"
+ content="""
+Ah, cabal tells me that 4.20130927 is out now. I missed that because I thought that the [News](http://git-annex.branchable.com/news/) page is 'authoritative' :-) and it's still advertising 4.20130909. Sorry about that.
+"""]]
diff --git a/doc/bugs/Unknown_command___39__list__39__/comment_2_800e1b6417768bdadda311ebfb5df637._comment b/doc/bugs/Unknown_command___39__list__39__/comment_2_800e1b6417768bdadda311ebfb5df637._comment
new file mode 100644
index 000000000..f8592b571
--- /dev/null
+++ b/doc/bugs/Unknown_command___39__list__39__/comment_2_800e1b6417768bdadda311ebfb5df637._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 2"
+ date="2013-09-30T16:23:31Z"
+ content="""
+I've had a bit of a mess with cabal. First my release scripts apparently broke and didn't upload the last 2 releases there. Then when I manually fixed that, hackage has been upgraded to a new version, which is broken and will not accept tarballs > 1 mb. So I had to re-upload git-annex hacked to fit in 1 mb (removing all documentation), and I did so from a current git snapshot. Meh.
+"""]]
diff --git a/doc/bugs/Unknown_command___39__list__39__/comment_3_35dfc75ce9efffff139f8929dc311e29._comment b/doc/bugs/Unknown_command___39__list__39__/comment_3_35dfc75ce9efffff139f8929dc311e29._comment
new file mode 100644
index 000000000..1899029ad
--- /dev/null
+++ b/doc/bugs/Unknown_command___39__list__39__/comment_3_35dfc75ce9efffff139f8929dc311e29._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="comment 3"
+ date="2013-10-04T11:17:42Z"
+ content="""
+Ah, I could have sworn that I also tried to update via cabal but didn't see a new version and this explains why...
+
+Your release script might also have a problem with updating the [[News]] page...
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers.mdwn b/doc/bugs/Unnecessary_remote_transfers.mdwn
new file mode 100644
index 000000000..9ae23e5a0
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers.mdwn
@@ -0,0 +1,24 @@
+### Please describe the problem.
+This is related to [[http://git-annex.branchable.com/bugs/assistant_does_not_always_use_repo_cost_info_when_queueing_downloads/]]
+
+### What steps will reproduce the problem?
+1. Make a client repo on two machines on the local network.
+2. Pair them.
+3. Make a remote transfer repo.
+4. Set up Jabber on both local machines.
+5. Put a large file into the annex on one of the local machines.
+6. Watch as the source client repo copies the file directly to the local paired machine, but also copies it to the remote transfer repo.
+7. Wait for the local paired transfer to finish.
+8. Manually disable syncing to the remote transfer repo.
+9. Manually reenable it.
+10. Watch as the remote transfer is not resumed.
+
+### What version of git-annex are you using? On what operating system?
+Using the 1 Nov Linux tarball, Ubuntu Raring.
+
+### Please provide any additional information below.
+This is a problem because unless I manually disable the remote repo, it will continue uploading the large file until it finishes, which uses the limited upstream bandwidth on my Internet connection--and this could take hours depending on the size of the file.
+
+The remote transfer wasn't even necessary to begin with, because it already had a direct connection to the local paired repo. But even so, it should at least abort the remote transfer when the local transfer finishes.
+
+Thanks for your work on git-annex assistant.
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_10_b778fbb1386f0f51bf057ffacd590ebb._comment b/doc/bugs/Unnecessary_remote_transfers/comment_10_b778fbb1386f0f51bf057ffacd590ebb._comment
new file mode 100644
index 000000000..8c985243a
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_10_b778fbb1386f0f51bf057ffacd590ebb._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 10"
+ date="2013-11-03T02:19:04Z"
+ content="""
+Thanks, Joey. I didn't realize that there were two instances of the assistant running.
+
+Forgive my ignorance, but if I disable the assistant running in the backup repo, will the other assistant still backup files to it?
+
+Also, from a UI perspective, does the webapp currently not seem to support secondary internal drives, at least in a useful way?
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_11_55430eac842d0a192dc7f41d7730e4d5._comment b/doc/bugs/Unnecessary_remote_transfers/comment_11_55430eac842d0a192dc7f41d7730e4d5._comment
new file mode 100644
index 000000000..808c5bca6
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_11_55430eac842d0a192dc7f41d7730e4d5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 11"
+ date="2013-11-03T02:32:47Z"
+ content="""
+Yes, either of the assistants will still back up files to it, as long as they have it configured as a git remote. The same way that your transfer repository is (probably) not running the git-annex assistant.
+
+It does sound like using the removable drive UI would have saved you some trouble. I'm not sure why the webapp would not list a llvm device as a removable drive -- from inspecting the code, it seems like it would not be filtered out, as long as /proc/mounts shows the decive as /dev/something (I don't have a llvm device handy to check what it looks like).
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_1_00c18e07678dc513a02d974fe059df73._comment b/doc/bugs/Unnecessary_remote_transfers/comment_1_00c18e07678dc513a02d974fe059df73._comment
new file mode 100644
index 000000000..7baa58489
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_1_00c18e07678dc513a02d974fe059df73._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-02T19:54:44Z"
+ content="""
+In what order does the webapp list your repositories?
+
+When a new file appears, it will always go through the list of repositories in order, and try to transfer the file to each in turn, unless the configuration indicates it shouldn't. So, if the remote transfer repo is listed before the local repo, it will first upload the file to the transfer repo, and then upload it to the local repo. (And then later on, remove it from the transfer repo, since the file has reached all clients, probably.) OTOH, if the local repo comes first, it will upload the file to it over the LAN, and then when it comes to the transfer repo, if the file has successfully been sent to all clients, the transfer repo will no longer want it, and so no expensive upload is done over the internet.
+
+You can re-order the repository list in the webapp by dragging them up and down. It should default to having your locally paired repos first, unless you've changed it. If you think it came up with the wrong order, paste in your .git/config before you re-order the repositories..
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_2_2e9992dbfceabd6df535a2770626de16._comment b/doc/bugs/Unnecessary_remote_transfers/comment_2_2e9992dbfceabd6df535a2770626de16._comment
new file mode 100644
index 000000000..cc0cb067e
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_2_2e9992dbfceabd6df535a2770626de16._comment
@@ -0,0 +1,35 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-11-02T22:48:18Z"
+ content="""
+The webapp has the remote repo at the bottom of the list. But here's .git/config. It has a high repo cost for the local paired repo, and no cost listed for the remote one:
+
+[[!format sh \"\"\"
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[annex]
+ uuid = 946f9095-588b-4421-b66a-4a1e5632ff6b
+ version = 3
+ direct = true
+ diskreserve = 1 megabyte
+ numcopies = 1
+ debug = false
+[gc]
+ auto = 0
+[remote \"Onyx\"]
+ url = ssh://me@git-annex-Onyx.local-me_annex/~/annex/
+ annex-uuid = 80709bc2-3cbe-434b-b7b9-306278b9a4e9
+ annex-cost = 125.0
+ fetch = +refs/heads/*:refs/remotes/Onyx/*
+[remote \"Remote\"]
+ annex-rsyncurl = username@git-annex-example.net-username_annex:annex/
+ annex-uuid = 33930bae-63d2-4a52-b330-58872aaeb1bf
+ fetch =
+ annex-sync = true
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_3_a98f3091a6a658919f0562cf396439c2._comment b/doc/bugs/Unnecessary_remote_transfers/comment_3_a98f3091a6a658919f0562cf396439c2._comment
new file mode 100644
index 000000000..b6900f339
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_3_a98f3091a6a658919f0562cf396439c2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 3"
+ date="2013-11-02T22:59:18Z"
+ content="""
+Also, I just realized that it's uploading two large files to my remote transfer repo, even though I already have both files in my local paired repo on both systems; i.e. there's no need to send it to the transfer repo at all. And it was yesterday when the two files were transferred. So I have no idea why today it thinks it needs to upload them to the transfer repo. :/
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_4_417c1e8e27ee1a1f9ebf9160560605c5._comment b/doc/bugs/Unnecessary_remote_transfers/comment_4_417c1e8e27ee1a1f9ebf9160560605c5._comment
new file mode 100644
index 000000000..b0d4c1146
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_4_417c1e8e27ee1a1f9ebf9160560605c5._comment
@@ -0,0 +1,96 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Super confused"
+ date="2013-11-02T23:30:41Z"
+ content="""
+I think now I'm double- or triple-confused. Here is me@desktop:~/annex/.git/config:
+
+[[!format sh \"\"\"
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[annex]
+ uuid = 80709bc2-3cbe-434b-b7b9-306278b9a4e9
+ version = 3
+ direct = true
+ fscknudge = true
+[gc]
+ auto = 0
+[remote \"laptop\"]
+ url = ssh://me@git-annex-laptop-me_annex/~/annex/
+ annex-uuid = 946f9095-588b-4421-b66a-4a1e5632ff6b
+ annex-cost = 175.0
+ fetch = +refs/heads/*:refs/remotes/laptop/*
+[remote \"Remote\"]
+ annex-rsyncurl = username@example.net:annex/
+ annex-uuid = 33930bae-63d2-4a52-b330-58872aaeb1bf
+ fetch =
+ annex-sync = false
+[remote \"backupOndesktop\"]
+ url = /mnt/debian/home/me/annex-backup
+ annex-uuid = 86535965-6ca7-4bf3-89af-bca3a07f96f9
+ fetch = +refs/heads/*:refs/remotes/backupOndesktop/*
+\"\"\"]]
+
+What I have set up (or intended to set up) is:
+
+* Client: me@laptop:~/annex
+* Client: me@desktop:~/annex
+* Transfer: username@example.net:~/annex
+* Full Backup: me@desktop:/mnt/debian/home/me/annex-backup
+
+What I expected was that:
+
+1. The two Client repos would sync directly over the LAN whenever possible.
+2. The transfer repo would be used only to sync the laptop and desktop, and then only if my laptop were not on the LAN with my desktop.
+3. The Full Backup repo would be synced directly with the me@desktop Client repo, within the same system, from one hard disk to the other.
+
+But what I'm seeing is...not quite that.
+
+1. It's very confusing (to me, at least) that on my desktop system I can look at my annex setup from the \"perspective\" of both local repos. When I \"switch\" to the other repo, the setup looks different: even the same repos can have different names and descriptions, and can be enabled and disabled independently depending on the \"perspective\"...but their Type is still the same.
+
+2. Looking from the \"perspective\" of the Full Backup repo, I'm seeing files being transferred to the Transfer repo, even though those files are already present in both Client repos, and even though the webapp says that the Full Backup repo has been synced. When I disable and reenable the Transfer repo, it starts those transfers over again, even though they aren't necessary. For example, here is the log from disabling and reenabling the Transfer repo from the \"perspective\" of the Full Backup repo:
+
+[[!format sh \"\"\"
+[2013-11-02 18:24:35 CDT] main: Syncing with example.net_annex
+(gpg)
+gpg: Terminated caught ... exiting
+[2013-11-02 18:24:49 CDT] call: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"config\",\"remote.example.net_annex.annex-sync\",\"true\"]
+[2013-11-02 18:24:49 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:49 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:49 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:49 CDT] main: Syncing with example.net_annex
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"symbolic-ref\",\"HEAD\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"refs/heads/master\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"git-annex\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"log\",\"refs/heads/git-annex..2c42d607c099b6ec4a20603b809f44d161e42489\",\"--oneline\",\"-n1\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"symbolic-ref\",\"HEAD\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"refs/heads/master\"]
+[2013-11-02 18:24:49 CDT] TransferScanner: starting scan of [Remote { name =\"example.net_annex\" }]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"ls-files\",\"--cached\",\"-z\",\"--\"]
+[2013-11-02 18:24:49 CDT] TransferScanner: queued Upload UUID \"33930bae-63d2-4a52-b330-58872aaeb1bf\" video.flv Nothing : expensive scan found missing object
+[2013-11-02 18:24:49 CDT] Transferrer: Transferring: Upload UUID \"33930bae-63d2-4a52-b330-58872aaeb1bf\" video.flv Nothing
+[2013-11-02 18:24:49 CDT] TransferScanner: queued Upload UUID \"33930bae-63d2-4a52-b330-58872aaeb1bf\" image.jpg Nothing : expensive scan found missing object
+[2013-11-02 18:24:49 CDT] call: /home/me/.bin/git-annex.linux/git-annex [\"transferkeys\",\"--readfd\",\"35\",\"--writefd\",\"34\"]
+[2013-11-02 18:24:49 CDT] TransferScanner: queued Upload UUID \"33930bae-63d2-4a52-b330-58872aaeb1bf\" linux-image-3.8.0-29-generic_3.8.0-29.42_i386.deb Nothing : expensive scan found missing object
+[2013-11-02 18:24:49 CDT] TransferScanner: finished scan of [Remote { name =\"example.net_annex\" }]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"git-annex\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+[2013-11-02 18:24:49 CDT] read: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"log\",\"refs/heads/git-annex..2c42d607c099b6ec4a20603b809f44d161e42489\",\"--oneline\",\"-n1\"]
+[2013-11-02 18:24:49 CDT] chat: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"cat-file\",\"--batch\"]
+[2013-11-02 18:24:49 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:49 CDT] TransferWatcher: transfer starting: Upload UUID \"33930bae-63d2-4a52-b330-58872aaeb1bf\" video.flv Nothing
+(gpg) [2013-11-02 18:24:49 CDT] chat: gpg [\"--batch\",\"--no-tty\",\"--use-agent\",\"--quiet\",\"--trust-model\",\"always\",\"--batch\",\"--passphrase-fd\",\"20\",\"--symmetric\",\"--force-mdc\",\"--no-textmode\"]
+[2013-11-02 18:24:50 CDT] call: git [\"--git-dir=/mnt/debian/home/me/annex-backup/.git\",\"--work-tree=/mnt/debian/home/me/annex-backup\",\"config\",\"remote.example.net_annex.annex-sync\",\"false\"]
+[2013-11-02 18:24:50 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:50 CDT] read: git [\"config\",\"--null\",\"--list\"]
+[2013-11-02 18:24:50 CDT] read: git [\"config\",\"--null\",\"--list\"]
+
+gpg: Terminated caught ... exiting\"\"\"]]
+
+I have no idea why it's doing that, because all three of those files are already in both Client repos and the Full Backup repo.
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_5_eb5a2717a1f0c7bb761d2a7866b23def._comment b/doc/bugs/Unnecessary_remote_transfers/comment_5_eb5a2717a1f0c7bb761d2a7866b23def._comment
new file mode 100644
index 000000000..0e2ec4ec8
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_5_eb5a2717a1f0c7bb761d2a7866b23def._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Deleting repos from different perspectives"
+ date="2013-11-02T23:33:48Z"
+ content="""
+One other thing, sorry, but I think this is important: From the perspective of the Full Backup repo, I set the Transfer repo to be deleted, thinking that would prevent the desktop's Client and Full Backup repos from syncing through the Transfer repo. But then when I switch to the perspective of the desktop's Client repo, it is \"cleaning out\" the Transfer repo--but I wanted the Transfer repo to be used for syncing the two Client repos! So I set it back to Transfer instead of Unwanted...but then when I switch back to the Full Backup perspective, the Transfer repo is no longer Unwanted.
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_6_89f756db1f3f2e60a3bd1f35f55fee43._comment b/doc/bugs/Unnecessary_remote_transfers/comment_6_89f756db1f3f2e60a3bd1f35f55fee43._comment
new file mode 100644
index 000000000..509cc3f3f
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_6_89f756db1f3f2e60a3bd1f35f55fee43._comment
@@ -0,0 +1,40 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="config from backup repo"
+ date="2013-11-03T00:20:11Z"
+ content="""
+Sorry for posting over and over again, just trying to provide info when I discover it.
+
+Here's **/mnt/debian/home/me/annex-backup/.git/config**
+
+[[!format sh \"\"\"
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[annex]
+ uuid = 86535965-6ca7-4bf3-89af-bca3a07f96f9
+ version = 3
+ direct = true
+ fscknudge = true
+ diskreserve = 100 megabyte
+ numcopies = 1
+ debug = false
+[gc]
+ auto = 0
+[remote \"desktop\"]
+ url = /home/me/annex
+ fetch = +refs/heads/*:refs/remotes/desktop/*
+ annex-uuid = 80709bc2-3cbe-434b-b7b9-306278b9a4e9
+[remote \"Remote\"]
+ annex-rsyncurl = username@example.net:annex/
+ annex-uuid = 33930bae-63d2-4a52-b330-58872aaeb1bf
+ annex-sync = false
+ fetch =\"\"\"]]
+
+1. Should I remove the \"Remote\" Transfer repo from this config file to prevent it from using the Transfer repo? I only want this repo to sync directly with the other internal hard disk.
+
+2. Is it correct for git-annex to add this Transfer repo to this config file in the first place?
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_7_5aaf8766a7ba05c4f92715e5d5175a8f._comment b/doc/bugs/Unnecessary_remote_transfers/comment_7_5aaf8766a7ba05c4f92715e5d5175a8f._comment
new file mode 100644
index 000000000..f117f15c1
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_7_5aaf8766a7ba05c4f92715e5d5175a8f._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 7"
+ date="2013-11-03T00:45:09Z"
+ content="""
+* The costs you show look fine.
+* Yes, deleting a repository in the webapp actually deletes it. It doesn't just remove the remote from .git/config. Most people using the webapp don't want to draw such a fine distinction, I think.
+* It's not a very usual configuration to have 2 repositories on the same machine with the git-annex assistant running in both. You might just want to configure the assistant to not run in the backup repository.
+
+Some of the things you've said suggest that the backup repository might not be immediately noticing when changes are pushed to it. Since its location is shown as /mnt/debian/home/me, I have to wonder if that's some NFS mount or other network filesystem causing problems.
+
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_8_e856b350632cc865d16d1995a6cdf065._comment b/doc/bugs/Unnecessary_remote_transfers/comment_8_e856b350632cc865d16d1995a6cdf065._comment
new file mode 100644
index 000000000..1177205e3
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_8_e856b350632cc865d16d1995a6cdf065._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 8"
+ date="2013-11-03T01:07:31Z"
+ content="""
+> It's not a very usual configuration to have 2 repositories on the same machine with the git-annex assistant running in both. You might just want to configure the assistant to not run in the backup repository.
+
+Maybe that's the crux of the problem. But I'm not sure what I did wrong to make that happen. I have a second internal hard disk in my desktop system, and I wanted to put a Full Backup repo on it. I tried to add a \"Removable drive\" repo (since I sometimes unplug it to swap cables with a DVD drive), but since the assistant didn't detect any actual removable drives, that didn't work. So I used \"Add another repository\" and set it to a Full Backup repo. Is that the wrong way to do it? :)
+
+> Some of the things you've said suggest that the backup repository might not be immediately noticing when changes are pushed to it. Since its location is shown as /mnt/debian/home/me, I have to wonder if that's some NFS mount or other network filesystem causing problems.
+
+/mnt/debian is /dev/mapper/lvm-root, another internal disk. The disk is working fine. :)
+"""]]
diff --git a/doc/bugs/Unnecessary_remote_transfers/comment_9_64f831545b34b78452952cf49b5f5b05._comment b/doc/bugs/Unnecessary_remote_transfers/comment_9_64f831545b34b78452952cf49b5f5b05._comment
new file mode 100644
index 000000000..03127c4ad
--- /dev/null
+++ b/doc/bugs/Unnecessary_remote_transfers/comment_9_64f831545b34b78452952cf49b5f5b05._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 9"
+ date="2013-11-03T01:52:56Z"
+ content="""
+Ok, since we don't have NFS craziness, I'm going to put theories about it not noticing incoming syncs on hold. (I think I probably misunderstood [this comment](http://git-annex.branchable.com/bugs/Unnecessary_remote_transfers/#comment-39490c318620c141e7557b7bcba0e5c8) and anyway the assistant has some throttling so won't always immediately load config changes that have been synced to it if some other config changes were loaded a minute before.)
+
+I think this behavior can probably be explained without resorting to any bugs, now that I have, I think, a full picture of the repository network:
+
+<pre>
+laptop <-> desktop <-> backup
+ | | |
+ v v v
+ transfer (cloud)
+</pre>
+
+Now when a file is added to desktop, it immediately copies it to backup, which is on the same machine, so that happens quite quickly. Then it starts sending it across the LAN to laptop.
+
+Meanwhile, the assistant daemon running on backup wakes up, notices it's just received an object, and sees that this object is currently located on only desktop and backup, but not yet on laptop or transfer. Which means that it should send the object to transfer, from which it will eventually reach laptop.
+
+The only ways I can think of to avoid such an unnecessary transfer would be a) for desktop could somehow tell backup that it's in the process of sending the file to laptop or b) for a map of current state of the network to be constructed and maintained and analyzed automatically, so it it could conclude backup does not need to send files to transfer if they're already present on desktop. There is some discussion about this in [[design/assistant/syncing]]. Hard problem in general I think, although slightly less hard in this specific case since desktop and backup know they're in the same machine.
+
+But it should be easy to configure it so this doesn't happen. Just make backup not have the transfer repository configured as a remote (or just pause it syncing to there in the webapp). Or, don't run the assistant at all on backup (see `~/.config/git-annex/autostart`).
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key.mdwn b/doc/bugs/Using_a_revoked_GPG_key.mdwn
new file mode 100644
index 000000000..4e522ab78
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key.mdwn
@@ -0,0 +1,34 @@
+### Please describe the problem.
+git-annex refuses to use revoked GPG keys. This may be understandable for the initial remote setup, but it hit me when I tried to add a new key to a remote. The previous key has been revoked (because it has been superseded by the new one), and git-annex refused to reinvoke the shared key with both keys because one of them was revoked.
+
+Given the encryption model does not allow key replacement, it should not refuse to reencrypt using a revoked key. Maybe using `--expert` would help.
+
+### What steps will reproduce the problem?
+Encrypt a special remote with a key K1. Revoke key K1. Try to add key K2 with enableremote. git-annex will refuse to encrypt the shared key with the revoked one.
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20130802-g1452ac3
+
+### Please provide any additional information below.
+
+[[!format sh """
+% git annex enableremote zoidberg-crypted encryption=42B8F7C2
+enableremote zoidberg-crypted (encryption update)
+You need a passphrase to unlock the secret key for
+user: "Samuel Tardieu <sam@rfc1149.net>"
+2048-bit ELG key, ID F0D70BAF, created 2002-05-31 (main key ID 1B80ADE6)
+
+gpg: NOTE: key has been revoked
+gpg: reason for revocation: Key is superseded
+gpg: revocation comment: Key superseded by 42B8F7C2
+gpg: revocation comment: (fingerprint 1D36 D924 8B33 DCAB 7BA5 BA44 7A30 BCF4 42B8 F7C2)
+gpg: F13322411B80ADE6: skipped: Unusable public key
+gpg: [stdin]: encryption failed: Unusable public key
+
+git-annex: user error (gpg ["--quiet","--trust-model","always","--encrypt","--no-encrypt-to","--no-default-recipient","--recipient","7A30BCF442B8F7C2","--recipient","F13322411B80ADE6"] exited 2)
+failed
+git-annex: enableremote: 1 failed
+"""]]
+
+> [[done]]; can now use: `git annex enableremote foo keyid-=REVOKEDKEY
+> keyid+=NEWKEY` to remove it, and add a new key. --[[Joey]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_1_7bb01d081282e5b02b7720b2953fe5be._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_1_7bb01d081282e5b02b7720b2953fe5be._comment
new file mode 100644
index 000000000..baddbbf49
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_1_7bb01d081282e5b02b7720b2953fe5be._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWg4VvDTer9f49Y3z-R0AH16P4d1ygotA"
+ nickname="Tobias"
+ subject="comment 1"
+ date="2013-08-12T11:47:28Z"
+ content="""
+I'd be very unhappy indeed if I couldn't revoke access to my annex.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_2_9c0c40360f0058a4bd346c1362e302b6._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_2_9c0c40360f0058a4bd346c1362e302b6._comment
new file mode 100644
index 000000000..003f9a34a
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_2_9c0c40360f0058a4bd346c1362e302b6._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://www.rfc1149.net/"
+ nickname="Sam"
+ subject="comment 2"
+ date="2013-08-13T07:28:30Z"
+ content="""
+Tobias: I don't understand what you mean. The issue here is that once an existing key is revoked, git-annex will refuse to add *another non-revoked* key.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_3_8f69f58107246595f5603f35c4aa7395._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_3_8f69f58107246595f5603f35c4aa7395._comment
new file mode 100644
index 000000000..7f18cfe39
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_3_8f69f58107246595f5603f35c4aa7395._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWg4VvDTer9f49Y3z-R0AH16P4d1ygotA"
+ nickname="Tobias"
+ subject="comment 3"
+ date="2013-08-13T08:47:45Z"
+ content="""
+Ah, sorry, i'm uncomprehending :)
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_4_78b3c52ba85edfa6ee6e273bec3bea5c._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_4_78b3c52ba85edfa6ee6e273bec3bea5c._comment
new file mode 100644
index 000000000..61b03c109
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_4_78b3c52ba85edfa6ee6e273bec3bea5c._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 4"
+ date="2013-08-16T07:14:12Z"
+ content="""
+The [[OpenPGP standard|https://tools.ietf.org/html/rfc4880]] specifies that revoked keys/subkeys \"are not to be used\". AFIK GnuPG, as any RFC-compliant implementation, will not let you encrypt to a revoked key no matter what. An extremely dirty workaround is to set up your system clock prior to the revocation date (but that might put your whole system at risk since other applications may rely synced clocks to work properly).
+
+That said, what you really wanted to do was to revoke access to K1 and add K2 instead. That seems to be a perfectly valid use-case, and it shouldn't be hard to add to git-annex; stay tunned ;-)
+
+
+Tobias: Not sure what you meant by \"revoke access to my annex\", but if you were thinking of the key owner, note that with the current [[encryption design|http://git-annex.branchable.com/design/encryption]], since that person may simply grab from the git repo and then at any time decrypt the passphrase for the symmetric cipher, it makes little sense to revoke access for that person unless you change that passphrase, and reencrypt all annexed files on the remote, which of course needs to be done locally for the encryption to make sense at all.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_5_a85ccf2f09ebe87147f8761b81a02326._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_5_a85ccf2f09ebe87147f8761b81a02326._comment
new file mode 100644
index 000000000..ff441671f
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_5_a85ccf2f09ebe87147f8761b81a02326._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://www.rfc1149.net/"
+ nickname="Sam"
+ subject="comment 5"
+ date="2013-08-19T11:35:52Z"
+ content="""
+Indeed, removing the revoked key and putting the new one would be acceptable, there is no reason to keep the revoked one around.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_6_8b89eb5e6386acd0a922310c04f863ac._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_6_8b89eb5e6386acd0a922310c04f863ac._comment
new file mode 100644
index 000000000..eb9cd0f54
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_6_8b89eb5e6386acd0a922310c04f863ac._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 6"
+ date="2013-08-19T13:22:59Z"
+ content="""
+All right, what would be a nice user interface, compatible with the current commands? I was thinking of something along the lines of `git annex enableremote +encryption=newKey -encryption=oldKey`, with an alias `+encryption=encryption` to be backward compatible. It's probably not optimal though, feel free to comment :-)
+
+Of course, `git-annex` should ensure that at any point in time the passphrase is always encrypted using an OpenPGP key. (Otherwise it might be stored clear in the git repository, which would void the encryption.) Also, anyone who can decrypt the passphrase can revoke all existing keys and reencrypt it using another key; this not really a big deal since the cipher is version-controlled anyway, so loosing access to the repo is unlikely.
+
+By the way, since we're about to amend the arguments for `enableremote`, it'd be nice to take advantage of the situation to allow pure asymmetric encryption. I propose `git annex initremote ... encryption=myKey crypto={none,hybrid,pubkey}` to use respectively no-encryption, an asymmetrically encrypted passphrase (the current design, default), and OpenPGP keys only.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_7_20dc5a7ce7cb6ca97ccdfb923c3b24bb._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_7_20dc5a7ce7cb6ca97ccdfb923c3b24bb._comment
new file mode 100644
index 000000000..02be72e36
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_7_20dc5a7ce7cb6ca97ccdfb923c3b24bb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 7"
+ date="2013-08-19T16:08:49Z"
+ content="""
+On second thought, I think it makes more sense to have something like `git annex initremote ... encryption={none,shared,hybrid,pubkey} keyid=whatever` and `git annex enableremote ... [+keyid=newkey] [-keyid=oldkey]`, where `keyid` can only be used when `encryption` is either `hybrid` (default) or `pubkey`.
+
+This would break compatibility with the current interpretation of `encryption`, but I believe it's not so invasive: People are not creating new remotes every day, and an error message could clarify the new behavior. It's also clearer, since key IDs can be added and deleted at will, whereas the encryption scheme cannot.
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_8_9dc921dc6077f828454a4444088b9a43._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_8_9dc921dc6077f828454a4444088b9a43._comment
new file mode 100644
index 000000000..a63ce1262
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_8_9dc921dc6077f828454a4444088b9a43._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 8"
+ date="2013-08-22T17:05:49Z"
+ content="""
+Note that the assistant generates initremote parameters so code there also needs to be changed if the syntax changes.
+
+I think I am ok with changing the syntax. However, it seems that `encryption=-oldkey encryption=newkey` could be used to remove the old revoked key and add a new one. Using `-keyid` as a parameter to initremote is a bit tricky since git-annex's regular option parser would see it, before the parameter could get to initremote. (Unless -keyid was defined as a regular option specific to initremote.) OR, git-annex could just try to detect when a key is revoked and automatically remove it when a new encryption key is specified.
+
+Hmm, it would be possible to have it just notice, when adding a new key, if one of the existing keys is revoked, and
+remove the revoked key automatically.
+
+The above doesn't deal with the case of wanting to add pure asymmetric encryption. It seems to me that from a user's point of view, what they really need to know about asymmetric encryption is that they can't easily give additional keyids access after the fact (without reencrypting and reuploading everything). So I think it would be good if the syntax made that obvious. Perhaps `encryptiononly=key`
+"""]]
diff --git a/doc/bugs/Using_a_revoked_GPG_key/comment_9_f50c802d78041fd1522f0e7599ce6a45._comment b/doc/bugs/Using_a_revoked_GPG_key/comment_9_f50c802d78041fd1522f0e7599ce6a45._comment
new file mode 100644
index 000000000..d86de4e1b
--- /dev/null
+++ b/doc/bugs/Using_a_revoked_GPG_key/comment_9_f50c802d78041fd1522f0e7599ce6a45._comment
@@ -0,0 +1,42 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 9"
+ date="2013-08-22T18:42:28Z"
+ content="""
+Hehe, I ran into the option parser issue when implementing that change
+;-) So I moved to `git annex enableremote ... [keyid+=newkey]
+[keyid-=oldkey]` (where `+` is optional, for consistency) which doesn't
+prevent users from specifying a key by something starting with a sign.
+
+While it's certainly possible to tell git-annex to manage the authorized
+keys itself, users may have other reasons to remove a key so I'm not
+sure it's a good idea. Also, what if someone forgets to add his/her new
+key after revocation (it's still possible to decrypt after all)? If
+another person updates the keyring afterwards, the first user will be
+denied further access, and will have to retrieve and reencrypt the
+\"cipher\" manually, which is not so trivial.
+
+
+I understand that asymmetric encryption needs special care, but Sam's
+use case could be reproduced with that scheme I believe. For instance a
+user may superseed and revoke his/her old key; then new files would be
+uploaded with the new one, but as long as the old key is not
+compromised, I don't see why s/he should reupload everything instead of
+using the old key when pulling from the remote. Of course one may argue
+that the key shouldn't be revoked at the first place, but if it's used
+for other purposes (e.g., it's publicly available on a key server) it's
+good practice to revoke it IMHO.
+
+As for the removal of keys with pure asymmetric encryption, it is just
+required I think: Otherwise revoking a key would prevent any further
+content to be encrypted. There I can't see any problem with git-annex
+managing the keyring itself (beside the extra code to write :-P).
+
+All in all if we are to allow deletion/addition of keyIDs (and I think
+we should!), I think it should be done for both `hybrid` and `pubkey`
+schemes. Do you really want another syntax? I'd say clarify the manage
+(plus maybe a warning when running the CLI) is enough, but true it's
+easy to shoot oneself in the foot there...
+
+"""]]
diff --git a/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_2_6d360a15818866242f9cbcf383094f8a._comment b/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_2_6d360a15818866242f9cbcf383094f8a._comment
deleted file mode 100644
index b0fe1b0fa..000000000
--- a/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_2_6d360a15818866242f9cbcf383094f8a._comment
+++ /dev/null
@@ -1,11 +0,0 @@
-[[!comment format=mdwn
- username="https://www.google.com/accounts/o8/id?id=AItOawnaH44G3QbxBAYyDwy0PbvL0ls60XoaR3Y"
- nickname="Nigel"
- subject="log file"
- date="2013-07-30T19:03:03Z"
- content="""
-Yes, will do. But need to recreate - I repeatedly executed rm -rf .git to repeat the test and left it 'clean'.
-
-PS. Is there an easy(er) way to 'undo' the creation of a repository without loosing any file content? One day I will run rm -rf in the wrong place!
-After an uninstall of annex it was hard for me to figure out how to start with a clean system when the webapp found the previously created repo.
-"""]]
diff --git a/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_3_1a7542249b9c37507126e97441057c12._comment b/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_3_1a7542249b9c37507126e97441057c12._comment
new file mode 100644
index 000000000..9bc0c90e6
--- /dev/null
+++ b/doc/bugs/Watcher_crashed_in_Android_on___47__storage__47__sdcard1_-_bug__63__/comment_3_1a7542249b9c37507126e97441057c12._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 3"
+ date="2013-11-10T18:18:09Z"
+ content="""
+Seems to me this was probably fixed in [[!commit 6b37fcffd872b62fb78047a77e4cee5ab0bb57f1]].
+
+However, I don't know why permission problems would happen on Android, which typically uses a filesystem that does not have restricted permissions for the sdcard.
+
+If you upgrade, you should be able to see if it fixed the crash, and it will also mention any file or directory that it's unable to read in the log.
+"""]]
diff --git a/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git.mdwn b/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git.mdwn
new file mode 100644
index 000000000..dd4b6a921
--- /dev/null
+++ b/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git.mdwn
@@ -0,0 +1,384 @@
+### Please describe the problem.
+I try to share some files between a windows machine and a linux machine in direct mode, with a remote repository between the two. I can't seem to reproduce the problem in indirect mode...
+
+I add a file on the windows machine then copy it to the remote repository. I then get it on the linux machine and edit it there. If I `git annex sync` and copy the file's data to the remote repository, a `git annex sync` on windows will fail like this:
+
+[[!format sh """
+$ git annex sync
+commit
+ok
+pull origin
+remote: Counting objects: 41, done.
+remote: Compressing objects: 100% (24/24), done.
+remote: Total 31 (delta 9), reused 0 (delta 0)
+Unpacking objects: 100% (31/31), done.
+From ssh://192.168.1.29:/home/raz/work/test
+ b23cb44..9073cc3 git-annex -> origin/git-annex
+ 7d4f0e2..87438fc master -> origin/master
+ 57a661c..b33b025 synced/git-annex -> origin/synced/git-annex
+ 7d4f0e2..87438fc synced/master -> origin/synced/master
+ok
+(merging origin/git-annex origin/synced/git-annex into git-annex...)
+(Recording state in git...)
+push origin
+Counting objects: 17, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (4/4), done.
+Writing objects: 100% (5/5), 565 bytes | 0 bytes/s, done.
+Total 5 (delta 2), reused 0 (delta 0)
+To ssh://192.168.1.29:/home/raz/work/test.git
+ b33b025..dcfaf23 git-annex -> synced/git-annex
+ ! [rejected] master -> synced/master (non-fast-forward)
+error: failed to push some refs to 'ssh://192.168.1.29:/home/raz/work/test.git'
+hint: Updates were rejected because a pushed branch tip is behind its remote
+hint: counterpart. Check out this branch and merge the remote changes
+hint: (e.g. 'git pull') before pushing again.
+hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+failed
+git-annex: sync: 1 failed
+"""]]
+
+A `git log` tells me the master branch is not properly merged so I assume the pull failed silently (I paste the log in the transcript).
+
+I can then try to manually fix the windows working copy and sometimes it kind of work, but sometimes I have a hard time recovering and I am better off cloning a new version and moving data's around...
+
+### What steps will reproduce the problem?
+Create a repository on a windows.
+
+Add a file.
+
+`git clone --bare` the repository and put it on a remote machine.
+
+Clone the remote repository to a linux machine.
+
+Get the file's data.
+
+Edit the file on linux.
+
+Commit it and copy the data's to the remote machine.
+
+`git clone sync` on the windows machine --> Error.
+
+### What version of git-annex are you using? On what operating system?
+On Windows:
+[[!format sh """
+git-annex version: 4.20130827-g4f18612
+build flags: Pairing Testsuite S3 WebDAV DNS
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 2
+"""]]
+
+On Linux
+[[!format sh """
+git-annex version: 4.20130815
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+### 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
+
+### On Windows
+
+$ mkdir test_windows
+
+$ cd test_windows/
+
+$ git init
+Initialized empty Git repository in c:/Users/raz/test_windows/.git/
+
+$ git annex init windows
+init windows
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ok
+(Recording state in git...)
+
+$ echo "test 1" > test.txt
+
+$ git annex add test.txt
+add test.txt (checksum...) ok
+(Recording state in git...)
+
+$ git annex sync
+commit
+ok
+git-annex: no branch is checked out
+
+$ cd ..
+
+$ git clone --bare test_windows/ test.git
+Cloning into bare repository 'test.git'...
+done.
+
+$ scp -r test.git 192.168.1.29:/home/raz/work/
+config 100% 183 0.2KB/s 00:00
+description 100% 73 0.1KB/s 00:00
+HEAD 100% 23 0.0KB/s 00:00
+applypatch-msg.sample 100% 452 0.4KB/s 00:00
+commit-msg.sample 100% 896 0.9KB/s 00:00
+post-commit.sample 100% 160 0.2KB/s 00:00
+post-receive.sample 100% 552 0.5KB/s 00:00
+post-update.sample 100% 189 0.2KB/s 00:00
+pre-applypatch.sample 100% 398 0.4KB/s 00:00
+pre-commit.sample 100% 1704 1.7KB/s 00:00
+pre-push.sample 100% 1348 1.3KB/s 00:00
+pre-rebase.sample 100% 4951 4.8KB/s 00:00
+prepare-commit-msg.sample 100% 1239 1.2KB/s 00:00
+update.sample 100% 3611 3.5KB/s 00:00
+exclude 100% 240 0.2KB/s 00:00
+825dc642cb6eb9a060e54bf8d69288fbee4904 100% 15 0.0KB/s 00:00
+a31b7a55380d79248658d3fffff6d2dc41a726 100% 116 0.1KB/s 00:00
+dcabbf728abe62b6e2bcc06b8306eb3aa9a497 100% 176 0.2KB/s 00:00
+332ecbfe923879df51a7a3f9bb86ebdfb64273 100% 45 0.0KB/s 00:00
+4f0e20d38d6dc757340a8c569270b5a857fc67 100% 160 0.2KB/s 00:00
+62956bcf45c63b24a637b22a742db0d9458248 100% 86 0.1KB/s 00:00
+7ec519eb1b257a85ae8f9373d0835dea9ddc04 100% 82 0.1KB/s 00:00
+1d1559a050b4a2df2e653b1e7ac15bdf7d56b1 100% 51 0.1KB/s 00:00
+b74dbedfac4d6a0a90580cff2088a5d61f6675 100% 130 0.1KB/s 00:00
+0ca042f439ef997f04a25a449aa1f539b93cf4 100% 53 0.1KB/s 00:00
+bbce5e51e5a90ffd26900de3546fc4f9704181 100% 151 0.2KB/s 00:00
+18bd66316298fcc5c06af9865c30a2fe4d2476 100% 176 0.2KB/s 00:00
+edf8b5cc207e16ca0173785a2ba569c5d4208c 100% 71 0.1KB/s 00:00
+packed-refs 100% 160 0.2KB/s 00:00
+
+$ cd test_windows/
+
+$ git remote add origin ssh://192.168.1.29:/home/raz/work/test.git
+
+$ git annex copy --to origin
+copy test.txt (checking origin...) (to origin...)
+test.txt
+ 7 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/1)
+
+sent 79 bytes received 31 bytes 220.00 bytes/sec
+total size is 7 speedup is 0.06
+ok
+(Recording state in git...)
+
+$ git annex sync
+commit
+ok
+pull origin
+remote: Counting objects: 11, done.
+remote: Compressing objects: 100% (5/5), done.
+remote: Total 6 (delta 1), reused 0 (delta 0)
+Unpacking objects: 100% (6/6), done.
+From ssh://192.168.1.29:/home/raz/work/test
+ * [new branch] git-annex -> origin/git-annex
+ * [new branch] master -> origin/master
+ok
+(merging origin/git-annex into git-annex...)
+(Recording state in git...)
+push origin
+Counting objects: 18, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (8/8), done.
+Writing objects: 100% (10/10), 874 bytes | 0 bytes/s, done.
+Total 10 (delta 4), reused 0 (delta 0)
+To ssh://192.168.1.29:/home/raz/work/test.git
+ * [new branch] git-annex -> synced/git-annex
+ * [new branch] master -> synced/master
+ok
+
+### On Linux
+
+$ git clone test.git test_linux
+Cloning into 'test_linux'...
+done.
+
+$ cd test_linux
+
+$ git annex init linux
+init linux ok
+(Recording state in git...)
+
+$ git annex sync
+(merging origin/git-annex origin/synced/git-annex into git-annex...)
+(Recording state in git...)
+commit
+ok
+pull origin
+ok
+push origin
+Counting objects: 11, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (6/6), done.
+Writing objects: 100% (8/8), 775 bytes | 0 bytes/s, done.
+Total 8 (delta 3), reused 0 (delta 0)
+To /home/raz/work/test.git
+ 0b4f175..41fba1d git-annex -> synced/git-annex
+ok
+
+$ git annex get
+get test.txt (from origin...) ok
+(Recording state in git...)
+
+$ git annex direct
+commit
+# On branch master
+nothing to commit, working directory clean
+ok
+direct test.txt ok
+direct ok
+
+$ git annex sync
+commit
+ok
+pull origin
+ok
+push origin
+Counting objects: 9, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (4/4), done.
+Writing objects: 100% (5/5), 492 bytes | 0 bytes/s, done.
+Total 5 (delta 1), reused 0 (delta 0)
+To /home/raz/work/test.git
+ 41fba1d..57a661c git-annex -> synced/git-annex
+ok
+
+$ cat test.txt
+test 1
+
+$ echo "test 2" > test.txt
+
+$ git annex sync
+add test.txt (checksum...) ok
+(Recording state in git...)
+commit
+(Recording state in git...)
+ok
+pull origin
+ok
+push origin
+Counting objects: 22, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (12/12), done.
+Writing objects: 100% (16/16), 1.40 KiB | 0 bytes/s, done.
+Total 16 (delta 4), reused 0 (delta 0)
+To /home/raz/work/test.git
+ 57a661c..4883cad git-annex -> synced/git-annex
+ 7d4f0e2..87438fc master -> synced/master
+ok
+
+$ git annex copy --to origin
+copy test.txt (to origin...) ok
+(Recording state in git...)
+
+$ git annex sync
+commit
+ok
+pull origin
+remote: Counting objects: 6, done.
+remote: Compressing objects: 100% (4/4), done.
+remote: Total 5 (delta 0), reused 0 (delta 0)
+Unpacking objects: 100% (5/5), done.
+From /home/raz/work/test
+ b23cb44..9073cc3 git-annex -> origin/git-annex
+ok
+(merging origin/git-annex into git-annex...)
+(Recording state in git...)
+push origin
+Counting objects: 18, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (8/8), done.
+Writing objects: 100% (10/10), 924 bytes | 0 bytes/s, done.
+Total 10 (delta 3), reused 0 (delta 0)
+To /home/raz/work/test.git
+ 4883cad..b33b025 git-annex -> synced/git-annex
+ok
+
+$
+
+
+### On Windows
+
+$ git annex sync
+commit
+ok
+pull origin
+remote: Counting objects: 41, done.
+remote: Compressing objects: 100% (24/24), done.
+remote: Total 31 (delta 9), reused 0 (delta 0)
+Unpacking objects: 100% (31/31), done.
+From ssh://192.168.1.29:/home/raz/work/test
+ b23cb44..9073cc3 git-annex -> origin/git-annex
+ 7d4f0e2..87438fc master -> origin/master
+ 57a661c..b33b025 synced/git-annex -> origin/synced/git-annex
+ 7d4f0e2..87438fc synced/master -> origin/synced/master
+ok
+(merging origin/git-annex origin/synced/git-annex into git-annex...)
+(Recording state in git...)
+push origin
+Counting objects: 17, done.
+Delta compression using up to 8 threads.
+Compressing objects: 100% (4/4), done.
+Writing objects: 100% (5/5), 565 bytes | 0 bytes/s, done.
+Total 5 (delta 2), reused 0 (delta 0)
+To ssh://192.168.1.29:/home/raz/work/test.git
+ b33b025..dcfaf23 git-annex -> synced/git-annex
+ ! [rejected] master -> synced/master (non-fast-forward)
+error: failed to push some refs to 'ssh://192.168.1.29:/home/raz/work/test.git'
+hint: Updates were rejected because a pushed branch tip is behind its remote
+hint: counterpart. Check out this branch and merge the remote changes
+hint: (e.g. 'git pull') before pushing again.
+hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+failed
+git-annex: sync: 1 failed
+
+$ git log --graph --oneline --decorate --all
+* 87438fc (origin/synced/master, origin/master) git-annex automatic sync
+* 7d4f0e2 (HEAD, synced/master, master) git-annex automatic sync
+*-. dcfaf23 (origin/synced/git-annex, git-annex) merging origin/git-annex orig
+|\ \
+| | * b33b025 merging origin/git-annex into git-annex
+| | |\
+| | |/
+| |/|
+| * | 9073cc3 (origin/git-annex) update
+| | * 73518bc update
+| | * 4883cad update
+| | * 1b447f5 update
+| |/
+|/|
+* | 57a661c update
+| |
+| \
+*-. \ 41fba1d merging origin/git-annex origin/synced/git-annex into git-annex
+|\ \ \
+| | |/
+| |/|
+| | * 0b4f175 merging origin/git-annex into git-annex
+| | |\
+| | |/
+| |/|
+| * | b23cb44 update
+| | * b5755a2 update
+| |/
+| * 6adcabb update
+| * df18bd6 update
+| * dcbbce5 branch created
+* 0d138eb update
+* fe6bccc branch created
+
+$
+
+# End of transcript or log.
+"""]]
+
+> Apparently `test.git` had `receive.denyNonFastForwards`
+> set to true, which prevents the forced pushing `git annex sync`
+> needs to do. I have made it print out a hint about this setting
+> when a push failes. [[done]] --[[Joey]]
diff --git a/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git/comment_1_155e0c4d3aa41eebfe27533ab70a91d3._comment b/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git/comment_1_155e0c4d3aa41eebfe27533ab70a91d3._comment
new file mode 100644
index 000000000..1a443fb19
--- /dev/null
+++ b/doc/bugs/Windows_and_Linux_in_direct_mode_confuses_git/comment_1_155e0c4d3aa41eebfe27533ab70a91d3._comment
@@ -0,0 +1,68 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawknruiCHUcOh2mmpkh7OFJ4iNfAOOamRVs"
+ nickname="Renaud"
+ subject="comment 1"
+ date="2013-08-29T06:38:44Z"
+ content="""
+I wonder if it isn't related to the fact that even if I do `git annex drop` on windows, the file is still marked as modified in git.
+What is in repository is the path to the file's data using unix style folder separator but what is in my working directory is a file containing the path using windows style folder separator.
+
+I paste a transcript to describe what I mean:
+
+[[!format sh \"\"\"
+$ mkdir tmp
+
+$ cd tmp
+
+$ git init
+Initialized empty Git repository in c:/Users/raz/tmp/tmp/.git/
+
+$ git annex init test
+init test
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ok
+(Recording state in git...)
+
+$ echo test > test
+
+$ git annex add
+add test (checksum...) ok
+(Recording state in git...)
+
+$ git annex sync
+commit
+ok
+git-annex: no branch is checked out
+
+$ git annex drop --force
+drop test ok
+(Recording state in git...)
+
+$ git status
+# On branch master
+# Changes not staged for commit:
+# (use \"git add <file>...\" to update what will be committed)
+# (use \"git checkout -- <file>...\" to discard changes in working directory)
+#
+# modified: test
+#
+no changes added to commit (use \"git add\" and/or \"git commit -a\")
+
+$ git diff
+diff --git a/test b/test
+index a9dd439..62343b2 120000
+--- a/test
++++ b/test
+@@ -1 +1 @@
+-.git/annex/objects/w8/pv/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93
+\ No newline at end of file
++.git\annex\objects\w8\pv\SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93
+\ No newline at end of file
+\"\"\"]]
+"""]]
diff --git a/doc/bugs/Windows_build_test_failures.mdwn b/doc/bugs/Windows_build_test_failures.mdwn
index 97027d425..ac4dce13c 100644
--- a/doc/bugs/Windows_build_test_failures.mdwn
+++ b/doc/bugs/Windows_build_test_failures.mdwn
@@ -1228,3 +1228,5 @@ Some tests failed!
# End of transcript or log.
"""]]
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/Windows_build_test_failures/comment_1_ea7523fdbafdc8be2971df52d9038826._comment b/doc/bugs/Windows_build_test_failures/comment_1_ea7523fdbafdc8be2971df52d9038826._comment
new file mode 100644
index 000000000..dc09fb89b
--- /dev/null
+++ b/doc/bugs/Windows_build_test_failures/comment_1_ea7523fdbafdc8be2971df52d9038826._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 1"
+ date="2013-09-13T19:18:26Z"
+ content="""
+The Windows port has improved quite a lot since this bug was filed. Can you still reproduce it?
+
+If you install the pre-built git-annex for Windows, you can run `git annex test` to run the test suite. Does that work? It works for some others on Windows.
+"""]]
diff --git a/doc/bugs/Windows_installer_includes_curl_and_wget__44___but_not_required_DLLs.mdwn b/doc/bugs/Windows_installer_includes_curl_and_wget__44___but_not_required_DLLs.mdwn
index 60a894b4e..a21813500 100644
--- a/doc/bugs/Windows_installer_includes_curl_and_wget__44___but_not_required_DLLs.mdwn
+++ b/doc/bugs/Windows_installer_includes_curl_and_wget__44___but_not_required_DLLs.mdwn
@@ -13,3 +13,5 @@ Windows 7.
### Please provide any additional information below.
Installing Cygwin and adding to path seems to fix issue.
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail.mdwn b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail.mdwn
new file mode 100644
index 000000000..64e95ca1b
--- /dev/null
+++ b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail.mdwn
@@ -0,0 +1,131 @@
+[[!tag moreinfo]]
+
+### Please describe the problem.
+git annex get on a clone of a repository created on Windows fails.
+
+### What steps will reproduce the problem?
+On Windows:
+1. Create an annex using git annex init
+
+2. git add files
+
+3. git annex sync (because I forgot about commit)
+
+On Linux:
+
+1. Mount the Windows annex via SMB (mine was read only, but probably won't matter)
+
+2. git clone the folder (works fine)
+
+3. git annex get (fails, due to Windows drive letter)
+
+### What version of git-annex are you using? On what operating system?
+
+*Windows:*
+
+git-annex version: 4.20130802-g0a52f02
+
+build flags: Pairing Testsuite S3 WebDAV DNS
+
+*Linux: (Debian wheezy on ARMel)*
+
+git-annex version: 3.20120629
+
+local repository version: 3
+
+default repository version: 3
+
+supported repository versions: 3
+
+upgrade supported from repository versions: 0 1 2
+
+
+### 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
+
+#output of git annex get on the Linux side.
+
+get Purchased/Caravan Palace/Panic/01 Queens.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/02 Maniac.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/03 The Dirty Side of the Street.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/04 12 juin 3049.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/05 Rock It for Me.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/06 Clash.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/07 Newbop.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/08 Glory of Nelly.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/09 Dramophone.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/10 Cotton Heads.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/11 Panic.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/12 Pirates.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/13 Beatophone.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/14 Sydney.mp3 (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+failed
+get Purchased/Caravan Palace/Panic/Thumbs.db (not available)
+ Try making some of these repositories available:
+ d6c78593-79d2-455a-8202-7be2133e2d48 -- ICARUS:E:\music
+
+
+And the (broken) symlinks:
+
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 01 Queens.mp3 -> .git/annex/objects/5P/vq/SHA256E-s9886015--dfb8f452d47f997a9141de3f152de375fad1d5ccb4a20d5c022064a630eaba88.mp3/SHA256E-s9886015--dfb8f452d47f997a9141de3f152de375fad1d5ccb4a20d5c022064a630eaba88.mp3
+lrwxrwxrwx 1 voltagex voltagex 200 Aug 11 23:05 02 Maniac.mp3 -> .git/annex/objects/J0/WV/SHA256E-s10116938--7ce35f4a54c4f74bd2e3813445cb3a07fae76b2854df06ab00876cd0067f34a5.mp3/SHA256E-s10116938--7ce35f4a54c4f74bd2e3813445cb3a07fae76b2854df06ab00876cd0067f34a5.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 03 The Dirty Side of the Street.mp3 -> .git/annex/objects/xz/4F/SHA256E-s8812949--9e15761ae8c6231d11d1f5a67de8a89142e2e4017b43b8ffac1088fd71842ca7.mp3/SHA256E-s8812949--9e15761ae8c6231d11d1f5a67de8a89142e2e4017b43b8ffac1088fd71842ca7.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 04 12 juin 3049.mp3 -> .git/annex/objects/Kp/k6/SHA256E-s8236133--3a6465bea3272ae7a22b77b67e96a91ae389390cc95642fb1456ce80e3313033.mp3/SHA256E-s8236133--3a6465bea3272ae7a22b77b67e96a91ae389390cc95642fb1456ce80e3313033.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 05 Rock It for Me.mp3 -> .git/annex/objects/Wk/Qv/SHA256E-s7701150--8197e499408e64601157df95927ac6b09bd37834a41eceecc5d12667bd7c66a4.mp3/SHA256E-s7701150--8197e499408e64601157df95927ac6b09bd37834a41eceecc5d12667bd7c66a4.mp3
+lrwxrwxrwx 1 voltagex voltagex 200 Aug 11 23:05 06 Clash.mp3 -> .git/annex/objects/ZQ/P4/SHA256E-s10201572--c2a1a8892fcaaab1ed59ca7f5ab9d45f0c3bb3c6d6450b95228039b9e8d7a0b4.mp3/SHA256E-s10201572--c2a1a8892fcaaab1ed59ca7f5ab9d45f0c3bb3c6d6450b95228039b9e8d7a0b4.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 07 Newbop.mp3 -> .git/annex/objects/Fk/wV/SHA256E-s6850587--b5ba0347f6a09a7ff8bec2dd1fbe8076fdff645d4bc1909ddeadfc035bf19fda.mp3/SHA256E-s6850587--b5ba0347f6a09a7ff8bec2dd1fbe8076fdff645d4bc1909ddeadfc035bf19fda.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 08 Glory of Nelly.mp3 -> .git/annex/objects/Pm/K3/SHA256E-s9002048--18149581cbfc3b4e3e72b784777fe34c53f1580e78e97f66058be0b1eb40e809.mp3/SHA256E-s9002048--18149581cbfc3b4e3e72b784777fe34c53f1580e78e97f66058be0b1eb40e809.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 09 Dramophone.mp3 -> .git/annex/objects/k3/Jf/SHA256E-s8199558--925117d9fc47a65e8e5324f3d0638a3c24bf51fd6c0b5d8ac2f63951c893cc48.mp3/SHA256E-s8199558--925117d9fc47a65e8e5324f3d0638a3c24bf51fd6c0b5d8ac2f63951c893cc48.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 10 Cotton Heads.mp3 -> .git/annex/objects/9f/32/SHA256E-s8801425--c6926238c0b1a3bbea1a5d17841ceac591e53e223e4c4c45a2077cabffc85d81.mp3/SHA256E-s8801425--c6926238c0b1a3bbea1a5d17841ceac591e53e223e4c4c45a2077cabffc85d81.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 11 Panic.mp3 -> .git/annex/objects/XF/WF/SHA256E-s9833770--5e837c7fa3ec096f7c0507efbcf398067029749f8a0fc77a2badf864b9ffbb7c.mp3/SHA256E-s9833770--5e837c7fa3ec096f7c0507efbcf398067029749f8a0fc77a2badf864b9ffbb7c.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 12 Pirates.mp3 -> .git/annex/objects/7Z/jz/SHA256E-s8017742--5fd49b2d89577266d2fb740e7e7def9338475af90c2ca99f9d6d513465b2bfac.mp3/SHA256E-s8017742--5fd49b2d89577266d2fb740e7e7def9338475af90c2ca99f9d6d513465b2bfac.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 13 Beatophone.mp3 -> .git/annex/objects/81/xv/SHA256E-s9339544--a1eb8404ecf0503b9f635378fec4e2c95ec08bb1428c2cd4c0cedf492811577d.mp3/SHA256E-s9339544--a1eb8404ecf0503b9f635378fec4e2c95ec08bb1428c2cd4c0cedf492811577d.mp3
+lrwxrwxrwx 1 voltagex voltagex 198 Aug 11 23:05 14 Sydney.mp3 -> .git/annex/objects/3K/99/SHA256E-s8459731--4ff44b25c912e914c79124ff9074c576c0024152442fc96c9bad65f5a50a40d9.mp3/SHA256E-s8459731--4ff44b25c912e914c79124ff9074c576c0024152442fc96c9bad65f5a50a40d9.mp3
+lrwxrwxrwx 1 voltagex voltagex 192 Aug 11 23:05 Thumbs.db -> .git/annex/objects/28/Zv/SHA256E-s85504--3604669cd3a55234516191eb4f19434829c1634d6dd69a9981185f095d2bbaba.db/SHA256E-s85504--3604669cd3a55234516191eb4f19434829c1634d6dd69a9981185f095d2bbaba.db
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_1_c87bae87b7902db60a3fef41e1fca85d._comment b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_1_c87bae87b7902db60a3fef41e1fca85d._comment
new file mode 100644
index 000000000..0577531b7
--- /dev/null
+++ b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_1_c87bae87b7902db60a3fef41e1fca85d._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlzWwnBfgJrkhPQakBo6DbPXutJIVDHkj0"
+ nickname="Adam"
+ subject="comment 1"
+ date="2013-08-11T14:15:40Z"
+ content="""
+Confirming the same errors happen with git-annex version: 4.20130802 from sid.
+
+"""]]
diff --git a/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_2_9e3c1f1ba05d8996b5a95829ce32c07e._comment b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_2_9e3c1f1ba05d8996b5a95829ce32c07e._comment
new file mode 100644
index 000000000..d98e7976e
--- /dev/null
+++ b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_2_9e3c1f1ba05d8996b5a95829ce32c07e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="bad bug report title 101"
+ date="2013-08-24T19:17:29Z"
+ content="""
+I don't understand why you think the problem has something to do with Windows drive letters. There are no Windows drive letters in the symlinks you show. The only place I see any Windows drive letter is in the descripton of the remote that `git annex get` displays when it fails to get the file. That description is purely informative, it's not a path that git-annex is trying to use.
+
+I'd suggest that you run `git annex get --debug` to see if it is doing anything obviously wrong. The mostly likely culprit is your SMB setup, which I am not going to be able to replicate.
+"""]]
diff --git a/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_3_3a0787912f4a3a8797b7786f5ce38590._comment b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_3_3a0787912f4a3a8797b7786f5ce38590._comment
new file mode 100644
index 000000000..16f240cf2
--- /dev/null
+++ b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_3_3a0787912f4a3a8797b7786f5ce38590._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlzWwnBfgJrkhPQakBo6DbPXutJIVDHkj0"
+ nickname="Adam"
+ subject="comment 3"
+ date="2013-08-26T06:56:33Z"
+ content="""
+You're correct. I can see in .git/config that the remote references z:\ which of course will break on the Linux side. Maybe this is a case of the error messages not quite telling me the right thing?
+"""]]
diff --git a/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_4_c4249f32d65594d79ea01145b93ec948._comment b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_4_c4249f32d65594d79ea01145b93ec948._comment
new file mode 100644
index 000000000..31bc7c1a1
--- /dev/null
+++ b/doc/bugs/Windows_to_Linux_clone_-_Windows_drive_letters_cause_git_annex_get_to_fail/comment_4_c4249f32d65594d79ea01145b93ec948._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 4"
+ date="2013-09-13T19:29:25Z"
+ content="""
+I'd suggest that you run git annex get --debug to see if it is doing anything obviously wrong. The mostly likely culprit is your SMB setup, which I am not going to be able to replicate.
+
+"""]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes.mdwn b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes.mdwn
new file mode 100644
index 000000000..e7ff53723
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes.mdwn
@@ -0,0 +1,44 @@
+### Please describe the problem.
+git-annex assistant is currently running. Here is the output of **ps -A u | grep -i git**:
+
+[[!format sh """
+5457 pts/2 Z+ 0:00 [git-annex] <defunct>
+5510 ? Sl 0:05 git-annex assistant
+5522 ? S 0:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+5573 ? S 0:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+5679 ? SN 0:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex check-attr -z --stdin annex.backend annex.numcopies --
+5680 ? Z 0:03 [git-annex] <defunct>
+5710 ? Z 0:00 [git-annex] <defunct>
+5732 pts/2 Z+ 0:00 [git-annex] <defunct>
+5752 pts/2 Z+ 0:00 [git-annex] <defunct>
+5785 ? Ss 0:00 ssh: .git/annex/ssh/example.net [mux]
+5905 ? Z 0:00 [git-annex] <defunct>
+5923 ? Z 0:00 [git-annex] <defunct>
+6513 pts/2 Z+ 0:00 [git-annex] <defunct>
+6552 ? Z 0:00 [git-annex] <defunct>
+7797 ? Z 0:00 [git-annex] <defunct>
+7873 pts/2 Z 0:00 [git-annex] <defunct>
+8708 pts/2 Z+ 0:00 [git-annex] <defunct>
+9821 ? Z 0:00 [git-annex] <defunct>
+9841 pts/2 Z+ 0:00 [git-annex] <defunct>
+10462 ? Z 0:00 [git-annex] <defunct>
+10522 pts/2 Z 0:00 [git-annex] <defunct>
+12777 pts/2 Z+ 0:00 [git-annex] <defunct>
+13878 pts/2 Z+ 0:00 [git-annex] <defunct>
+14254 ? Z 0:00 [git-annex] <defunct>
+14276 pts/2 Z+ 0:00 [git-annex] <defunct>
+15932 ? Sl 0:00 git-annex transferkeys --readfd 37 --writefd 20
+16022 pts/2 Sl 0:00 git-annex transferkeys --readfd 28 --writefd 22
+16079 pts/2 S 0:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+16081 ? S 0:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+31565 pts/2 Sl+ 0:20 git-annex webapp
+31580 pts/2 S+ 0:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31590 pts/2 S+ 0:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31618 pts/2 S+ 0:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31635 ? Sl 9:26 /usr/lib/firefox/firefox /mnt/debian/home/me/annex-backup/.git/annex/webapp.html
+31689 pts/2 SN+ 0:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup check-attr -z --stdin annex.backend annex.numcopies --
+31812 pts/2 Z 0:00 [git-annex] <defunct>
+31835 ? Ss 0:02 ssh: .git/annex/ssh/example.net [mux]
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_1_0f8b248025722309e9577d7dad74b76b._comment b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_1_0f8b248025722309e9577d7dad74b76b._comment
new file mode 100644
index 000000000..578fecb58
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_1_0f8b248025722309e9577d7dad74b76b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-03T01:12:25Z"
+ content="""
+This is apparently the same repository where [[all_this_went_on|bugs/Unnecessary_remote_transfers]].
+
+I don't know if this is indicative of a problem. I see more zombies than I would normally expect, but I don't know if the number is growing, or shrinking, or staying the same. You should at least look at ps -f to see which of the multiple git-annex assistant daemons you have configured to run on this machine (not a usual configuration) is the parent of the zombies.
+"""]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_2_f5f7db688a2a93ee7453674fb742043b._comment b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_2_f5f7db688a2a93ee7453674fb742043b._comment
new file mode 100644
index 000000000..ceb05ea0c
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_2_f5f7db688a2a93ee7453674fb742043b._comment
@@ -0,0 +1,52 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-11-03T01:19:42Z"
+ content="""
+Indeed. I've been looking forward to setting up git-annex assistant for a long time, waiting until I had more free time, and was finally pushed to do it when I had a weird problem with Dropbox. I'm not sure what I did wrong to make such a mess, haha.
+
+I see \"5510 git-annex assistant\" and \"31565 git-annex webapp\"--does the \"webapp\" one count as an assistant process too?
+[[!format sh \"\"\"$ ps -ef | gi git
+UID PID PPID C STIME TTY TIME CMD
+me 3404 31565 0 17:44 pts/2 00:00:04 [git-annex] <defunct>
+me 5457 31565 0 17:59 pts/2 00:00:00 [git-annex] <defunct>
+me 5510 1 0 17:59 ? 00:00:06 git-annex assistant
+me 5522 5510 0 17:59 ? 00:00:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+me 5573 5510 0 17:59 ? 00:00:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+me 5679 5510 0 17:59 ? 00:00:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex check-attr -z --stdin annex.backend annex.numcopies --
+me 5680 5510 0 17:59 ? 00:00:03 [git-annex] <defunct>
+me 5710 5510 0 18:00 ? 00:00:00 [git-annex] <defunct>
+me 5732 31565 0 18:00 pts/2 00:00:00 [git-annex] <defunct>
+me 5752 31565 0 18:00 pts/2 00:00:00 [git-annex] <defunct>
+me 5785 1 0 18:01 ? 00:00:00 ssh: .git/annex/ssh/example.net [mux]
+me 5905 5510 0 18:02 ? 00:00:00 [git-annex] <defunct>
+me 5923 5510 0 18:02 ? 00:00:00 [git-annex] <defunct>
+me 6513 31565 0 18:05 pts/2 00:00:00 [git-annex] <defunct>
+me 6552 5510 0 18:06 ? 00:00:00 [git-annex] <defunct>
+me 7797 5510 0 18:09 ? 00:00:00 [git-annex] <defunct>
+me 7873 31565 0 18:09 pts/2 00:00:00 [git-annex] <defunct>
+me 8708 31565 0 18:10 pts/2 00:00:00 [git-annex] <defunct>
+me 9821 5510 0 18:12 ? 00:00:00 [git-annex] <defunct>
+me 9841 31565 0 18:14 pts/2 00:00:00 [git-annex] <defunct>
+me 10462 5510 0 18:23 ? 00:00:00 [git-annex] <defunct>
+me 10522 31565 0 18:24 pts/2 00:00:00 [git-annex] <defunct>
+me 12777 31565 0 18:34 pts/2 00:00:00 [git-annex] <defunct>
+me 13878 31565 0 18:35 pts/2 00:00:00 [git-annex] <defunct>
+me 14254 5510 0 18:36 ? 00:00:00 [git-annex] <defunct>
+me 14276 31565 0 18:36 pts/2 00:00:00 [git-annex] <defunct>
+me 15932 5510 0 18:55 ? 00:00:00 git-annex transferkeys --readfd 37 --writefd 20
+me 16022 31565 0 18:55 pts/2 00:00:00 git-annex transferkeys --readfd 28 --writefd 22
+me 16079 16022 0 18:55 pts/2 00:00:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+me 16081 15932 0 18:55 ? 00:00:00 git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+me 25136 25135 0 20:15 pts/6 00:00:00 grep -i git
+me 31565 31478 0 17:42 pts/2 00:00:21 git-annex webapp
+me 31580 31565 0 17:42 pts/2 00:00:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+me 31590 31565 0 17:42 pts/2 00:00:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+me 31618 31565 0 17:42 pts/2 00:00:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+me 31635 27578 8 17:42 ? 00:13:42 /usr/lib/firefox/firefox /mnt/debian/home/me/annex-backup/.git/annex/webapp.html
+me 31689 31565 0 17:42 pts/2 00:00:00 git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup check-attr -z --stdin annex.backend annex.numcopies --
+me 31812 31565 0 17:42 pts/2 00:00:00 [git-annex] <defunct>
+me 31835 1 0 17:42 ? 00:00:02 ssh: .git/annex/ssh/example.net [mux]\"\"\"]]
+
+"""]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_3_ffcae976aa3dc2426188797c1aaffb82._comment b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_3_ffcae976aa3dc2426188797c1aaffb82._comment
new file mode 100644
index 000000000..78e816f06
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_3_ffcae976aa3dc2426188797c1aaffb82._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-03T01:31:26Z"
+ content="""
+`ps fax` is much easier to read
+
+Yes, the assistant can be started by either `git annex assistant` or, if it's not already running, `git annex webapp`
+"""]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_4_8a7ff6841ad7c27ead06bf12f46b20a0._comment b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_4_8a7ff6841ad7c27ead06bf12f46b20a0._comment
new file mode 100644
index 000000000..2bf32bd37
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_4_8a7ff6841ad7c27ead06bf12f46b20a0._comment
@@ -0,0 +1,49 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 4"
+ date="2013-11-03T01:35:32Z"
+ content="""
+Ah, thank you. I get lost in ps's man page. :)
+
+[[!format sh \"\"\"
+31635 ? Rl 16:16 \_ /usr/lib/firefox/firefox /mnt/debian/home/me/annex-backup/.git/annex/webapp.html
+31565 pts/2 Sl+ 0:21 | \_ git-annex webapp
+31580 pts/2 S+ 0:00 | \_ git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31590 pts/2 S+ 0:00 | \_ git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31618 pts/2 S+ 0:00 | \_ git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+31689 pts/2 SN+ 0:00 | \_ git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup check-attr -z --stdin annex.backend annex.numcopies --
+31812 pts/2 Z 0:00 | \_ [git-annex] <defunct>
+ 3404 pts/2 Z 0:04 | \_ [git-annex] <defunct>
+ 5457 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+ 5732 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+ 5752 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+ 6513 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+ 7873 pts/2 Z 0:00 | \_ [git-annex] <defunct>
+ 8708 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+ 9841 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+10522 pts/2 Z 0:00 | \_ [git-annex] <defunct>
+12777 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+13878 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+14276 pts/2 Z+ 0:00 | \_ [git-annex] <defunct>
+16022 pts/2 Sl 0:00 | \_ git-annex transferkeys --readfd 28 --writefd 22
+16079 pts/2 S 0:00 | \_ git --git-dir=/mnt/debian/home/me/annex-backup/.git --work-tree=/mnt/debian/home/me/annex-backup cat-file --batch
+26828 pts/6 S+ 0:00 | \_ grep -i git
+31835 ? Ss 0:02 ssh: .git/annex/ssh/example.net [mux]
+ 5510 ? Sl 0:06 git-annex assistant
+ 5522 ? S 0:00 \_ git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+ 5573 ? S 0:00 \_ git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+ 5679 ? SN 0:00 \_ git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex check-attr -z --stdin annex.backend annex.numcopies --
+ 5680 ? Z 0:03 \_ [git-annex] <defunct>
+ 5710 ? Z 0:00 \_ [git-annex] <defunct>
+ 5905 ? Z 0:00 \_ [git-annex] <defunct>
+ 5923 ? Z 0:00 \_ [git-annex] <defunct>
+ 6552 ? Z 0:00 \_ [git-annex] <defunct>
+ 7797 ? Z 0:00 \_ [git-annex] <defunct>
+ 9821 ? Z 0:00 \_ [git-annex] <defunct>
+10462 ? Z 0:00 \_ [git-annex] <defunct>
+14254 ? Z 0:00 \_ [git-annex] <defunct>
+15932 ? Sl 0:00 \_ git-annex transferkeys --readfd 37 --writefd 20
+16081 ? S 0:00 \_ git --git-dir=/home/me/annex/.git --work-tree=/home/me/annex cat-file --batch
+ 5785 ? Ss 0:00 ssh: .git/annex/ssh/example.net [mux] \"\"\"]]
+"""]]
diff --git a/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_5_406fdee0728680774a69d28446163f10._comment b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_5_406fdee0728680774a69d28446163f10._comment
new file mode 100644
index 000000000..f8f223524
--- /dev/null
+++ b/doc/bugs/Zombie_processes_and__47__or_stuck_git_processes/comment_5_406fdee0728680774a69d28446163f10._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 5"
+ date="2013-11-03T02:33:14Z"
+ content="""
+I believe that these zombies were all caused by switching between repository views in the webapp. I was able to reproduce 1 zombie per switch between repos.
+
+There are a few other places where git-annex execs itself, but not many, and most of them are often used and it would be noticed if they were crypts from which pour forth the living dead. (Oddly the TV show I was thinking about watching this evening.)
+
+<pre>
+joey@darkstar:~/src/git-annex>git grep readProgramFile
+Assistant/Repair.hs: program <- readProgramFile
+Assistant/Threads/Cronner.hs: program <- liftIO $ readProgramFile
+Assistant/Threads/Cronner.hs: program <- readProgramFile
+Assistant/Threads/Transferrer.hs: program <- liftIO readProgramFile
+Assistant/TransferSlots.hs: program <- liftIO readProgramFile
+Assistant/WebApp/Control.hs: program <- readProgramFile
+Assistant/WebApp/OtherRepos.hs: program <- readProgramFile
+Assistant/XMPP/Git.hs: program <- readProgramFile
+Command/Assistant.hs: program <- readProgramFile
+Config/Files.hs:readProgramFile :: IO FilePath
+Config/Files.hs:readProgramFile = do
+Remote/Git.hs: program <- readProgramFile
+</pre>
+"""]]
diff --git a/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error..mdwn b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error..mdwn
new file mode 100644
index 000000000..9befd7c80
--- /dev/null
+++ b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error..mdwn
@@ -0,0 +1,39 @@
+### Please describe the problem.
+
+After setting the username (xyz@gmail.com) and the password the webapp takes several minutes until eventually an error message is displayed stating that:
+
+ Unable to connect to the Jabber server. Maybe you entered the wrong password? (Error message: host gmail.com:5222 failed: connect: does not exist (Network is unreachable))
+
+Testing with xyz@xmpp.l.gmail.com yields:
+
+ Unable to connect to the Jabber server. Maybe you entered the wrong password? (Error message: host xmpp.l.google.com:5222 failed: AuthenticationFailure)
+
+What's strange about that is that the exact same procedure works on a different (Ubuntu-) system with almost no time spend.
+
+### What steps will reproduce the problem?
+
+Trying to set up the jabber connection.
+
+### What version of git-annex are you using? On what operating system?
+
+ git-annex version: 4.20130922-g7dc188a
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi
+ (actually a zeroinstall feed from here: http://f12n.de/0install/git-annex-webapp.xml which is based on the standalone build)
+
+OS: up-to-date ARCH 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
+
+[2013-09-23 19:24:04 CEST] main: starting assistant version 4.20130922-g7dc188a
+(scanning...) [2013-09-23 19:24:04 CEST] Watcher: Performing startup scan
+(started...)
+[2013-09-23 20:18:12 CEST] read: host ["-t","SRV","--","_xmpp-client._tcp.gmail.com"]
+.git/annex/daemon.log (END)
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_1_6d821af99ab3c83a5b0f52d3713ab8e2._comment b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_1_6d821af99ab3c83a5b0f52d3713ab8e2._comment
new file mode 100644
index 000000000..c2dd31f17
--- /dev/null
+++ b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_1_6d821af99ab3c83a5b0f52d3713ab8e2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:27:24Z"
+ content="""
+Sounds like the SRV lookup is failing. Does `git-annex version` list either DNS or ADNS in the build flags?
+
+Does `host -t SRV _xmpp-client._tcp.gmail.com` work?
+"""]]
diff --git a/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_2_206b6c8cce8350fc088f01c42fc4715b._comment b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_2_206b6c8cce8350fc088f01c42fc4715b._comment
new file mode 100644
index 000000000..1cb191d8f
--- /dev/null
+++ b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_2_206b6c8cce8350fc088f01c42fc4715b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawknwkXgi8SnK4QT32ANl3GMKvFLyQGeHqo"
+ nickname="Florian"
+ subject="comment 2"
+ date="2013-09-25T21:19:23Z"
+ content="""
+Aaaah ok ... the *host* command is not installed by default on Arch Linux. I've installed it ... now it works ... will report it to the package maintainer.
+"""]]
diff --git a/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_3_ed36f503f88611382b50687608b9b7e7._comment b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_3_ed36f503f88611382b50687608b9b7e7._comment
new file mode 100644
index 000000000..a69763af7
--- /dev/null
+++ b/doc/bugs/__34__Configuring_Jabber_Account__34___fails_with_a___34__Network_unreachable__34___error./comment_3_ed36f503f88611382b50687608b9b7e7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 3"
+ date="2013-11-08T18:42:22Z"
+ content="""
+Seems like I should fix the standalone linux tarball to either include the host program, or better, build git-annex with the Haskell [DNS library](https://hackage.haskell.org/package/dns). (I think that the Mac app and other builds are built with DNS by default, since they have dependencies installed using cabal directly).
+
+I need to first get that library included in Debian, so I can install it reliably on my build systems.
+"""]]
diff --git a/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu.mdwn b/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu.mdwn
new file mode 100644
index 000000000..7968d32cc
--- /dev/null
+++ b/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu.mdwn
@@ -0,0 +1,22 @@
+### Please describe the problem.
+Using assistant via xfce's "Internet -> Git annex" menu item, trying to connect to an ssh server fails
+
+### What steps will reproduce the problem?
+Use xubuntu 13.04 and git-annex
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 3.20121112ubuntu2
+
+xubuntu 13.04
+
+### Please provide any additional information below.
+if I "sudo apt-get install ssh-askpass", this gets resolved. I think this should be fixed in the ubuntu repository's program dependencies.
+
+Also if I run "git-annex webapp" from the terminal, this doesn't happen because it will ask me for the password in the terminal.
+[[!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
+ Failed to ssh to the server. Transcript: ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory Permission denied, please try again. ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory Received disconnect from xxx.xxx.xxx.xxx: 2: Too many authentication failures for <user>
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu/comment_1_f4656f8a0f36535def0772db06098c5f._comment b/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu/comment_1_f4656f8a0f36535def0772db06098c5f._comment
new file mode 100644
index 000000000..34a2ed325
--- /dev/null
+++ b/doc/bugs/__40__assistant__41___dependency_on_ssh-askpass_-_not_installed_automatically_on_xubuntu/comment_1_f4656f8a0f36535def0772db06098c5f._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T20:08:57Z"
+ content="""
+It's not a dependency. It's a recommends.
+
+apt does not install new recommends that get added to a package. Adding that recommends only causes it to be installed by default when new users install the package
+
+This seems to be the best I can do, short of adding a separate git-annex-assistant package, which could depend on ssh-askpass.
+Might not be a bad idea..
+"""]]
diff --git a/doc/bugs/__96__git_annex_import__96___clobbers_mtime.mdwn b/doc/bugs/__96__git_annex_import__96___clobbers_mtime.mdwn
index ce1c67fee..7edebe584 100644
--- a/doc/bugs/__96__git_annex_import__96___clobbers_mtime.mdwn
+++ b/doc/bugs/__96__git_annex_import__96___clobbers_mtime.mdwn
@@ -58,3 +58,5 @@ mtimes are clobbered with what I think is the time of the first time `git annex`
upgrade supported from repository versions: 0 1 2
Debian unstable amd64
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/install/Android/comment_7_c6dc23d0e6f4138c4bf8e3452755676f._comment b/doc/bugs/__96__git_annex_import__96___clobbers_mtime/comment_4_7235130786e764ec3ad5facfecde62da._comment
index 61c1a916b..8bc6274f9 100644
--- a/doc/install/Android/comment_7_c6dc23d0e6f4138c4bf8e3452755676f._comment
+++ b/doc/bugs/__96__git_annex_import__96___clobbers_mtime/comment_4_7235130786e764ec3ad5facfecde62da._comment
@@ -1,8 +1,8 @@
[[!comment format=mdwn
username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
nickname="Richard"
- subject="comment 7"
- date="2013-07-30T15:02:51Z"
+ subject="comment 4"
+ date="2013-09-26T09:08:11Z"
content="""
-@Tony @justjohn: I created a proper bug for this: [[bugs/git-annex_broken_on_Android_4.3]]
+Fixed in http://source.git-annex.branchable.com/?p=source.git;a=commitdiff;h=98fc7e8
"""]]
diff --git a/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories.mdwn b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories.mdwn
new file mode 100644
index 000000000..1580cee81
--- /dev/null
+++ b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories.mdwn
@@ -0,0 +1,113 @@
+### Please describe the problem.
+
+`git annex import otherrepo` does not work.
+
+
+### What steps will reproduce the problem?
+
+ richih@eudyptes ~ % mcd killme/git-annex-source
+ richih@eudyptes ~/killme/git-annex-source % git init; git annex init
+ Initialized empty Git repository in /home/richih/killme/git-annex-source/.git/
+ init ok
+ (Recording state in git...)
+ richih@eudyptes (git)-[master] ~/killme/git-annex-source % dd if=/dev/urandom of=foo bs=1M count=1
+ 1+0 records in
+ 1+0 records out
+ 1048576 bytes (1.0 MB) copied, 0.281043 s, 3.7 MB/s
+ richih@eudyptes (git)-[master] ~/killme/git-annex-source % git annex add .
+ add foo (checksum...) ok
+ (Recording state in git...)
+ richih@eudyptes (git)-[master] ~/killme/git-annex-source % git commit -m files
+ [master (root-commit) 8054eeb] files
+ 1 file changed, 1 insertion(+)
+ create mode 120000 foo
+ richih@eudyptes (git)-[master] ~/killme/git-annex-source % mcd ../git-annex-import
+ richih@eudyptes ~/killme/git-annex-import % git init; git annex init
+ Initialized empty Git repository in /home/richih/killme/git-annex-import/.git/
+ init ok
+ (Recording state in git...)
+ richih@eudyptes (git)-[master] ~/killme/git-annex-import % git annex import ../git-annex-source/foo
+ richih@eudyptes (git)-[master] ~/killme/git-annex-import % ls
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130920 on Debian Sid
+
+
+### PS:
+
+To add insult to injury, this does "work":
+
+ ih@eudyptes (git)-[master] ~/killme/git-annex-import % mcd bar
+ richih@eudyptes (git)-[master] ~/killme/git-annex-import/bar % git annex import ../../git-annex-source/
+ import .git/description (checksum...) ok
+ import .git/HEAD (checksum...) ok
+ import .git/config (checksum...) ok
+ import .git/index (checksum...) ok
+ import .git/COMMIT_EDITMSG (checksum...) ok
+ import .git/refs/heads/git-annex (checksum...) ok
+ import .git/refs/heads/master (checksum...) ok
+ import .git/hooks/update.sample (checksum...) ok
+ import .git/hooks/applypatch-msg.sample (checksum...) ok
+ import .git/hooks/pre-rebase.sample (checksum...) ok
+ import .git/hooks/pre-commit.sample (checksum...) ok
+ import .git/hooks/pre-applypatch.sample (checksum...) ok
+ import .git/hooks/prepare-commit-msg.sample (checksum...) ok
+ import .git/hooks/commit-msg.sample (checksum...) ok
+ import .git/hooks/post-update.sample (checksum...) ok
+ import .git/hooks/pre-push.sample (checksum...) ok
+ import .git/hooks/pre-commit (checksum...) ok
+ import .git/info/exclude (checksum...) ok
+ import .git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 (checksum...) ok
+ import .git/objects/a2/6f9bdbe47ada699d537eaa8b6fbfc1e53ef214 (checksum...) ok
+ import .git/objects/30/4b790d132863d54313e2380bed17e557944f08 (checksum...) ok
+ import .git/objects/ab/09feaa1b55080f42ccfad8c8bb5612f2397c5a (checksum...) ok
+ import .git/objects/95/b73ee41ebe8abbd5d8c0c368d1148b5256d4f2 (checksum...) ok
+ import .git/objects/2e/96f9962c1baf83c563aa59dcc67e19f21d4b1f (checksum...) ok
+ import .git/objects/74/6306e594874907246b2300b3af22f2805dde3e (checksum...) ok
+ import .git/objects/5b/11e29d0ef96be4ee73f8dae9b2f525cb808ef1 (checksum...) ok
+ import .git/objects/fc/0c0dc4d0579a15c20be29186a27feb2ee77304 (checksum...) ok
+ import .git/objects/73/c38d817e0a9f1ef4699551ae83130edd166364 (checksum...) ok
+ import .git/objects/c9/80716b5b506515410ca3ad1d88ceae13d8f6f9 (checksum...) ok
+ import .git/objects/e2/6cb10dbce11f4065c249183bb085d0afc1b55d (checksum...) ok
+ import .git/objects/80/54eeb150b094b0d8483c43ccf2ddf182c71bd3 (checksum...) ok
+ import .git/annex/sentinal (checksum...) ok
+ import .git/annex/sentinal.cache (checksum...) ok
+ import .git/annex/index (checksum...) ok
+ import .git/annex/index.lck (checksum...) ok
+ import .git/annex/journal.lck (checksum...) ok
+ import .git/annex/objects/F7/zw/SHA256E-s1048576--74f3a1a65df608d1c8ae575f83c6ee21a5aeb1a914ca73f202a881f8c3ba8f59/SHA256E-s1048576--74f3a1a65df608d1c8ae575f83c6ee21a5aeb1a914ca73f202a881f8c3ba8f59
+ git-annex: ../../git-annex-source/.git/annex/objects/F7/zw/SHA256E-s1048576--74f3a1a65df608d1c8ae575f83c6ee21a5aeb1a914ca73f202a881f8c3ba8f59/SHA256E-s1048576--74f3a1a65df608d1c8ae575f83c6ee21a5aeb1a914ca73f202a881f8c3ba8f59: rename: permission denied (Permission denied)
+ failed
+ import .git/logs/HEAD (checksum...) ok
+ import .git/logs/refs/heads/git-annex (checksum...) ok
+ import .git/logs/refs/heads/master (checksum...) ok
+ (Recording state in git...)
+ error: Invalid path 'bar/.git/COMMIT_EDITMSG'
+ error: unable to add bar/.git/COMMIT_EDITMSG to index
+ fatal: adding files failed
+
+ git-annex: user error (xargs ["-0","git","--git-dir=/home/richih/killme/git-annex-import/.git","--work-tree=/home/richih/killme/git-annex-import","add","--"] exited 123)
+ failed
+ git-annex: import: 2 failed
+ richih@eudyptes (git)-[master] ~/killme/git-annex-import/bar % ls -la
+ total 0
+ drwxr-xr-x 3 richih richih 17 Sep 24 01:45 .
+ drwxr-xr-x 4 richih richih 38 Sep 24 01:45 ..
+ drwxr-xr-x 8 richih richih 152 Sep 24 01:45 .git
+ richih@eudyptes (git)-[master] ~/killme/git-annex-import/bar %
+
+> I have made git-annex import skip .git directories. Of course,
+> running it on *any* directory without the --duplicate option
+> will result in it moving data to git-annex, so is not advisable
+> to do that if you want to keep the data in the directory where it was.
+>
+> I am doubtful about special-casing git-annex import to do something
+> else when told to import a git-annex repository. It seems a bit of a
+> slippery slope to it getting very complicated, which we seem to already be
+> further down than I would like. If people are this pissed off about
+> git-annex import's behavior,
+> I would be inclined to *remove* it. Then you can use `mv` and `git annex
+> add`. I originally wrote git-annex import just to avoid needing to run
+> those 2 commands myself, and I can make my own local shell script
+> to do that... --[[Joey]]
diff --git a/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_1_94ccd548c084286163eeb2af1ddc18e3._comment b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_1_94ccd548c084286163eeb2af1ddc18e3._comment
new file mode 100644
index 000000000..4de9cc10d
--- /dev/null
+++ b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_1_94ccd548c084286163eeb2af1ddc18e3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:21:25Z"
+ content="""
+Import skips symlinks and other non-regular files. It would work if the source repository was in direct mode.
+"""]]
diff --git a/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_2_befde3ef3d2b171ebb691915ff3af172._comment b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_2_befde3ef3d2b171ebb691915ff3af172._comment
new file mode 100644
index 000000000..9996882fc
--- /dev/null
+++ b/doc/bugs/__96__git_annex_import__96___does_not_work_on_other_git_annex_repositories/comment_2_befde3ef3d2b171ebb691915ff3af172._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="it's worse than not working, it kills! :)"
+ date="2013-10-07T12:06:22Z"
+ content="""
+so yeah, it doesn't really work well, and maybe that is to be expected because of symlinks, but it's much worse than that: the original git annex repo will actually be destroyed because git annex import will [[trash the .git metadata directory|bugs/git_annex_import_destroys_a_fellow_git_annex_repository]]. Recovering from that is... interesting, to say the least. :)
+"""]]
diff --git a/doc/bugs/__96__git_annex_sync__96___ignores_remotes.mdwn b/doc/bugs/__96__git_annex_sync__96___ignores_remotes.mdwn
new file mode 100644
index 000000000..825d9527b
--- /dev/null
+++ b/doc/bugs/__96__git_annex_sync__96___ignores_remotes.mdwn
@@ -0,0 +1,106 @@
+### Please describe the problem.
+
+A mere `git annex sync` does not go through the reachable remotes.
+
+### What steps will reproduce the problem?
+
+I do not know what could have put my repository in this state.
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 4.20130802-g1452ac3
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+
+Linux dawn 3.10.3-1-ARCH #1 SMP PREEMPT Fri Jul 26 11:26:59 CEST 2013 x86_64 GNU/Linux
+
+### Please provide any additional information below.
+
+[[!format sh """
+% git annex status
+supported backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+supported remote types: git S3 bup directory rsync web webdav glacier hook
+repository mode: direct
+trusted repositories: 1
+ f3cb4e8f-65f1-4ded-a6a1-abef64ddcff5 -- zoidberg (sam@git-annex:/media/git-annex/Music)
+semitrusted repositories: 5
+ 00000000-0000-0000-0000-000000000001 -- web
+ 063a31dc-542d-407f-a9ed-124479fa6354 -- here (dawn)
+ 22b72aa6-058b-4622-8132-27aa2d8950dc -- arrakis (sam@arrakis:~/Music)
+ 5b3a1abf-5e0b-41bc-a141-774d6236ec76 -- backup on old USB disk
+ 6affec3c-fd26-11e2-9ddd-53f02e5ca176 -- music on eeePC
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 9.83 gigabytes (+1 megabyte reserved)
+local annex keys: 3947
+local annex size: 23.51 gigabytes
+known annex keys: 3965
+known annex size: 23.56 gigabytes
+bloom filter size: 16 mebibytes (0.8% full)
+backend usage:
+ SHA256E: 7912
+
+% git remote -v
+arrakis arrakis:Music (fetch)
+arrakis arrakis:Music (push)
+zoidberg ssh://git-annex@zoidberg.rfc1149.net:2222/~/Music (fetch)
+zoidberg ssh://git-annex@zoidberg.rfc1149.net:2222/~/Music (push)
+
+# Note how here it does not seem to sync with any remote
+% git annex sync
+(Recording state in git...)
+commit
+ok
+
+% git annex sync zoidberg
+(Recording state in git...)
+commit
+ok
+pull zoidberg
+ok
+push zoidberg
+Everything up-to-date
+ok
+
+% git annex sync arrakis
+(Recording state in git...)
+commit
+ok
+pull arrakis
+From arrakis:Music
+ c1a24bd..ba060b7 git-annex -> arrakis/git-annex
+ 98b9a8e..be9c146 master -> arrakis/master
+ e0df2be..be9c146 synced/master -> arrakis/synced/master
+ok
+
+# A nameless sync with debug turned on
+% git annex sync --debug
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","symbolic-ref","HEAD"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","refs/heads/master"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","git-annex"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..ba060b7777413ab687d64771b5d6c2b36a072335","--oneline","-n1"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..f401f2b7b67567862df7c5b8d304f52c3af43f4b","--oneline","-n1"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..feaba7c5ea5f4ca73c123e6ea44ffd6333bf383e","--oneline","-n1"]
+[2013-08-06 10:59:57 CEST] chat: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","cat-file","--batch"]
+[2013-08-06 10:59:57 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","ls-files","--stage","-z","--others","--exclude-standard","--","/home/sam/Music"]
+[2013-08-06 10:59:57 CEST] chat: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","cat-file","--batch"]
+(Recording state in git...)
+[2013-08-06 11:00:16 CEST] feed: xargs ["-0","git","--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","add","-f"]
+commit
+[2013-08-06 11:00:16 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","commit","-m","git-annex automatic sync"]
+ok
+[2013-08-06 11:00:17 CEST] call: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","--verify","-q","refs/heads/synced/master"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/master..refs/heads/synced/master","--oneline","-n1"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","git-annex"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..ba060b7777413ab687d64771b5d6c2b36a072335","--oneline","-n1"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..f401f2b7b67567862df7c5b8d304f52c3af43f4b","--oneline","-n1"]
+[2013-08-06 11:00:17 CEST] read: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","log","refs/heads/git-annex..feaba7c5ea5f4ca73c123e6ea44ffd6333bf383e","--oneline","-n1"]
+[2013-08-06 11:00:17 CEST] call: git ["--git-dir=/home/sam/Music/.git","--work-tree=/home/sam/Music","branch","-f","synced/master"]
+"""]]
+
+[[done]]
diff --git a/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_1_39421e6935233cd8f45949ebdef369fe._comment b/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_1_39421e6935233cd8f45949ebdef369fe._comment
new file mode 100644
index 000000000..a88baa834
--- /dev/null
+++ b/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_1_39421e6935233cd8f45949ebdef369fe._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:13:31Z"
+ content="""
+It seems to me that you must have set `git config remote.zoidberg.annex-sync false`
+(or clicked around in the webapp and caused it to set that). If you set annex-sync back to true, it will sync with all remotes by default.
+"""]]
diff --git a/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_2_53fb15d6fbf96d43564ff7c866239d18._comment b/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_2_53fb15d6fbf96d43564ff7c866239d18._comment
new file mode 100644
index 000000000..1b870e1f7
--- /dev/null
+++ b/doc/bugs/__96__git_annex_sync__96___ignores_remotes/comment_2_53fb15d6fbf96d43564ff7c866239d18._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://www.rfc1149.net/"
+ nickname="Sam"
+ subject="Indeed"
+ date="2013-08-07T16:17:41Z"
+ content="""
+You are perfectly right. Every remote had this parameter set to false for a reason I do not know.
+"""]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow.mdwn b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow.mdwn
index 46024e500..95751527b 100644
--- a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow.mdwn
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow.mdwn
@@ -79,3 +79,9 @@ What version of git-annex are you using? On what operating system?
git-annex version: 3.20130216
On current Debian sid/experimental
+
+> [[Done]], thanks to guilhem. We ended up using a different algorythm
+> which is faster yet, basically it now does a diff-index between the
+> index and each branch for its second stage bloom filter.
+> Speedup is 30x with 0 (or 1?) branch, and then massive for each
+> additional branch. --[[Joey]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_3_12b20cbbc2b4cd1ab8af7e3eec9589b4._comment b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_3_12b20cbbc2b4cd1ab8af7e3eec9589b4._comment
new file mode 100644
index 000000000..9c1da8eea
--- /dev/null
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_3_12b20cbbc2b4cd1ab8af7e3eec9589b4._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 3"
+ date="2013-08-10T17:00:21Z"
+ content="""
+So, if I've understood it correctly (please correct me if that's not the case :) )
+
+Currently git-annex unused goes through this process
+
+* Look through all files in the index and find those which are git-annex keys (git ls-tree + git cat-file)
+* Look through all files the current ref and find those which are git-annex keys (git ls-tree + git cat-file)
+* For each ref in the repo
+ - Look through all files and find those which are git-annex keys (git ls-tree + git cat-file)
+* Then at the end
+ - Compare this list of keys with what is stored in .git/annex/objects
+ - Print out any objects which does not match a key.
+
+If that's the case, it means if that if you have multiple refs, even is they only differ by single empty commits, git-annex will end up doing a cat-file for the same file multiple times (one per ref), which is expensive.
+
+Would it be possible to change the algorithm for git-annex unused into instead something like:
+
+* For the index, HEAD, and all refs
+ - Create a list all files and remove those which are duplicates based on their sha1 hash (git ls-tree | uniq)
+* Then Look through this reduced list to find those which are git-annex keys (git cat-file)
+* Then check as before
+
+Unless this bypasses some safety or case I've overlooked, I think it should be possible to speed up git-annex unused quite a bit.
+
+"""]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_4_a50b43c15d2650df90f0fa1ced47f532._comment b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_4_a50b43c15d2650df90f0fa1ced47f532._comment
new file mode 100644
index 000000000..3de85407e
--- /dev/null
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_4_a50b43c15d2650df90f0fa1ced47f532._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 4"
+ date="2013-08-11T12:48:47Z"
+ content="""
+I think that could work. It would probably tend to use more memory than the current method, but only a small constant multiplier more. And unused is already the one command that necessarily needs to hold information about the whole repository in memory.
+
+Note that git cat-file is only needed when dealing with branches other than the current working tree. In that special case, it can, and AFAIK does have the optimisation of looking directly at the symlink target instead. Your method may turn out to be both slower and use more memory in that case. It may make sense to special case handling of that case and keep the current code paths there (most of the necessary code for it is used by other stuff anyway).
+"""]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_5_7328bc51bd001f2b732a92a2ae175839._comment b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_5_7328bc51bd001f2b732a92a2ae175839._comment
new file mode 100644
index 000000000..21890a4e1
--- /dev/null
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_5_7328bc51bd001f2b732a92a2ae175839._comment
@@ -0,0 +1,114 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 5"
+ date="2013-08-11T20:43:22Z"
+ content="""
+I've compared my bash/coreutils implementation mentioned above [annex-funused](https://gitorious.org/arand-scripts/arand-scripts/blobs/918cc79b99e22cbdca01ea4de10e2ca64abfc27a/annex-funused) with `git annex unused` in various situations, and from what I've seen `annex-funused` is pretty much always faster.
+
+In the case of no unused files they seem to be about the same.
+
+In all other cases there is a very considerable difference, for example, in my current main annex I get:
+
+ $ time git annex unused
+ unused . (checking for unused data...) (checking master...) (checking synced/master...) (checking barracuda160G/master...) ok
+
+ real 5m13.830s
+ user 2m0.444s
+ sys 0m28.344s
+
+
+whereas
+
+ $ time annex-funused
+ == WARNING ==
+ This program should NOT be trusted to reliably find unused files in the
+ git annex.
+
+
+ real 0m1.569s
+ user 0m2.024s
+ sys 0m0.184s
+
+I tried to check memory usage via `/usr/bin/time -v` as well, and that showed (re-running in the same annex as above)
+
+annex-funused
+
+ Maximum resident set size (kbytes): 13560
+
+git annex unused
+
+ Maximum resident set size (kbytes): 29120
+
+
+I've also written a comparison script [annex-testunused](https://gitorious.org/arand-scripts/arand-scripts/blobs/918cc79b99e22cbdca01ea4de10e2ca64abfc27a/annex-testunused) (needs annex-funused in $PATH) which creates an annex with a bunch of unused files and compares the running time for both versions:
+
+<pre>
+$ annex-testunused
+Initialized empty Git repository in /tmp/tmp.fmsAvsPTcd/.git/
+init ok
+(Recording state in git...)
+###
+* b2840d7 (HEAD, master) delete ~1100 files
+* c4a1e3a add 3000 files
+* bc19777 (git-annex) update
+* b3e6539 update
+* bec2c8f branch created
+annex unused
+real 0m4.154s
+real 0m2.029s
+real 0m2.044s
+annex funused
+real 0m0.923s
+real 0m0.933s
+real 0m0.905s
+Initialized empty Git repository in /tmp/tmp.7qFoCRWzB3/.git/
+init ok
+(Recording state in git...)
+###
+* a5ff392 (HEAD, master) empty
+* cca4810 (1) delete ~1100 files
+* 587c406 add 3000 files
+* de0afeb (git-annex) update
+* 37b7881 update
+* 1735062 branch created
+annex unused
+real 0m3.499s
+real 0m3.443s
+real 0m3.435s
+annex funused
+real 0m0.956s
+real 0m0.956s
+real 0m0.874s
+Initialized empty Git repository in /tmp/tmp.L5fjdAgnFv/.git/
+init ok
+(Recording state in git...)
+###
+* 94463a0 (HEAD, master) empty
+* e115619 (10) empty
+* 20686d4 (9) empty
+* 2e01a3f (8) empty
+* 043289d (7) empty
+* 6a52966 (6) empty
+* 0dc866d (5) empty
+* 35db331 (4) empty
+* 48504bc (3) empty
+* e25cac7 (2) empty
+* 655d026 (1) delete ~1100 files
+* 91a07d1 add 3000 files
+* 3c9ac62 (git-annex) update
+* c5736e0 update
+* 862d5b8 branch created
+annex unused
+real 0m16.242s
+real 0m16.277s
+real 0m16.246s
+annex funused
+real 0m0.960s
+real 0m0.960s
+real 0m0.927s
+</pre>
+
+So, unless I've missed something fundamental (I keep thinking I might have...), it seems to be very consistently faster, and scale ok where `git annex unused` scales rather poorly.
+
+"""]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_6_880ef2ee797221332dbb629b2d55522f._comment b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_6_880ef2ee797221332dbb629b2d55522f._comment
new file mode 100644
index 000000000..a4fea313f
--- /dev/null
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_6_880ef2ee797221332dbb629b2d55522f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 6"
+ date="2013-08-12T04:14:18Z"
+ content="""
+The memory usage is probably lower because `sort` and `comm` and bash's `<(command)` all have particularly well tuned memory usage with 37 years of history behind them. Particularly GNU `sort` will transparently use a temp file rather than storing too much data in memory, and does rather sophisticated stuff to make that work efficiently. It's rather harder to get that kind of behavior when not using the unix tools and instead using stock programming language primatives like sort() and hashes.
+
+I still suspect that `git cat-file` is slower than a direct readlink(2) of the symlink, when that can be done.
+"""]]
diff --git a/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_7_826fd82cdf9b1c79c9b555ca26c2c176._comment b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_7_826fd82cdf9b1c79c9b555ca26c2c176._comment
new file mode 100644
index 000000000..c2dbd1810
--- /dev/null
+++ b/doc/bugs/added_branches_makes___39__git_annex_unused__39___slow/comment_7_826fd82cdf9b1c79c9b555ca26c2c176._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 7"
+ date="2013-08-12T18:07:44Z"
+ content="""
+Hmm, probably, do you think this way of getting everything and then doing the filtering could work reasonably in git-annex? Assuming \"git cat-file --batch\" is the main bottleneck, reducing the amount of runs for it would still likely be an improvement?
+"""]]
diff --git a/doc/bugs/addurl_fails_on_the_internet_archive.mdwn b/doc/bugs/addurl_fails_on_the_internet_archive.mdwn
new file mode 100644
index 000000000..556575db6
--- /dev/null
+++ b/doc/bugs/addurl_fails_on_the_internet_archive.mdwn
@@ -0,0 +1,65 @@
+### Please describe the problem.
+
+`addurl` doesn't support the internet archive:
+
+1. it doesn't actually accept the proper URL as a secondary source of content
+2. it doesn't parse the HTML from the video page (the "details page")
+
+### What steps will reproduce the problem?
+
+ # download eben moglen's excellent re:publica presentation from youtube
+ git annex addurl https://www.youtube.com/watch?v=sKOk4Y4inVY
+ # copy that file aside
+ cp -L re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm-bak
+ # drop it so we can try again
+ git annex drop re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+ # add the IA URL for the same video, failing
+ git annex addurl --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+ # try again with --relaxed to skip some checks
+ git annex addurl --relaxed --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+ # observe both files are the same size and checksum
+
+The files should look like this:
+
+[[!format txt """
+anarcat@angela:presentations$ ls -alL re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm*
+-r--r--r-- 1 anarcat anarcat 419359123 oct 9 23:41 re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+-r--r--r-- 1 anarcat anarcat 419359123 oct 11 19:40 re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm-bak
+anarcat@angela:presentations$ md5sum re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm*
+7892df24a9e1c40e2587be1035728ef0 re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+7892df24a9e1c40e2587be1035728ef0 re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm-bak
+"""]]
+
+There are two separate bugs here: one is the above need to use --relaxed even though the file is the same.
+
+The second is probably simply that quvi doesn't support the internet archive, and maybe that one should be moved to a separate [[todo]]/[[wishlist]]. I was expecting this to "do the right thing" (ie. download the video):
+
+ git annex addurl http://archive.org/details/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia
+
+... but instead it downloads the HTML.
+### What version of git-annex are you using? On what operating system?
+
+my good old faithful `4.20130921-g434dc22` i compiled manually some time ago. :)
+
+This is [[done]] in git-annex version: 4.20131011-g2c0badc. Thanks!
+
+### Please provide any additional information below.
+
+[[!format sh """
+anarcat@marcos:presentations$ git annex addurl --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+ failed to verify url exists: http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+failed
+git-annex: addurl: 1 failed
+anarcat@marcos:presentations$ git annex addurl --debug --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+[2013-10-09 18:26:30 EDT] call: quvi ["-v","mute","--support","http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm"]
+addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm [2013-10-09 18:26:30 EDT] read: curl ["-s","--head","-L","http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm","-w","%{http_code}"]
+
+ failed to verify url exists: http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+failed
+git-annex: addurl: 1 failed
+"""]]
+
+Originally reported in [[tips/Internet_Archive_via_S3]]. --[[anarcat]]
+
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/addurl_fails_on_the_internet_archive/comment_1_e227aa25eea0b41f1176037a601c5844._comment b/doc/bugs/addurl_fails_on_the_internet_archive/comment_1_e227aa25eea0b41f1176037a601c5844._comment
new file mode 100644
index 000000000..4754b8366
--- /dev/null
+++ b/doc/bugs/addurl_fails_on_the_internet_archive/comment_1_e227aa25eea0b41f1176037a601c5844._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 1"
+ date="2013-10-11T18:49:25Z"
+ content="""
+Afaik this was fixed in 747f5b123cb3c6b3b87d4e79f8767e69d842b96b.
+
+Probably noone has bothered to add IA support to quvi, but it should be doable.
+"""]]
diff --git a/doc/bugs/addurl_fails_on_the_internet_archive/comment_2_6d4fd58f0caa1f75ee2dd3f0a909cd91._comment b/doc/bugs/addurl_fails_on_the_internet_archive/comment_2_6d4fd58f0caa1f75ee2dd3f0a909cd91._comment
new file mode 100644
index 000000000..f24d0583f
--- /dev/null
+++ b/doc/bugs/addurl_fails_on_the_internet_archive/comment_2_6d4fd58f0caa1f75ee2dd3f0a909cd91._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="awesome, fix confirmed, and IA+quvi forwarded upstream"
+ date="2013-10-12T11:23:31Z"
+ content="""
+Great! I confirm latest versions work properly.. I have [written the quvi-devel mailing list](http://sourceforge.net/mailarchive/forum.php?thread_name=20131012104904.GA11972%40angela.anarcat.ath.cx&forum_name=quvi-devel) to ask for help for archive.org support, we'll see where it goes...
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit.mdwn b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit.mdwn
new file mode 100644
index 000000000..e739b9691
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit.mdwn
@@ -0,0 +1,28 @@
+### Please describe the problem.
+
+I installed git-annex on my android device (Nook HD+, with Cyanogenmod 10.1 installed) for the first time today and was excited to get it working. However, I noticed the device warming alarmingly, and, after installing a CPU usage monitor, it became clear that git annex was the problem, as it was hovering around 30-40% even when idle.
+
+I tried quitting git-annex using the webapp's "Shutdown Daemon" menu option, and it seemed to shut down successfully, but the CPU monitor still showed that process present and taking up high amounts of CPU (sometimes well over 50%). I used the android app switcher and noticed that the terminal emulator for git annex was still running; I tried to quit this by using the X button and it seemed to close, but the CPU monitor still showed the git-annex process consuming large amounts of CPU. Finally I had to quit the process forcefully from the monitor.
+
+### What steps will reproduce the problem?
+
+Install & run; observe CPU. I used a dedicated CPU monitor to stop it the first time; another time, I tried stopping it by going to Preferences, Apps, Running Applications, where it told me it had one process and one service running. I stopped the service without issue; it said the process could not be safely stopped but I stopped it anyway and that successfully stopped the app.
+
+
+### What version of git-annex are you using? On what operating system?
+
+the current (4.20130826-g46f422) version on Android.
+
+### 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
+
+(I'm not sure how to get a log out of the web app to paste here unfortunately.
+
+# End of transcript or log.
+"""]]
+
+> [[done]]; I fixed the bug which turned out to be a stupid
+> minunderstanding of how a java library worked. --[[Joey]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_1d841ff0b0ffd814efed2449dc1f35f3._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_1d841ff0b0ffd814efed2449dc1f35f3._comment
new file mode 100644
index 000000000..892894ad4
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_1d841ff0b0ffd814efed2449dc1f35f3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 10"
+ date="2013-08-27T01:46:36Z"
+ content="""
+This seems to be a reversion instroduced in commit a48d340abdaf3296a2ddacd73c18adc9a13a02ef. With that backed out, I get 0% cpu usage for the terminal app. Even if I run top in the terminal, its CPU sits under 1%.
+
+Clearly the infinite loop in that patch is running faster than expected!
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_cd101e0af45d8f463011fb0d04b3b822._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_cd101e0af45d8f463011fb0d04b3b822._comment
new file mode 100644
index 000000000..d8ca9fb05
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_10_cd101e0af45d8f463011fb0d04b3b822._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 10"
+ date="2013-08-26T20:19:06Z"
+ content="""
+Yeah, that would definitely explain both what I'm seeing and why you haven't been seeing it.
+
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_11_8595041cfe703d9bea49e792732dc15f._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_11_8595041cfe703d9bea49e792732dc15f._comment
new file mode 100644
index 000000000..085f3d108
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_11_8595041cfe703d9bea49e792732dc15f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 11"
+ date="2013-08-27T02:27:08Z"
+ content="""
+Awesome! I'll grab a new nightly in a day or two and give it another shot.
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_1_8e7bc6965ea967a8d43240791a30c5bc._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_1_8e7bc6965ea967a8d43240791a30c5bc._comment
new file mode 100644
index 000000000..756b9d5c6
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_1_8e7bc6965ea967a8d43240791a30c5bc._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 1"
+ date="2013-08-26T18:34:44Z"
+ content="""
+Just noticed I was using the autobuild instead of the last release version; I'll try the release version and see if that makes any difference.
+
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_2_891c1073f908b204651899d41599f944._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_2_891c1073f908b204651899d41599f944._comment
new file mode 100644
index 000000000..c26c512ea
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_2_891c1073f908b204651899d41599f944._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-26T18:42:02Z"
+ content="""
+If you shut down the daemon, it seems to me that the process that was still running would probably be `git annex transferkey` which runs in its own process to upload/download file contents. I normally see 0% to 1% cpu use from git-annex when it is running on my android tablet. It's possible that the 1% use is due to it waking up every second, which got fixed in 9dc2373977d583b4c4aa6cf0555dc97309f89991.
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_3_de02b8f1b5928fa1a7078c4aa2124bea._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_3_de02b8f1b5928fa1a7078c4aa2124bea._comment
new file mode 100644
index 000000000..71ad88d74
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_3_de02b8f1b5928fa1a7078c4aa2124bea._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 3"
+ date="2013-08-26T19:03:45Z"
+ content="""
+OK, so I might have a rogue transferkey process going on, but one which starts over again when I restart the app?
+
+I've set this all up purely as a \"can I do this\" experiment right now; there is literally zero important data there to lose, either on the tablet or on the laptop, so maybe I could just write this off as a bad result of my first few shaky attempts to get the device paired with my laptop, wipe out both annexes, and start completely from scratch.
+
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_6_506acc4275a81ed9e9b08e8a40fcf96a._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_6_506acc4275a81ed9e9b08e8a40fcf96a._comment
new file mode 100644
index 000000000..553a135a0
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_6_506acc4275a81ed9e9b08e8a40fcf96a._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 6"
+ date="2013-08-26T19:38:12Z"
+ content="""
+a final note -- according to the process monitor, the process eating CPU is \"ga.androidterm\". There are also a small swarm of about 6 git processes none of which are consuming much CPU time at all.
+
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_7_d38d6f40db4c9437764c7b2ddf36b5a9._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_7_d38d6f40db4c9437764c7b2ddf36b5a9._comment
new file mode 100644
index 000000000..66a560191
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_7_d38d6f40db4c9437764c7b2ddf36b5a9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 7"
+ date="2013-08-26T20:00:39Z"
+ content="""
+It's certianly possible that the terminal app eats cpu for some reason even when sitting idle. It's hard for me to tell since I've been measuring cpu use by running top inside that terminal, which necessarily seems to use a lot of the CPU just to draw the screen.
+
+If it's the terminal at fault, it would continue after you shutdown the git-annex daemon, since that doesn't close the terminal.
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_8_9bb23e9cbc77ecca4b1209b0f66bc2b0._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_8_9bb23e9cbc77ecca4b1209b0f66bc2b0._comment
new file mode 100644
index 000000000..3fce2f21f
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_8_9bb23e9cbc77ecca4b1209b0f66bc2b0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="oh yeah, i can run top in adb.."
+ date="2013-08-26T20:14:13Z"
+ content="""
+So, I can tell that on my tablet, the terminal app is using 82% cpu while idle.
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_d1ce7fc251db076da61eed5bb9d71b9a._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_d1ce7fc251db076da61eed5bb9d71b9a._comment
new file mode 100644
index 000000000..ffd0a44be
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_d1ce7fc251db076da61eed5bb9d71b9a._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 9"
+ date="2013-08-26T20:49:34Z"
+ content="""
+(removed my earlier comments with debug info, since it wasn't relevant and I'd just as soon not display my gmail id and home machine's address on the web if I don't need to)
+
+"""]]
diff --git a/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_feb71c1022ff65d82e66a3958a41dfb2._comment b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_feb71c1022ff65d82e66a3958a41dfb2._comment
new file mode 100644
index 000000000..8f32df035
--- /dev/null
+++ b/doc/bugs/android:_high_CPU_usage__44___unclear_how_to_quit/comment_9_feb71c1022ff65d82e66a3958a41dfb2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 9"
+ date="2013-08-26T20:16:05Z"
+ content="""
+Strace doesn't show it doing anything. I suppose I should try building the terminal without the several patches I added to it to support git-annex to see if I somehow made it use all this cpu..
+"""]]
diff --git a/doc/bugs/assistant_always_assumes_port_22__63__.mdwn b/doc/bugs/assistant_always_assumes_port_22__63__.mdwn
new file mode 100644
index 000000000..27896acd4
--- /dev/null
+++ b/doc/bugs/assistant_always_assumes_port_22__63__.mdwn
@@ -0,0 +1,39 @@
+### Please describe the problem.
+git-annex assistant always assumes port 22 (I use a different port), despite my editing .ssh/config to correct this.
+
+Also, assistant doesn't give me a port option like it did in the intro screencast.
+
+### What steps will reproduce the problem?
+Using my version of git-annex, I assume.
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 3.20121112ubuntu2
+
+xubuntu 13.04
+
+### Please provide any additional information below.
+I don't see any .git/annex/daemon.log.
+
+I click the "remote server" link, sign in just fine [note below]. I click "Use a git repository on the server" (but "Use an encrypted rsync repository on the server" also does this), and eventually I get an error:
+[[!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
+Failed to make repository
+
+Something went wrong setting up the repository on the remote server.
+
+Transcript: ssh: connect to host <host> port 22: Connection timed out
+
+# End of transcript or log.
+"""]]
+
+> Your version of git-annex is too old.
+> Support for setting the port was added in version 3.20121211 --
+> about a month after the version you have installed
+> (ah, the period where everything was 11 and 12.. I don't miss it!)
+>
+> I don't recommend using such an old version of the assistant,
+> *massive* numbers of bugs have been fixed since then. Upgrade to
+> the Ubuntu PPA. [[done]] --[[Joey]]
+
+note: if I use "git-annex webapp" in the terminal it works fine; if I use xfce's "internet -> git annex" menu, it errors trying to use ssh_askpass, which I don't have. I'm going to make a new thread about this.
diff --git a/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac.mdwn b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac.mdwn
new file mode 100644
index 000000000..23babd797
--- /dev/null
+++ b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac.mdwn
@@ -0,0 +1,53 @@
+### Please describe the problem.
+Tried adding a removable drive repository through git-annex assistant on Mac, asked to encrypt it, got Internal server error with explanation: unable to determine gcrypt-id of remote
+
+### What steps will reproduce the problem?
+current (today's) version of git-annex build for Mountain Lion installed
+app launched
+default annex initialized, a couple file added
+a removable 2GB USB drive (ExFAT) mounted in OS
+click Add another repository
+choose removable drive
+choose to encrypt
+a window explaining the need to wait for entropy shows
+then we get the Internal server error: unable to determine gcrypt-id of remote
+
+### What version of git-annex are you using? On what operating system?
+git-annex version 4.20130922-g7dc188a
+Mac OS X 10.8.5
+
+### Please provide any additional information below.
+
+looking at transcript below, it appears the root cause is the lack of initial git/gcrypt configuration. perhaps this needs to be caught/addressed somehow
+
+[[!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
+
+gpg: can't open `/usr/local/share/gnupg/options.skel': No such file or directory
+.......+++++
+.+++++
+gpg: key 71BFBC31 marked as ultimately trusted
+ok
+(Recording state in git...)
+(Recording state in git...)
+(encryption setup) (hybrid cipher with gpg key C4B2EA8D71BFBC31) gcrypt: Development version -- Repository format MAY CHANGE
+gpg: checking the trustdb
+gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
+gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
+gcrypt: WARNING: Skipping missing key C4B2EA8D71BFBC31
+gcrypt: You have not configured any keys you can encrypt to for this repository
+gcrypt: Use ::
+gcrypt: git config gcrypt.participants YOURKEYID
+gcrypt: Development version -- Repository format MAY CHANGE
+gcrypt: WARNING: Skipping missing key C4B2EA8D71BFBC31
+gcrypt: You have not configured any keys you can encrypt to for this repository
+gcrypt: Use ::
+gcrypt: git config gcrypt.participants YOURKEYID
+03/Oct/2013:00:05:24 +0400 [Error#yesod-core] unable to determine gcrypt-id of remote @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+
+
+# End of transcript or log.
+"""]]
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_1_4ea192e57f86a33087997746722e6acf._comment b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_1_4ea192e57f86a33087997746722e6acf._comment
new file mode 100644
index 000000000..2d0802cae
--- /dev/null
+++ b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_1_4ea192e57f86a33087997746722e6acf._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 1"
+ date="2013-10-02T20:37:03Z"
+ content="""
+Can you take a look at ~/annex/.git/config and if there is an entry for this git remote, post it? (Or post the whole thing if unsure..)
+
+Also, can you get gpg to list your secret keys, and see if key 71BFBC31 is in the list? You can do so by running `gpg --list-secret-keys` ; if you don't have gpg in your path at the terminal, you can use the version from the git-annex DMG by first running `/Volumes/git-annex/git-annex.app/Contents/MacOS/runshell`
+"""]]
diff --git a/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_2_622ad5b34780fc8468c5c515ad9f27fa._comment b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_2_622ad5b34780fc8468c5c515ad9f27fa._comment
new file mode 100644
index 000000000..2ba7a5984
--- /dev/null
+++ b/doc/bugs/assistant_bails_when_adding_encrypted_usbdrive_repo_on_mac/comment_2_622ad5b34780fc8468c5c515ad9f27fa._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnyMzZZLS1xGW1raqc_9Md6Ksdkvx5rUJU"
+ nickname="Michael"
+ subject="comment 2"
+ date="2013-10-04T10:59:30Z"
+ content="""
+Sorry Joey, I was tinkering around trying to get the assistant off the ground and have destroyed the evidence of the bug in the process. I will try to recreate it and post the details. (most of my problems are/were related to bundled git/gpg/other software, I posted a separate comment in OSX Install page)
+"""]]
diff --git a/doc/bugs/assistant_does_not_allow_adding_an_existing_repo.mdwn b/doc/bugs/assistant_does_not_allow_adding_an_existing_repo.mdwn
new file mode 100644
index 000000000..8a6218c04
--- /dev/null
+++ b/doc/bugs/assistant_does_not_allow_adding_an_existing_repo.mdwn
@@ -0,0 +1,8 @@
+The assistant does not allow adding an existing repo: I tried to add a "remote server", to enter the credits, and then I add to choose between "git-annex" or "rsync". Choosing "git-annex" tries to create a new repo and then fails. The repo on the server is a bare one, accessed via gitolite. Setting the remote manually ("git remote add origin git@example.org:my-annex.git" works (I can pull, push, ...))
+
+Mac OS 10.7 version 2013-09-10
+
+
+[[!meta title="assistant does not interoperate with gitolite when adding a repository"]]
+
+[2013-09-13 17:00:55 CEST] chat: ssh ["-p","22","git@example.org","sh -c 'mkdir -p '\"'\"'my-annex.git'\"'\"'&&cd '\"'\"'my-annex.git'\"'\"'&&if [ ! -d .git ]; then git init --bare --shared; fi&&git annex init'"]
diff --git a/doc/bugs/assistant_does_not_allow_adding_an_existing_repo/comment_1_87e84d56d56abefe8cac8a52b76c9003._comment b/doc/bugs/assistant_does_not_allow_adding_an_existing_repo/comment_1_87e84d56d56abefe8cac8a52b76c9003._comment
new file mode 100644
index 000000000..b260b8df5
--- /dev/null
+++ b/doc/bugs/assistant_does_not_allow_adding_an_existing_repo/comment_1_87e84d56d56abefe8cac8a52b76c9003._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 1"
+ date="2013-09-13T18:19:03Z"
+ content="""
+I suppose the assistant could try to add a git remote and pull from it, and only if this pull fails go try to run shell commands to create it. This might work with gitolite, gitosis, github, etc. Although only partially for ones that don't support running git-annex-shell..
+"""]]
diff --git a/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_3_f9b2a700c060707fae1bcb2ec0e4e4dc._comment b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_3_f9b2a700c060707fae1bcb2ec0e4e4dc._comment
new file mode 100644
index 000000000..757a1c727
--- /dev/null
+++ b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_3_f9b2a700c060707fae1bcb2ec0e4e4dc._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmOsy6nbvPyXLd--qqjPMLnVIzxgZwtKlQ"
+ nickname="Nicolas"
+ subject="comment 3"
+ date="2013-09-11T23:19:26Z"
+ content="""
+This behaviour is indeed very confusing when one attempts to use git-annex with the assistant only, without thinking about the underlying machinery.
+Having the assistant automatically put a .gitignore file in empty directories is a possible solution, but maybe printing a warning in the log when the watcher sees an empty directory could be an unobtrusive and helpful solution? (At least it would have helped me)
+"""]]
diff --git a/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_4_014d213a959dd7993bdd247722a8817e._comment b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_4_014d213a959dd7993bdd247722a8817e._comment
new file mode 100644
index 000000000..f6be08ae4
--- /dev/null
+++ b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_4_014d213a959dd7993bdd247722a8817e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmOsy6nbvPyXLd--qqjPMLnVIzxgZwtKlQ"
+ nickname="Nicolas"
+ subject="comment 4"
+ date="2013-09-11T23:24:58Z"
+ content="""
+Another problem with the current behaviour is that when deleting a directory and its contents on a repository, the contents are deleted on the other repositories but empty directories are left behind...
+"""]]
diff --git a/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_5_440f349781d7d9ca2d1ed81386f7dd26._comment b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_5_440f349781d7d9ca2d1ed81386f7dd26._comment
new file mode 100644
index 000000000..0d5f0aa29
--- /dev/null
+++ b/doc/bugs/assistant_doesn__39__t_sync_empty_directories/comment_5_440f349781d7d9ca2d1ed81386f7dd26._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 5"
+ date="2013-11-01T22:12:04Z"
+ content="""
+I agree that this is very confusing. Also having to manually delete empty, renamed directories is...less than ideal. :)
+"""]]
diff --git a/doc/bugs/assistant_doesn__39__t_sync_file_permissions/comment_3_4d5ae51b4c7e6177d934d7c9f21b912c._comment b/doc/bugs/assistant_doesn__39__t_sync_file_permissions/comment_3_4d5ae51b4c7e6177d934d7c9f21b912c._comment
new file mode 100644
index 000000000..6bf189414
--- /dev/null
+++ b/doc/bugs/assistant_doesn__39__t_sync_file_permissions/comment_3_4d5ae51b4c7e6177d934d7c9f21b912c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 3"
+ date="2013-11-02T23:49:49Z"
+ content="""
+Dropbox handles permissions, e.g. if I \"chmod -x\" a file on one system, it does the same to my other systems. It would be a bit of a step backward if git-annex can't do this. :/ Just my two cents.
+"""]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual.mdwn b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual.mdwn
new file mode 100644
index 000000000..c5a75b361
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual.mdwn
@@ -0,0 +1,24 @@
+Thanks for git annex!
+
+### Please describe the problem.
+
+I've set up two computers A, B to sync to (and each other through) a remote server S. If I add files to A, it syncs with S. But B is not getting synced unless I run 'git annex sync' or restart the daemon in the webapp, i.e. I don't see these files on B at all, not even as broken symlinks.
+The same happens if I manually copy files from A to S. B is not updating the copy count in 'git annex whereis' until I manually sync on B.
+
+It would be great if B could automatically sync when S is changed, either file locations or contents.
+
+### What steps will reproduce the problem?
+
+Both computers' local repos were setup with annex assistant, and switched into indirect mode. The server contains git repo and file data. All systems, computers and server are set to manual in the preferred content mode.
+
+### What version of git-annex are you using? On what operating system?
+
+A is running Debian testing with git-annex 4.20130827, B and S are running Debian stable with the backports version of git-annex 4.20130815~bpo70+1. A and S are 64 bit, B is 32 bit. All are up to date.
+
+### Please provide any additional information below.
+
+I tried this setup before with direct mode and different preferred content settings (A, B as client, S as backup or archive), and syncing of git and file data was working then.
+
+Despite being able to run 'sync' it is at least inconvenient to not have automatically updated file location information when I run the assistant. (I could then just run without it, but I had it happen to me that I setup a local repo w/o assistant, and when I ran assistant, expecting it would tell me "there are no local repos, would you like to create one?" it somehow automatically found the manually created one and started copying files. But that's another problem.)
+
+> [[done]] unless my diagnosis is wrong. --[[Joey]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_1_37acb3afafb1b4c4da7c778130cf3035._comment b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_1_37acb3afafb1b4c4da7c778130cf3035._comment
new file mode 100644
index 000000000..94dc51d0a
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_1_37acb3afafb1b4c4da7c778130cf3035._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlQsgfXntaEvZPKgd_K0dfoFcYBJXKcaFE"
+ nickname="Sten"
+ subject="Direct oder indirect mode makes no difference"
+ date="2013-09-09T23:36:49Z"
+ content="""
+Direct or indirect mode does not make a difference. I created another setup like this, only different is direct mode, otherwise the same (in particular preferred content mode is manual). Result: Still no sync.
+"""]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_2_9d58887ee0184663852bde83b8d497c7._comment b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_2_9d58887ee0184663852bde83b8d497c7._comment
new file mode 100644
index 000000000..8d388ceee
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_2_9d58887ee0184663852bde83b8d497c7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlQsgfXntaEvZPKgd_K0dfoFcYBJXKcaFE"
+ nickname="Sten"
+ subject="computer in manual mode seems to be the reason, not server"
+ date="2013-09-10T02:21:59Z"
+ content="""
+If I create a setup like originally described with the only difference being S set to full backup mode, I see no change in sync behavior.
+
+In detail, what happens is: A gets files added. These changes are committed and synced. Because S is in full backup mode, the file content is also sent from A to S (this is different, but expected). However, B still does not sync until manually run. I would expect that B's manual mode only applies to file content (it is the preferred content setting), not to changes to the git repo, thus I'd expect git changes to sync to all involved (and accessible) repos.
+"""]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_3_b70881c8026e30fd3ddc051bd01a888b._comment b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_3_b70881c8026e30fd3ddc051bd01a888b._comment
new file mode 100644
index 000000000..d42cf6cd2
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_3_b70881c8026e30fd3ddc051bd01a888b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlQsgfXntaEvZPKgd_K0dfoFcYBJXKcaFE"
+ nickname="Sten"
+ subject="available copies update need manual sync too"
+ date="2013-09-10T02:55:44Z"
+ content="""
+After copying files from S to B (as expected manually), I have to (unexpectedly) manually sync again on A to update the #copies on A.
+"""]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_4_43f756e2e6ff985c8e050da0e369d486._comment b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_4_43f756e2e6ff985c8e050da0e369d486._comment
new file mode 100644
index 000000000..51e9cc135
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_4_43f756e2e6ff985c8e050da0e369d486._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlQsgfXntaEvZPKgd_K0dfoFcYBJXKcaFE"
+ nickname="Sten"
+ subject="output of git annex sync "
+ date="2013-09-10T03:19:51Z"
+ content="""
+When running sync on B after copying file content from A to S (manually or automatically), I saw the following output (copied just the end of it):
+ ...
+ file.pdf | 1 +
+ file.txt | 1 +
+ 762 files changed, 762 insertions(+)
+ ...
+ create mode 120000 file.pdf
+ create mode 120000 file.txt
+
+git-annex: /home/sten/Documents/.git/annex/merge/: getDirectoryContents: does not exist (No such file or directory)
+failed
+push server
+Everything up-to-date
+ok
+git-annex: sync: 1 failed
+
+A subsequent sync worked without error.
+
+"""]]
diff --git a/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_5_eda947eb7f8c46b9a61d6430b5f9ebfd._comment b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_5_eda947eb7f8c46b9a61d6430b5f9ebfd._comment
new file mode 100644
index 000000000..05a3d7f74
--- /dev/null
+++ b/doc/bugs/assistant_fails_to_sync_in_preferred_content_mode_manual/comment_5_eda947eb7f8c46b9a61d6430b5f9ebfd._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 5"
+ date="2013-09-13T18:30:53Z"
+ content="""
+You have described the following git-annex network:
+
+ A --(ssh)-- S --(ssh)-- B
+
+So A automatically syncs to S. But there is no way at all for A to tell B that it has made changes. So B does not automatically sync.
+
+The git-annex webapp will detect this kind of situation, and display this alert:
+
+[[assistant/xmppnudge.png]]
+
+Once you set up an XMPP account, the network will look like:
+
+ A --(ssh)-- S --(ssh)-- B
+ \_________(XMPP)_______/
+
+And now B will immediatly know when A has pushed a change to S, and will go get it.
+
+(The `getDirectoryContents` error is probably because you are running git annex sync in a repository that the git-annex assistant is running in, and they are both using the same tmp directory for merging branches sync pulled. It does not seem to be worth worrying about.)
+"""]]
diff --git a/doc/bugs/assistant_ignore_.gitignore/comment_2_22f75af80c779dcb4d6033b90373f74e._comment b/doc/bugs/assistant_ignore_.gitignore/comment_2_22f75af80c779dcb4d6033b90373f74e._comment
new file mode 100644
index 000000000..893be9055
--- /dev/null
+++ b/doc/bugs/assistant_ignore_.gitignore/comment_2_22f75af80c779dcb4d6033b90373f74e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnNqLKszWk9EoD4CDCqNXJRIklKFBCN1Ao"
+ nickname="maurizio"
+ subject="git-annex from wheezy-backports should depend on a more recent git version on debian wheezy (7.2) "
+ date="2013-11-12T18:57:52Z"
+ content="""
+It is correct that the bug is solved on the git-annex package found on wheezy-backports, but this package does not force an update of git to a more recent version. Therefore the bug still affects wheezy users. The way to solve it is to install git also from wheezy-backports.
+
+
+"""]]
diff --git a/doc/bugs/assistant_ignore_.gitignore/comment_3_8b2a400e1d44a1c9b183e2b7861efbe3._comment b/doc/bugs/assistant_ignore_.gitignore/comment_3_8b2a400e1d44a1c9b183e2b7861efbe3._comment
new file mode 100644
index 000000000..e58d46084
--- /dev/null
+++ b/doc/bugs/assistant_ignore_.gitignore/comment_3_8b2a400e1d44a1c9b183e2b7861efbe3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 3"
+ date="2013-11-12T19:10:48Z"
+ content="""
+Agreed, I've made the changes so the next update of the backport will do so.
+"""]]
diff --git a/doc/bugs/authentication_to_rsync.net_fails.mdwn b/doc/bugs/authentication_to_rsync.net_fails.mdwn
new file mode 100644
index 000000000..707f93d49
--- /dev/null
+++ b/doc/bugs/authentication_to_rsync.net_fails.mdwn
@@ -0,0 +1,30 @@
+### Please describe the problem.
+
+Used assistant to "Add a cloud repository". Supplied hostname, username in webapp. Directory "annex" port 22.
+Clicked on "Use this rsync.net repository" and got
+
+**********************
+ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
+ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
+ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
+Received disconnect from 69.43.165.7: 2: Too many authentication failures for 2440
+**********************
+
+### What steps will reproduce the problem?
+See above? A simple "ssh user@host.rsync.net ls /usr/bin" reveals that indeed no ssh-askpass is available in that namespace.
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20130521 on debian linux 7.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
+
+That log is empty.
+# End of transcript or log.
+"""]]
+
+> I added ssh-askpass as a recommends, so I suppose
+> I can close this. [[done]] --[[Joey]]
diff --git a/doc/bugs/authentication_to_rsync.net_fails/comment_1_9db65f89415c8d825f268afb75244998._comment b/doc/bugs/authentication_to_rsync.net_fails/comment_1_9db65f89415c8d825f268afb75244998._comment
new file mode 100644
index 000000000..731d5148f
--- /dev/null
+++ b/doc/bugs/authentication_to_rsync.net_fails/comment_1_9db65f89415c8d825f268afb75244998._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawliqfHEW134uawIUPwyKiyOdoF-oI5TxnQ"
+ nickname="Ethan"
+ subject="Doh. /usr/bin/ssh-askpass needs to be on *local* machine."
+ date="2013-08-15T20:13:31Z"
+ content="""
+My mistake; the problem was the I was missing /usr/bin/ssh-askpass on my local machine, not the rsync.net host.
+
+I still think this is a bug. I'm on a debian machine and installed git-annex from its debian package, so seems like the ssh-askpass package should be listed as a dependency. But that's a debian packaging problem, not a git-annex bug per se, so I'll go file it elsewhere.
+"""]]
diff --git a/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_3_51da7f5881f65422328d341e5ab0d250._comment b/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_3_51da7f5881f65422328d341e5ab0d250._comment
new file mode 100644
index 000000000..4cf86f646
--- /dev/null
+++ b/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_3_51da7f5881f65422328d341e5ab0d250._comment
@@ -0,0 +1,33 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="I'm afraid I'm getting this too"
+ date="2013-09-12T12:48:04Z"
+ content="""
+Very similar setup. Initially set up on a Mac, then tried to set up the first local pairing with a Linux system. Basically seeing exactly the same thing.
+
+ bad comment in ssh public key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDa09lpmgLeRVF1KZn2gX6tmBH4Jpcou/rkPbhwLoFNLtQsdNrbjDKuyc4pDbUhexWVvub1YCLItLK0vYRdMvoJWjNzy926sHs8CxXFVg6PMQXw3wOHousSn0NkVfwUMNn5aS+1vz/WDlStmg7WzXgiPg1Whn6CKIomxA63rUMe3I+2nVkyO6jGlOkliPApVP2utURJbyxBDYDB+Ys7zUxvEcCekhxJO263myuo2gwI4A3mfTLRJMzbz8frRZJz5iuUIcOHaIDy6n0qKFq18BDux4SDwNjQ34yti5yqveRBMwFndHQYN6YHk1k26h0kyhb2T6lXaaAirSqa3dwfZuKp rachel@celestia.local
+
+
+# Versions and Stuff:
+
+## Mac:
+
+* OS X 10.8.4
+* git-annex 4.20130909-ga29f960 (downloaded about half an hour ago!)
+* BTW I have git installed from Homebrew, version 1.8.3.4 in my shell's $PATH, but obviously /usr/bin/git from the system is intact.
+* Hostname: celestia.local
+* Username: rachel
+
+## Linux:
+* Ubuntu 13.04
+* git-annex 3.20121112ubuntu4 (from Ubuntu's own repos)
+* I note that's later than the version you said this bug was fixed in, hence the report. :-)
+* Hostname: twilight.local (mDNS domain not appended even by hostname -f but avahi is working)
+* Username: rachel
+
+IPv6 is active, but I note a comment somewhere that that's probably not relevant for git-annex.
+
+Machines are very local to each other, in the same room, connected via a gigabit switch. They can definitely see each other. :-)
+
+"""]]
diff --git a/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_4_ba384314c1e47ec4b72e1843e0500df9._comment b/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_4_ba384314c1e47ec4b72e1843e0500df9._comment
new file mode 100644
index 000000000..4b9e27bba
--- /dev/null
+++ b/doc/bugs/bad_comment_in_ssh_public_key_ssh-rsa/comment_4_ba384314c1e47ec4b72e1843e0500df9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmpBDWko1yZmngBYzm_CeBv8RjoIMXaINE"
+ nickname="Rachel"
+ subject="latest works"
+ date="2013-09-12T13:19:09Z"
+ content="""
+Downloaded the latest tarball (4.20130911-g6625d0e) and that seems to be able to pair ok.
+
+Different bug though: It objects to push.default = simple in ~/.gitconfig, but no such complaint on osx. But that's a different bug; i'll report separately when I'm a bit more up to speed.
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing..mdwn b/doc/bugs/box.com_never_stops_syncing..mdwn
new file mode 100644
index 000000000..42b2eaf1a
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing..mdwn
@@ -0,0 +1,63 @@
+### Please describe the problem.
+Git-annex will constantly sync most(if not all) my files to box.com
+
+### What steps will reproduce the problem?
+1 - Use git-annex instead of Dropbox at work
+2 - Boot computer.
+3 - Watch it sync everything to box.com (even files i believe it has transferred each and every day for the last few months)
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20130827
+
+But i have never seen it work satisfactory in any version.
+
+Also, i have seen this is 10+ different clean git-annexes. So it isn't annex specific.
+
+### Please provide any additional information below.
+
+I am going to add more debug to this bug constantly. (I intend to do a full 'git annex copy --to box.com --not --in box.com' daily, and see if the same files are transfered again and again)
+
+
+For now, i see a few different issues already:
+
+
+[[!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
+
+
+tou@DSK1049:~/work-annex$ git annex copy --to box.com --not --in box.com 2>&1 | tee ../work-annex-copy-to-box.com-not-in-box.com-run1.log
+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","git-annex"]
+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","show-ref","--hash","refs/heads/git-annex"]
+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..dbe8b1cfa5f84126c45a39fdc7c7f26e272c71cc","--oneline","-n1"]
+[2013-09-11 09:24:53 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..45e279375897a2cd7f5b893402e0ec25c1b23436","--oneline","-n1"]
+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..c4921be4434f751493fce1c932ac759214abacd4","--oneline","-n1"]
+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","log","refs/heads/git-annex..d591398dc1cac824a5fc5bdacdcb82301a9b15a3","--oneline","-n1"]
+[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]
+[2013-09-11 09:24:54 CEST] read: git ["config","--null","--list"]
+[2013-09-11 09:24:54 CEST] read: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","ls-files","--cached","-z","--"]
+[2013-09-11 09:24:54 CEST] chat: git ["--git-dir=/home/tou/work-annex/.git","--work-tree=/home/tou/work-annex","cat-file","--batch"]
+copy Documents/Gamle catillo overførsler/Rapport b-bm.odt (gpg) (checking box.com...) ok
+copy Documents/Gamle catillo overførsler/Rapport brandt skorstensfejeren.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/4a5/18e/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1/GPGHMACSHA1--5f8660edac93899cf9adc5fadcc480ddc2992bb1.chunkcount) failed
+copy Documents/Gamle catillo overførsler/Rapport teamkoege.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/98d/ae7/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44/GPGHMACSHA1--5253241407527aa6c980f1174fdbc32713c54c44.chunkcount) failed
+copy Documents/Gamle catillo overførsler/Rapport vikarborsen.odt (checking box.com...) ok
+copy Documents/Gamle catillo overførsler/Rapport-terrariemesteren.odt (checking box.com...) ok
+copy Documents/Gamle catillo overførsler/catillo-efhandel.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/9d9/aea/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52/GPGHMACSHA1--1516eac1ec7b4ceaa840faebabde1f50f5db0a52.chunkcount) failed
+copy Documents/Nøgeordsanalyse catillo104.xlsx (checking box.com...) (ResponseTimeout) failed
+copy Documents/Søgeordsliste.txt (checking box.com...) ok
+copy Documents/catillo guide.odt (checking box.com...) ok
+copy Documents/guide bruger oprettelse.odt (checking box.com...) (failed to read https://www.box.com/dav/work-annex/49e/175/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c/GPGHMACSHA1--2b47737f8de7faac7704eaa322785edad63a921c.chunkcount) failed
+copy Documents/guide skift backup bånd.odt (checking box.com...) ok
+copy Documents/lilletest.csv (checking box.com...) (failed to read https://www.box.com/dav/work-annex/915/373/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33/GPGHMACSHA1--49ba3d5f63c012ae2cd2c0fc3e729178b1023c33.chunkcount) failed
+copy Dropbox/adams-scraper/CommonFunctions.py (checking box.com...) (ResponseTimeout) failed
+copy Dropbox/adams-scraper/__pycache__/CommonFunctions.cpython-33.pyc (checking box.com...) (to box.com...) [2013-09-11 09:28:30 CEST] chat: gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--batch","--passphrase-fd","14","--symmetric","--force-mdc"]
+
+100% 0.0 B/s 0sResponseTimeout
+ResponseTimeout
+failed
+
+
+# End of transcript or log.
+"""]]
+
+More to come(full log)
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_1_124a5edcd89cc6b61e1a41f5b4d640d7._comment b/doc/bugs/box.com_never_stops_syncing./comment_1_124a5edcd89cc6b61e1a41f5b4d640d7._comment
new file mode 100644
index 000000000..ee1c88cc7
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_1_124a5edcd89cc6b61e1a41f5b4d640d7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T20:29:14Z"
+ content="""
+It seems you are getting a lot of timeouts from box.com, both when checking if content is present there and when uploading content that it does not have.
+
+I have heard some grumbles about box.com not being very reliable right now.
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_2_42574181aa721319ba54eadf0a15ddff._comment b/doc/bugs/box.com_never_stops_syncing./comment_2_42574181aa721319ba54eadf0a15ddff._comment
new file mode 100644
index 000000000..5a0cde548
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_2_42574181aa721319ba54eadf0a15ddff._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 2"
+ date="2013-09-12T20:54:33Z"
+ content="""
+The problem being. I've used box.com with one of my own hooks(owncloud), where it is completely stable!
+
+The instability is not a the box.com end.
+
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_3_2ad727849070cfd52d6c719478e9cce3._comment b/doc/bugs/box.com_never_stops_syncing./comment_3_2ad727849070cfd52d6c719478e9cce3._comment
new file mode 100644
index 000000000..5eab58b3f
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_3_2ad727849070cfd52d6c719478e9cce3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 3"
+ date="2013-09-12T20:56:44Z"
+ content="""
+git-annex is using box.com's WebDAV interface. Is owncloud?
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_4_83ce23e45f5a5845d4f04519ee14ec65._comment b/doc/bugs/box.com_never_stops_syncing./comment_4_83ce23e45f5a5845d4f04519ee14ec65._comment
new file mode 100644
index 000000000..eb9dc5134
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_4_83ce23e45f5a5845d4f04519ee14ec65._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 4"
+ date="2013-09-12T21:33:29Z"
+ content="""
+It uses the following url https://www.box.com/dav
+
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_5_ef1c9d87b04db5047ab72167d3269687._comment b/doc/bugs/box.com_never_stops_syncing./comment_5_ef1c9d87b04db5047ab72167d3269687._comment
new file mode 100644
index 000000000..9d9c1329b
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_5_ef1c9d87b04db5047ab72167d3269687._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 5"
+ date="2013-09-12T21:44:32Z"
+ content="""
+It may be that there is a timeout in the http library that I am using for webdav that is too low. See <https://github.com/snoyberg/http-conduit/issues/137>
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_6_c9cb39eba941678035f9b2888da1085c._comment b/doc/bugs/box.com_never_stops_syncing./comment_6_c9cb39eba941678035f9b2888da1085c._comment
new file mode 100644
index 000000000..5eaf4f4bb
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_6_c9cb39eba941678035f9b2888da1085c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 6"
+ date="2013-09-12T21:49:05Z"
+ content="""
+That would probably do it. With other implementations(fuse mount) i've seen stalls and other bad behaviour with that DAV server.
+
+The owncloud hook doesn't have a timeout set. It probably should have one to prevent a total stall.
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_7_4b0632a4e37c96959a8e6434e9fd86fb._comment b/doc/bugs/box.com_never_stops_syncing./comment_7_4b0632a4e37c96959a8e6434e9fd86fb._comment
new file mode 100644
index 000000000..2ac3f360e
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_7_4b0632a4e37c96959a8e6434e9fd86fb._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="Logs"
+ date="2013-09-13T11:43:22Z"
+ content="""
+So have two days of logs now, and it doesn't look like it is retrying old files.
+
+http://paste.ubuntu.com/6101255/ <- day 1
+
+http://paste.ubuntu.com/6101256/ <- day 2
+
+Setting the computer to do the following loop over the weekend, lets see if everything is done come monday.
+
+for i in `seq 3 2000`; do git annex copy --to box.com --not --in box.com 2>&1 | tee ../work-annex-copy-to-box.com-not-in-box.com-run$i.log; done
+
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_8_d9d318b8c958de6031ae323da20af625._comment b/doc/bugs/box.com_never_stops_syncing./comment_8_d9d318b8c958de6031ae323da20af625._comment
new file mode 100644
index 000000000..8dfbd6944
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_8_d9d318b8c958de6031ae323da20af625._comment
@@ -0,0 +1,55 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWg4VvDTer9f49Y3z-R0AH16P4d1ygotA"
+ nickname="Tobias"
+ subject="Update"
+ date="2013-09-18T11:17:33Z"
+ content="""
+Only just got back to work now. The script has done 10 iteration. This is the status:
+
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run1.log |grep \" ok\"| wc -l
+137
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run2.log |grep \" ok\"| wc -l
+77
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run3.log |grep \" ok\"| wc -l
+116
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run4.log |grep \" ok\"| wc -l
+70
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run5.log |grep \" ok\"| wc -l
+26
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run6.log |grep \" ok\"| wc -l
+6
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run7.log |grep \" ok\"| wc -l
+6
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run8.log |grep \" ok\"| wc -l
+0
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run9.log |grep \" ok\"| wc -l
+0
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run10.log |grep \" ok\"| wc -l
+0
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run11.log |grep \" ok\"| wc -l
+0
+
+tou@DSK1049:~$ cat work-annex-copy-to-box.com-not-in-box.com-run12.log |grep \" ok\"| wc -l
+0
+
+I have all the log files of course.
+
+tou@DSK1049:~/work-annex$ git annex find --not --in box.com| wc -l
+1639
+
+So, of the last 5 iteration 0 files of 1639 missing were transfered. Most of these files are <10kbyte
+
+http://paste.ubuntu.com/6123459/ <- pastebin of work-annex-copy-to-box.com-not-in-box.com-run11.log if it is of any use.
+
+"""]]
diff --git a/doc/bugs/box.com_never_stops_syncing./comment_9_689ac6a4a305197cf5566f98dab47b4b._comment b/doc/bugs/box.com_never_stops_syncing./comment_9_689ac6a4a305197cf5566f98dab47b4b._comment
new file mode 100644
index 000000000..99a0eb9ae
--- /dev/null
+++ b/doc/bugs/box.com_never_stops_syncing./comment_9_689ac6a4a305197cf5566f98dab47b4b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 9"
+ date="2013-09-28T19:34:42Z"
+ content="""
+Filed a bug on the DAV library about this: <http://bugs.debian.org/724856>
+"""]]
diff --git a/doc/bugs/build_fails_in_Assistant__47__WebApp__47__Gpg.hs.mdwn b/doc/bugs/build_fails_in_Assistant__47__WebApp__47__Gpg.hs.mdwn
new file mode 100644
index 000000000..172f28143
--- /dev/null
+++ b/doc/bugs/build_fails_in_Assistant__47__WebApp__47__Gpg.hs.mdwn
@@ -0,0 +1,57 @@
+### Please describe the problem.
+
+Building from git fails in Assistant/WebApp/Gpg.hs
+
+### What steps will reproduce the problem?
+
+Follow instructions at <http://git-annex.branchable.com/install/cabal/> for building from git:
+
+[[!format sh """
+cabal update
+PATH=$HOME/bin:$PATH
+cabal install c2hs --bindir=$HOME/bin
+cabal install --only-dependencies
+cabal configure
+cabal build
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+
+git master (7da58f3ebf8), openSUSE 12.3
+
+### Please provide any additional information below.
+
+[[!format txt """
+# 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
+
+Assistant/WebApp/Configurators/Fsck.hs:69:35:
+ Warning: This binding for `u' shadows the existing binding
+ bound at Assistant/WebApp/Configurators/Fsck.hs:60:17
+
+Assistant/WebApp/Configurators/Fsck.hs:126:11:
+ Warning: This binding for `check' shadows the existing binding
+ imported from `Assistant.WebApp.Common' at Assistant/WebApp/Configurators/Fsck.hs:16:1
+-30
+ (and originally defined in `Yesod.Form.Functions')
+[322 of 371] Compiling Assistant.TransferQueue ( Assistant/TransferQueue.hs, dist/build/git-annex/git
+-annex-tmp/Assistant/TransferQueue.o )
+[323 of 371] Compiling Assistant.Threads.Glacier ( Assistant/Threads/Glacier.hs, dist/build/git-annex
+/git-annex-tmp/Assistant/Threads/Glacier.o )
+[324 of 371] Compiling Assistant.Threads.Merger ( Assistant/Threads/Merger.hs, dist/build/git-annex/g
+it-annex-tmp/Assistant/Threads/Merger.o )
+[325 of 371] Compiling Assistant.Threads.Cronner ( Assistant/Threads/Cronner.hs, dist/build/git-annex
+/git-annex-tmp/Assistant/Threads/Cronner.o )
+[326 of 371] Compiling Assistant.MakeRemote ( Assistant/MakeRemote.hs, dist/build/git-annex/git-annex
+-tmp/Assistant/MakeRemote.o )
+[327 of 371] Compiling Assistant.WebApp.Gpg ( Assistant/WebApp/Gpg.hs, dist/build/git-annex/git-annex
+-tmp/Assistant/WebApp/Gpg.o )
+
+Assistant/WebApp/Gpg.hs:88:40:
+ Not in scope: type constructor or class `MonadIO'
+ Perhaps you meant `Monad' (imported from Assistant.WebApp.Common)
+
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/cabal_install_fails_to_install_manpage.mdwn b/doc/bugs/cabal_install_fails_to_install_manpage.mdwn
new file mode 100644
index 000000000..265ad2432
--- /dev/null
+++ b/doc/bugs/cabal_install_fails_to_install_manpage.mdwn
@@ -0,0 +1,43 @@
+### Please describe the problem.
+
+The git-annex manual page is not installed when using [[install/cabal]] to install git-annex.
+
+### What steps will reproduce the problem?
+
+Follow [[install/cabal]] with `--bin-dir=/usr/local` and try `man git-annex`.
+
+I was expecting the manpage to be installed in `/usr/local/share/man`.
+
+### What version of git-annex are you using? On what operating system?
+
+git annex from a recent git build (4.20130909-g7f079d6) in Debian wheezy.
+
+### Please provide any additional information below.
+
+<del>This could be just a documentation problem...</del> Actually, the manpage can be read directly from the source tree in `doc/git-annex.mdwn`, but I still think it should be installed, for [[!wikipedia POLA]]'s sake. --[[anarcat]]
+
+I figured it out - that stuff is in the makefile, I updated [[install/cabal]] accordingly, so <del>done</del> - not done just yet. --[[anarcat]]
+
+> Doesn't seem right to me; Setup.hs has some stuff to do with
+> installing man pages. This does currently require that they
+> are distributed in pre-built form in the .tar.gz on hackage,
+> which I've just checked and they are.
+>
+> Perhaps cabal put the man pages somewhere else? After all, you
+> apparently did not set --datadir --[[Joey]]
+
+> > True, I didn't - the docs didn't say to. ;) But really, it's one of two things, either Setup.hs can install manpages, and then the Makefile shouldn't install it, or we should update documentation to use the makefile only. I'll try this again next time I reinstall through cabal i guess... -- [[anarcat]]a
+
+>>> The default location cabal installs man pages to is
+>>> `~/.cabal/share/man/man1`. That is insane, but it is not as
+>>> insane as not installing programs into PATH, which is why
+>>> the documentation tells how to set --bindir to fix that particular
+>>> cabal insanity. (Also, many systems don't have a good per-user
+>>> man directory anyway.)
+>>>
+>>> `make install` does not use `cabal install` because as noted, cabal
+>>> install is thurougly bat shit crazy. Not all systems that have
+>>> cabal have make, which is why the cabal documentation is the way it is.
+>>> --[[Joey]]
+
+[[done]]
diff --git a/doc/bugs/can__39__t_annex_get_from_annex_in_direct_mode.mdwn b/doc/bugs/can__39__t_annex_get_from_annex_in_direct_mode.mdwn
index d09a13b07..ca47d3a4c 100644
--- a/doc/bugs/can__39__t_annex_get_from_annex_in_direct_mode.mdwn
+++ b/doc/bugs/can__39__t_annex_get_from_annex_in_direct_mode.mdwn
@@ -19,3 +19,5 @@ Debian Linux: 3.20120629 (from the package manager)
there is no <filehash>.<extension> file in the relevant directories, there are only .map and .cache files. The Windows annex is in direct mode, and the Linux annex fails to annex get from this correctly.
[[!meta title="can't use a direct mode repository as a http remote"]]
+
+> [[done]]; unsupported configuration. --[[Joey]]
diff --git a/doc/bugs/cannot_determine_uuid_for_origin.mdwn b/doc/bugs/cannot_determine_uuid_for_origin.mdwn
new file mode 100644
index 000000000..611a0f236
--- /dev/null
+++ b/doc/bugs/cannot_determine_uuid_for_origin.mdwn
@@ -0,0 +1,135 @@
+[[!toc]]
+
+### Please describe the problem.
+
+I get this error when trying to copy annexed files from my laptop to the bare repository on my server:
+
+ anarcat@angela:ohm2013$ git annex copy -t origin .
+ git-annex: cannot determine uuid for origin
+
+### What steps will reproduce the problem?
+
+Here's my setup:
+
+ * `angela`: regular git repository on my laptop (`angela`) where i ran `git annex init` and `git annex add`ed 4 big files (in `~anarcat/presentations/ohm2013`)
+ * `marcos-bare`: a bare git repository where i ran `git annex init` on a different server (`marcos`) (in `~anarcat/repos/presentations/ohm2013.git`)
+ * `marcos-checkout`: a checkout of the above repository on marcos (in `~anarcat/presentations/ohm2013`)
+
+I ran `git pull/push` everwhere in there, and still get the error.
+
+Remotes on all repos:
+
+ * `angela`: `origin anarcat.ath.cx:repos/presentations/ohm2013.git`
+ * `marcos-bare`: no remote
+ * `marcos-checkout`: `origin /home/anarcat/repos/presentations/ohm2013.git`
+
+Note that file added with `git annex addurl` on `marcos-checkout` properly gets propagated on `angela` once i do `git annex get` there.
+
+### What version of git-annex are you using? On what operating system?
+
+`angela` runs:
+
+[[!format txt """
+git-annex version: 4.20130730-ge59a8c6
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+I was able to reproduce with the backport version too.
+
+I compiled it by hand from git.
+
+`marcos` runs:
+
+[[!format txt """
+git-annex version: 3.20120629
+local repository version: unknown
+default repository version: 3
+supported repository versions: 3
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+### Please provide any additional information below.
+
+In addition, there's this error on `marcos-bare`:
+
+[[!format sh """
+anarcat@marcos:ohm2013.git$ git annex status -d
+supported backends: SHA256 SHA1 SHA512 SHA224 SHA384 SHA256E SHA1E SHA512E SHA224E SHA384E WORM URL
+supported remote types: git S3 bup directory rsync web hook
+trusted repositories: git ["--git-dir=/home/anarcat/repos/presentations/ohm2013.git","show-ref","git-annex"]
+git ["--git-dir=/home/anarcat/repos/presentations/ohm2013.git","show-ref","--hash","refs/heads/git-annex"]
+git ["--git-dir=/home/anarcat/repos/presentations/ohm2013.git","log","refs/heads/git-annex..6063e958c02259a39b87d0f1dc44c9272c52df3f","--oneline","-n1"]
+git ["--git-dir=/home/anarcat/repos/presentations/ohm2013.git","cat-file","--batch"]
+0
+semitrusted repositories: 4
+ 00000000-0000-0000-0000-000000000001 -- web
+ 5868f840-02e7-11e3-94e9-9b3701bd28bb -- marcos-checkout
+ aafdd242-02e7-11e3-bb6a-6f16a5c6103e -- here (marcos-bare)
+ befc3057-d23d-4312-843a-0645e93107d8 -- angela
+untrusted repositories: 0
+dead repositories: 0
+available local disk space: 14 gigabytes (+1 megabyte reserved)
+local annex keys: 0
+local annex size: 0 bytes
+known annex keys: git ["--git-dir=/home/anarcat/repos/presentations/ohm2013.git","ls-files","--cached","-z","--","/home/anarcat/repos/presentations/ohm2013.git"]
+fatal: '/home/anarcat/repos/presentations/ohm2013.git' is outside repository
+0
+known annex size: 0 bytes
+bloom filter size: 16 mebibytes (0% full)
+backend usage:
+"""]]
+
+### Workaround!
+
+I found that I could succesfully push to the non-bare repo, like this:
+
+[[!format txt """
+anarcat@angela:ohm2013$ git remote add marcos-checkout ssh://anarcat.ath.cx/~/presentations/ohm2013
+anarcat@angela:ohm2013$ git fetch marcos-checkout
+From ssh://anarcat.ath.cx/~/presentations/ohm2013
+ * [new branch] git-annex -> marcos-checkout/git-annex
+ * [new branch] master -> marcos-checkout/master
+anarcat@angela:ohm2013$ git annex copy AlerteRouge.webm --to marcos-checkout
+copy AlerteRouge.webm (checking marcos-checkout...) (to marcos-checkout...)
+SHA256E-s138903105--a69db8d4c3835b03bdb08cb1cccfde5c76f586f934d63283694e7101b25352a8.webm
+[...]
+"""]]
+
+It seems that git-annex doesn't like bare repos at all...
+
+### Fix
+
+It seems that my problem was specifically related to [[bare repositories]], which are not well supported historically. There has been other reports of problems in the past, which I missed in my search because symptoms were different:
+
+ * [[bugs/bare git repos]]
+ * [[forum/get and copy with bare repositories]]
+
+Yet while I was able to do `git annex get --all` *from* the `marcos-bare` repository, I still get the original error message while trying to `git annex copy -t marcos-bare`, which is pretty annoying considering the original files are on my laptop, which is not publicly accessible. So I basically need to add the `marcos-checkout` as a remote, copy there, then get from the bare repo to make this work, which is a rather convoluted way of doing things. :)
+
+It seems to me a proper fix would be to be able to `git annex copy --to marcos-bare`. Thanks!
+
+Update: it seems te problem was that I had the following in my `.git/config`:
+
+ [remote "marcos-bare"]
+ url = ssh://anarcat.ath.cx/~/repos/presentations/ohm2013.git
+ annex-ignore = true
+ fetch = +refs/heads/*:refs/remotes/marcos-bare/*
+
+I have *no* idea how that `annex-ignore` got there, but that was the root of my problem. Removing it it allowed my to do `git annex copy`. I really don't know how this happened, but I guess this is [[done]], although I believe this error message is really confusing and could be improved. --[[anarcat]]
+
+> `annex-ignore` is set automatically by git-annex if it fails to query
+> the uuid of a remote the first time it tries to use it. It will say
+> when it does that. The assumption
+> is that a remote whose uuid cannot be looked up is a git remote
+> on a server w/o git-annex support (like github) and it would be annoying
+> to constantly be trying and failing to get that uuid.
+>
+> So, I've improved the error message. Now when annex-ignore is set
+> for a remote, the error you got will mention that.
+>
+> (Also, there is not currently anything lacking in git-annex's support
+> for bare repositories.) --[[Joey]]
diff --git a/doc/bugs/cannot_link_executable_on_android.mdwn b/doc/bugs/cannot_link_executable_on_android.mdwn
new file mode 100644
index 000000000..cb660dd9c
--- /dev/null
+++ b/doc/bugs/cannot_link_executable_on_android.mdwn
@@ -0,0 +1,28 @@
+### Please describe the problem.
+Then starting git-annex on my Galaxy Nexus Android device, in the terminal window I get:
+
+[[!format sh """
+Falling back to hardcoded app location: cannot find expected files in /data/app-lib
+git annex webapp
+u0_a123@maguro:/sdcad/git-annex.home $ git annex webapp
+CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?)
+u0_a123@maguro:/sdcad/git-annex.home $
+"""]]
+
+### What steps will reproduce the problem?
+Start git-annex.
+
+### What version of git-annex are you using? On what operating system?
+Nightly build and release from a few days ago - 1.0.52
+
+### 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.
+"""]]
+
+> [[dup|done]] of [[git-annex_broken_on_Android_4.3]].--[[Joey]]
diff --git a/doc/bugs/clicking_back_in_the_web_browser_crashes.mdwn b/doc/bugs/clicking_back_in_the_web_browser_crashes.mdwn
new file mode 100644
index 000000000..1b7e2ec71
--- /dev/null
+++ b/doc/bugs/clicking_back_in_the_web_browser_crashes.mdwn
@@ -0,0 +1,23 @@
+### Please describe the problem.
+
+When I click on the "back" button in my web browser, I get the following error message:
+
+ git-annex has shut down
+
+ You can now close this browser window.
+
+### What steps will reproduce the problem?
+
+ 1. git annex webapp
+ 2. click on "configuration" (or whatever)
+ 3. click on the back button of your web browser
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130815~bpo70+1 on Debian Wheezy, with Chromium Version 29.0.1547.57 Debian 7.1 (217859)
+
+### Please provide any additional information below.
+
+Click "forward" actually brings us back to sanity, and the webapp doesn't actually *crash*. -- [[anarcat]]
+
+> I have applied the page reload fix/hack. [[done]] --[[Joey]]
diff --git a/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_1_c962218657a28494ff837a471d71b43f._comment b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_1_c962218657a28494ff837a471d71b43f._comment
new file mode 100644
index 000000000..ece6ce0e3
--- /dev/null
+++ b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_1_c962218657a28494ff837a471d71b43f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T04:23:36Z"
+ content="""
+This occurs when the javascript long polling code fails 4 times in a row attempting to communicate with git-annex's web server. Normally this will mean that the assistant has been stopped. I have seen it once or twice happen while the web server is still running -- possibly due to the browser killing the connection? I have never seen it happen when navigating between pages in the webapp, which is designed to allow use of back button etc. If you can reproduce it reliably, using the chromium inspector to modify the javascript code (look for \"longpoll\") and perhaps add some debug prints might track down what is going on.
+"""]]
diff --git a/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_2_643b2c99ecfe851c576a023ce4385dbb._comment b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_2_643b2c99ecfe851c576a023ce4385dbb._comment
new file mode 100644
index 000000000..feac21ffe
--- /dev/null
+++ b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_2_643b2c99ecfe851c576a023ce4385dbb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="2001:1928:1:9::1"
+ subject="comment 2"
+ date="2013-09-09T04:31:30Z"
+ content="""
+i can reproduce reliably alright. It's quite systematic. I have found the `longpolling.js` file in the inspector, but I am not very familiar with in-browser javascript debugging, so I am not sure where to go from here.
+
+Note that the assistant doesn't actually crash. This is also reproducable in Debian sid.
+"""]]
diff --git a/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_3_6e85c50439da81212f4239c74947b75e._comment b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_3_6e85c50439da81212f4239c74947b75e._comment
new file mode 100644
index 000000000..a3dee1d52
--- /dev/null
+++ b/doc/bugs/clicking_back_in_the_web_browser_crashes/comment_3_6e85c50439da81212f4239c74947b75e._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 3"
+ date="2013-09-09T05:22:49Z"
+ content="""
+Actually I am able to reproduce it. One thing I can see is that git-annex does not see any connection attempts from the browser when these longpolling attempts are made and fail. So this is all failing on the javascript side. Increasing the connection failure counter does not help. Every ajax request fails, no matter how many times it tries. Chromium has apparently decided that, because we've navigated back to a page, it should not be allowed to load any new resources. This seems to be new, buggy behavior.
+
+It seems the only way out of this bad state would be for the javacript to force a reload of the page. Of course, if git-annex has legitimately exited, that would fail to reload. I suppose the chromium \"this webpage is not available\" that would result is at least accurate...
+
+(At some point, I should probably try to add support for something more modern than long polling.)
+"""]]
diff --git a/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work.mdwn b/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work.mdwn
new file mode 100644
index 000000000..190f3bb3b
--- /dev/null
+++ b/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work.mdwn
@@ -0,0 +1,74 @@
+### Please describe the problem.
+Copying to a gpg encrypted webdav remote (with davfs) seems to work, but fails.
+The command "git annex copy --to 1und1 some/file" returns ok, but a fsck fails and running
+the copy again copies the file again to the remote.
+
+### What steps will reproduce the problem?
+[[!format sh """
+git annex copy --to 1und1 some/file # seems ok
+git annex copy --to 1und1 some/file # copies again
+git annex fsck --from 1und1 some/file # fails
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+4.20131002 on debian (mostly stable), armel.
+
+### Please provide any additional information below.
+
+I used strace to see what is going on. It seems the chunkcount file is not written. When I create that file by hand fsck is happy.
+(git annex seems to have two different locations for that file (dcf/85a and 3W/Qm). The second (3W/Qm) doesn't exist.)
+
+[[!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
+copy to webdav (git annex copy --to 1und1 some/file)
+output of basically "strace git annex ... | grep media":
+
+9871 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", <unfinished ...>
+9871 stat64("/media/1und1/git-annex/3W/Qm/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", 0xb65145d0) = -1 ENOENT (No such file or directory)
+9871 mkdir("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33", 0777 <unfinished ...>
+9871 statfs("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", <unfinished ...>
+9871 stat64("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
+9871 open("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0666 <unfinished ...>
+9871 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", <unfinished ...>
+9871 chmod("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", 040755 <unfinished ...>
+9871 openat(AT_FDCWD, "/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 15
+9871 unlink("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1" <unfinished ...>
+9871 rmdir("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/" <unfinished ...>
+9871 mkdir("/media/1und1/git-annex/dcf/85a", 0777) = -1 EEXIST (File exists)
+9871 stat64("/media/1und1/git-annex/dcf/85a", {st_mode=S_IFDIR|0755, st_size=64, ...}) = 0
+9871 stat64("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
+9871 rename("/media/1und1/git-annex/tmp/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", "/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/" <unfinished ...>
+9871 openat(AT_FDCWD, "/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 15
+9871 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", {st_mode=S_IFREG|0644, st_size=11705, ...}) = 0
+9871 chmod("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", 0100444) = 0
+9871 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", {st_mode=S_IFDIR|0755, st_size=152, ...}) = 0
+9871 chmod("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/", 040555 <unfinished ...>
+
+fsck webdav, but fails (git annex fsck --from 1und1 some/file):
+
+10208 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", <unfinished ...>
+10208 stat64("/media/1und1/git-annex/3W/Qm/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", 0xb6428160) = -1 ENOENT (No such file or directory)
+
+
+manual file creation:
+chmod u+w ...
+echo -n 1 > /media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount
+chmod u-w ...
+
+
+fsck webdav again, now all is fine ("fixing location log"):
+10670 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", {st_mode=S_IFREG|0444, st_size=1, ...}) = 0
+10670 open("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 14
+10670 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", {st_mode=S_IFREG|0444, st_size=11705, ...}) = 0
+10670 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", {st_mode=S_IFREG|0444, st_size=1, ...}) = 0
+10670 open("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunkcount", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 14
+10670 stat64("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", {st_mode=S_IFREG|0444, st_size=11705, ...}) = 0
+10672 open("/media/1und1/git-annex/dcf/85a/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33/GPGHMACSHA1--10ff9e1cc8191235670c2fd95375bccf62004f33.chunk1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 20
+# End of transcript or log.
+"""]]
+
+> There was a bug that caused it not to write the chunkcount file.
+> I have fixed it, and put in a workaround so fsck, etc, will
+> see that the file is stored on the remote despite there being no
+> chunkcount file present. [[done]] --[[Joey]]
diff --git a/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work/comment_1_77629f620b28ac62364de44b41fa539d._comment b/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work/comment_1_77629f620b28ac62364de44b41fa539d._comment
new file mode 100644
index 000000000..d5ad2d88d
--- /dev/null
+++ b/doc/bugs/copy_to_webdav_sometimes_doesn__39__t_work/comment_1_77629f620b28ac62364de44b41fa539d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlqOu7P4tb4D-Xo2pYrjln2NsAObtErliM"
+ nickname="Alexander"
+ subject="comment 1"
+ date="2013-10-27T07:00:01Z"
+ content="""
+thanks!
+"""]]
diff --git a/doc/bugs/cross_platform_permissions_woes.mdwn b/doc/bugs/cross_platform_permissions_woes.mdwn
new file mode 100644
index 000000000..d67ca4ae0
--- /dev/null
+++ b/doc/bugs/cross_platform_permissions_woes.mdwn
@@ -0,0 +1,36 @@
+a little introduction:
+i am forced to use windows on my work laptop and workstation, also my wife needs windows.
+my "servers" would be linux, i am actually using fedora and i upgraded from fc17 since i was not able to get a recent version of git annex to compile there.
+
+what happens, is that once i try to copy from the windows machine where the file is to the linux through ssh+rsync, i receive this error - as long as the user owning the linux repository isn't root:
+
+ c:\locale>git annex copy --to linux myfile
+ copy myfile (checking linux...) (to linux...)
+ rsync: failed to open "/linux/annex/tmp/SHA256E-s10--937a89b559820f8658892"
+ myfile
+ 10 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/1)
+ rsync error: syntax or usage error (code 1) at /home/lapo/package/rsync-3.0.9-1/src/rsyn
+ total size is 10 speedup is 0.09
+ failed
+ git-annex: copy: 1 failed
+
+the file in tmp has no permissions at all:
+
+ me@linux annex]$ ls -lart tmp/SHA256E-s10--937a89b559820f86588921ef3eb12c13074d078b62ef205bb597bf2e895408c3
+ ----------. 1 me me 10 Oct 13 22:50 tmp/SHA256Es10--937a89b559820f86588921ef3eb12c13074d078b62ef205bb597bf2e895408c3
+
+(just consider the following if the above makes any sense:) in another case (i cannot reproduce it now, possibly due to having upgraded git annex from some 2012 release), it happened that a failed download via copy/move from linux to windows (failed for permissions) would not be recorded as failed (on windows side), causing files to possibly be killed at the first subsequent drop command.
+
+my question is: are these 0-permissions on tmp files a bug or just due to some ignorance i did put in setting up the git/annex repo ? is a git/annex repo to be run solely as root/sudoer ? or shall i take any other step in configuring it ?
+
+technicalities:
+
+"client": windows version:
+
+ git-annex version: 4.20131002-gf25991c
+
+"server": linux version:
+
+ git-annex version: 3.20130207
+
+> [[done]]; fixed in newer git-annex versions. --[[Joey]]
diff --git a/doc/bugs/cross_platform_permissions_woes/comment_1_7f01104de38a6a319a8f36aa1dc8b4b3._comment b/doc/bugs/cross_platform_permissions_woes/comment_1_7f01104de38a6a319a8f36aa1dc8b4b3._comment
new file mode 100644
index 000000000..a3116cdcf
--- /dev/null
+++ b/doc/bugs/cross_platform_permissions_woes/comment_1_7f01104de38a6a319a8f36aa1dc8b4b3._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-15T18:29:10Z"
+ content="""
+Based on the '/linux/annex/' path, your \"linux\" git remote is set up using some sort of network mount of your Linux box to Windows.
+
+If that's the case, then rsync is running on Windows and probably doesn't know anything about permissions, to probably does something horrible when it's told to write a file to the linux filesystem.
+
+If I'm right about that, I can easily fix it, by making git-annex on Windows not use rsync for such file to file copies. But I first need you to verify if I'm right about how your \"linux\" git remote is configured.
+
+(Also, you should be able to work around the problem by changing the git remote to use a ssh:// url to the linux system.)
+"""]]
diff --git a/doc/bugs/cross_platform_permissions_woes/comment_2_0a34e11b466fad287325425e76487fa1._comment b/doc/bugs/cross_platform_permissions_woes/comment_2_0a34e11b466fad287325425e76487fa1._comment
new file mode 100644
index 000000000..8ee7c18a5
--- /dev/null
+++ b/doc/bugs/cross_platform_permissions_woes/comment_2_0a34e11b466fad287325425e76487fa1._comment
@@ -0,0 +1,73 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmCzVCPjgg_Un_114P8iiSwExms0G2csCA"
+ nickname="Michele"
+ subject="details about my problem"
+ date="2013-10-15T23:30:26Z"
+ content="""
+Thank for your answer, but unfortunately the remote is already an ssh (although i agree it should happen most certainly also via samba/cifs mount).
+it happens as long as the remote is NOT defined as root login.
+I suppose it could as well be something with my setup (although i've tried different windows/linux hosts) and I have no idea how to debug it.
+
+this is a transcript of recreating the problem (i've just edited user/hostname):
+
+ Microsoft Windows [Version 6.1.7601]
+ C:\>git init wintest
+ Initialized empty Git repository in C:/wintest/.git/
+ C:\>cd wintest
+ C:\wintest>git annex init wintest
+ init wintest
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ ok
+ (Recording state in git...)
+ C:\wintest>echo \"thisisatest\">wintest
+ C:\wintest>git annex add wintest
+ add wintest (checksum...) ok
+ (Recording state in git...)
+ C:\wintest>git remote add remote ssh://me@linuxbox/home/me/testlinux
+ C:\wintest>ssh me@linuxbox
+ [me@home ~]$ git init --bare testlinux
+ Initialized empty Git repository in /home/me/testlinux/
+ [me@home ~]$ cd testlinux/
+ [me@home testlinux]$ git annex init linux
+ init linux ok
+ (Recording state in git...)
+ [me@home testlinux]$ exit
+ C:\wintest>git annex sync
+ commit
+ ok
+ pull remote
+ warning: no common commits
+ remote: Counting objects: 5, done.
+ remote: Compressing objects: 100% (3/3), done.
+ remote: Total 5 (delta 1), reused 0 (delta 0)
+ Unpacking objects: 100% (5/5), done.
+ From ssh://linux/home/me/testlinux
+ * [new branch] git-annex -> remote/git-annex
+ ok
+ (merging remote/git-annex into git-annex...)
+ (Recording state in git...)
+ push remote
+ Counting objects: 18, done.
+ Delta compression using up to 2 threads.
+ Compressing objects: 100% (12/12), done.
+ Writing objects: 100% (16/16), 1.45 KiB, done.
+ Total 16 (delta 2), reused 0 (delta 0)
+ To ssh://me@linux/home/michele/testlinux
+ * [new branch] git-annex -> synced/git-annex
+ * [new branch] master -> synced/master
+ ok
+ C:\wintest>git annex copy --to remote wintest
+ copy wintest (checking remote...) (to remote...)
+ wintest
+ 15 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/1)
+
+ rsync error: syntax or usage error (code 1) at /home/lapo/package/rsync-3.0.9-1/src/rsync-3.0.9/main.c(1052) [sender=
+ total size is 15 speedup is 0.13
+ failed
+ git-annex: copy: 1 failed
+
+ C:\wintest>
+"""]]
diff --git a/doc/bugs/cross_platform_permissions_woes/comment_3_278f91b4bc4c32717ab1c39c2abf9305._comment b/doc/bugs/cross_platform_permissions_woes/comment_3_278f91b4bc4c32717ab1c39c2abf9305._comment
new file mode 100644
index 000000000..1cfed0a90
--- /dev/null
+++ b/doc/bugs/cross_platform_permissions_woes/comment_3_278f91b4bc4c32717ab1c39c2abf9305._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 3"
+ date="2013-10-16T15:47:38Z"
+ content="""
+I think you will have better luck if you upgrade your server's git-annex version. I checked and some fixes for exactly this problem went in around May. Also, testing with the current version, I followed your procedure exactly and did not see the problem.
+"""]]
diff --git a/doc/bugs/cross_platform_permissions_woes/comment_4_eb6a271cb63c71341469c9ff89dc0eb9._comment b/doc/bugs/cross_platform_permissions_woes/comment_4_eb6a271cb63c71341469c9ff89dc0eb9._comment
new file mode 100644
index 000000000..08ebe1e6d
--- /dev/null
+++ b/doc/bugs/cross_platform_permissions_woes/comment_4_eb6a271cb63c71341469c9ff89dc0eb9._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmCzVCPjgg_Un_114P8iiSwExms0G2csCA"
+ nickname="Michele"
+ subject="solved"
+ date="2013-10-18T21:00:38Z"
+ content="""
+installing very recent version on linux solved the problem !!! indeed a bug, but an old one! (quite difficult to get an updated version with cabal on fc19 and so forth, i would add a couple suggestion to share in the fedora install page)
+thank you
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos.mdwn b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos.mdwn
new file mode 100644
index 000000000..8007ae11f
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos.mdwn
@@ -0,0 +1,199 @@
+### Please describe the problem.
+Data loss due to incorrect merge of repos in direct mode. (I tested the same scenario in indirect mode and it worked fine there)
+
+Given 2 repos A and B, in direct mode:
+
+1. in A: mkdir f, with a file f in it
+2. in B: touch f
+3. in B: sync
+
+Result: Only an f.variant-f###remains, which is file f of B, and the merge conflict has already been automatically resolved. I.e. Directory f containing file f, is lost.
+
+Expected result: remaining contents: f.variant-AAA which is file f of B, f.variant-BBB which is directory f of A, containing a file f. Merge conflict marked resolved.
+
+### What steps will reproduce the problem?
+Execute the script given below in additional information.
+
+### What version of git-annex are you using?
+git-annex version: 4.20130911-g6625d0e
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi
+
+### On what operating system?
+Linux basementcat 3.10.10-1-ARCH #1 SMP PREEMPT Fri Aug 30 11:30:06 CEST 2013 x86_64 GNU/Linux
+
+### Please provide any additional information below.
+
+[[!format sh """
+[~]$ mkdir test
+[~/test]$ mkdir a
+[~/test/a]$ git init
+Initialized empty Git repository in /home/limyreth/test/a/.git/
+[~/test/a]$ git annex init test
+init test ok
+(Recording state in git...)
+[~/test/a]$ touch firstfile
+[~/test/a]$ git annex add firstfile
+add firstfile (checksum...) ok
+(Recording state in git...)
+[~/test/a]$ git annex sync
+commit
+ok
+git-annex: no branch is checked out
+[~]$ git clone test/a
+Cloning into 'a'...
+done.
+[~]$ mv a test/b
+[~/test/a]$ git annex direct
+commit
+# On branch master
+nothing to commit, working directory clean
+ok
+direct firstfile ok
+direct ok
+[~/test/a]$ ls -l
+total 0
+-rw-r--r-- 1 limyreth users 0 Oct 12 15:09 firstfile
+[~/test/a]$ mkdir f
+[~/test/a]$ touch f/f
+[~/test/a]$ git annex add f/f
+add f/f (checksum...) ok
+(Recording state in git...)
+[~/test/a]$ git annex sync
+commit
+ok
+[~/test/b]$ git remote -v
+origin /home/limyreth/test/a (fetch)
+origin /home/limyreth/test/a (push)
+[~/test/b]$ ls
+firstfile
+[~/test/b]$ git annex direct
+commit
+(Recording state in git...)
+# On branch master
+nothing to commit, working directory clean
+ok
+direct ok
+[~/test/b]$ touch f
+[~/test/b]$ git annex add f
+add f (checksum...) ok
+(Recording state in git...)
+[~/test/b]$ git annex sync
+(merging origin/git-annex into git-annex...)
+(Recording state in git...)
+commit
+ok
+pull origin
+remote: Counting objects: 14, done.
+remote: Compressing objects: 100% (7/7), done.
+remote: Total 9 (delta 1), reused 0 (delta 0)
+Unpacking objects: 100% (9/9), done.
+From /home/limyreth/test/a
+ 2a8fa45..ad6802d master -> origin/master
+ 1f39016..19e3e12 git-annex -> origin/git-annex
+ * [new branch] synced/master -> origin/synced/master
+
+Adding f/f
+CONFLICT (file/directory): There is a directory with name f in refs/remotes/origin/master. Adding f as f~HEAD
+Automatic merge failed; fix conflicts and then commit the result.
+f: needs merge
+(Recording state in git...)
+ok
+[master 37a8019] git-annex automatic merge conflict fix
+
+Already up-to-date.
+ok
+(merging origin/git-annex into git-annex...)
+(Recording state in git...)
+push origin
+Counting objects: 36, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (20/20), done.
+Writing objects: 100% (25/25), 2.16 KiB | 0 bytes/s, done.
+Total 25 (delta 5), reused 0 (delta 0)
+To /home/limyreth/test/a
+ ad6802d..37a8019 master -> synced/master
+ * [new branch] git-annex -> synced/git-annex
+ok
+[~/test/b]$ ls -l
+total 0
+-rw-r--r-- 1 limyreth users 0 Oct 12 15:11 firstfile
+-rw-r--r-- 1 limyreth users 0 Oct 12 15:11 f.variant-f874
+[~/test/b]$ git log --summary
+commit 37a80199abe3cf82100bbdb5dd2217ed6bcb4b62
+Merge: 5a8942a ad6802d
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:47 2013 +0200
+
+ git-annex automatic merge conflict fix
+
+commit 5a8942a9a1735cb313c1f6624cbd3f48b252d9d9
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:47 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 f
+
+commit ad6802dc231d389b86154e2df900a70b18e17b29
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:40 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 f/f
+
+commit 2a8fa45bea996ab5ae219a017d4b642153e6d9c9
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:09:40 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 firstfile
+[~/test/a]$ git annex sync
+(merging synced/git-annex into git-annex...)
+commit
+ok
+merge synced/master
+Updating ad6802d..37a8019
+Fast-forward
+ f.variant-f874 | 1 +
+ f/f | 1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+ create mode 120000 f.variant-f874
+ delete mode 120000 f/f
+ok
+[~/test/a]$ git log --summary
+commit 37a80199abe3cf82100bbdb5dd2217ed6bcb4b62
+Merge: 5a8942a ad6802d
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:47 2013 +0200
+
+ git-annex automatic merge conflict fix
+
+commit 5a8942a9a1735cb313c1f6624cbd3f48b252d9d9
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:47 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 f
+
+commit ad6802dc231d389b86154e2df900a70b18e17b29
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:11:40 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 f/f
+
+commit 2a8fa45bea996ab5ae219a017d4b642153e6d9c9
+Author: timdiels <timdiels.m@gmail.com>
+Date: Sat Oct 12 15:09:40 2013 +0200
+
+ git-annex automatic sync
+
+ create mode 120000 firstfile
+
+"""]]
+
+> Bug fixed; test case added; [[done]] --[[Joey]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_1_294c33af08649256908a97894f93c05d._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_1_294c33af08649256908a97894f93c05d._comment
new file mode 100644
index 000000000..1b22d2ce5
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_1_294c33af08649256908a97894f93c05d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlWskoNgUB7r70OXglR-4iKI4bOuPJb-xg"
+ nickname="Tim"
+ subject="comment 1"
+ date="2013-10-13T12:35:47Z"
+ content="""
+I've just tested a similar scenario with 2 conflicting files, a file-file conflict, and then it works fine. That makes sense, as there's a test written for that.
+
+So the specific bits are: directory-file conflict of repos in direct mode.
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_2_02a2b69adbb04b557146e713b70b34d2._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_2_02a2b69adbb04b557146e713b70b34d2._comment
new file mode 100644
index 000000000..7df35b33d
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_2_02a2b69adbb04b557146e713b70b34d2._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 2"
+ date="2013-10-16T18:04:27Z"
+ content="""
+I can confirm this bug, thanks for a good reproduction recipe.
+
+However, there is no actual data loss. If you switch to repo to indirect mode, you can use `git checkout` to check out the past versions from before the botched merge. When you do, you'll find that the files that the merge seemingly deleted in fact still have their contents present. It is preserved in `.git/annex/objects` by the automatic merge conflict resolution code, which does that whenever it deletes a file, whether for good reasons or for buggy reasons.
+
+So if you feel you lost data due to this, you can almost certainly get it back and I'm happy to help with that.
+
+
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_3_d296ef26fc90f4e3166bba6d2de0a1ee._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_3_d296ef26fc90f4e3166bba6d2de0a1ee._comment
new file mode 100644
index 000000000..4adee73bd
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_3_d296ef26fc90f4e3166bba6d2de0a1ee._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlWskoNgUB7r70OXglR-4iKI4bOuPJb-xg"
+ nickname="Tim"
+ subject="comment 3"
+ date="2013-10-17T16:04:03Z"
+ content="""
+I had a recent backup of the data so no real harm was done.
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_4_33ba2c890c962a71ae9fadc417359f8e._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_4_33ba2c890c962a71ae9fadc417359f8e._comment
new file mode 100644
index 000000000..bff93623c
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_4_33ba2c890c962a71ae9fadc417359f8e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlWskoNgUB7r70OXglR-4iKI4bOuPJb-xg"
+ nickname="Tim"
+ subject="comment 4"
+ date="2013-10-31T19:44:34Z"
+ content="""
+Has this issue been fixed? I checked out the repository today and compiled with cabal, but I don't see a f.variant-A and a f.variant-B pop up after sync.
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_5_39eb0bb96fd271bd0de4a3a40814ae1b._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_5_39eb0bb96fd271bd0de4a3a40814ae1b._comment
new file mode 100644
index 000000000..0e5d67f74
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_5_39eb0bb96fd271bd0de4a3a40814ae1b._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 5"
+ date="2013-11-01T15:48:21Z"
+ content="""
+AFAIK this bug is fixed, which is why I wrote above, \"Bug fixed; test case added; done\"
+
+If you have reason to think otherwise, better follow up.
+
+"""]]
diff --git a/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_6_d80c4b631bdf58901a06f29a2c5682e2._comment b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_6_d80c4b631bdf58901a06f29a2c5682e2._comment
new file mode 100644
index 000000000..29457da8a
--- /dev/null
+++ b/doc/bugs/data_loss:_incorrect_merge_upon_conflicting_directory-file_of_direct_repos/comment_6_d80c4b631bdf58901a06f29a2c5682e2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlWskoNgUB7r70OXglR-4iKI4bOuPJb-xg"
+ nickname="Tim"
+ subject="comment 6"
+ date="2013-11-14T14:58:10Z"
+ content="""
+Ah indeed, tried it again and it's indeed fixed. Tried some other things as well, and conflict resolution ended up doing just fine.
+"""]]
diff --git a/doc/bugs/direct_mode_assistant_in_subdir_confusion.mdwn b/doc/bugs/direct_mode_assistant_in_subdir_confusion.mdwn
index 4ab311174..a705e434f 100644
--- a/doc/bugs/direct_mode_assistant_in_subdir_confusion.mdwn
+++ b/doc/bugs/direct_mode_assistant_in_subdir_confusion.mdwn
@@ -4,3 +4,34 @@ into it, and commit them there. These may have been files that needed to be comm
I'm pretty sure this does not affect indirect mode.
--[[Joey]]
+
+The relevant commit, in my family's annex is
+22e694549d698922389deb017c39c2b40371cdf0 --[[Joey]]
+
+Was able to reproduce this as follows:
+
+1. Make 2 repositories A and B, with B in direct mode.
+2. In A, touch topfile; git annex add topfile; git annex sync
+3. In B: mkdir subdir; cd subdir; git annex assistant
+
+Result is a subdir/topfile appearing in B, which is wrong.
+
+<pre>
+ subdir/topfile | 1 +
+ topfile | 1 -
+</pre>
+
+Note that manually doing a git-annex sync in B's subdir does not cause this
+to happen. It's specific to the assistant somehow.
+
+--[[Joey]]
+
+Before 2407170eaf78d9aa38d73d1af68c20da9882779b, git-annex sync in a subdir
+had the same problem. That made it always run from the top of the work
+tree, which its code actually assumes is the case.
+
+The assistant, however, does not do that, and it's useful in general to
+only run it in a subdir.
+
+> Made sync merge code handle this correctly. Conflicted merge handing code
+> was already ok. [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/direct_repository_on_FAT32_fails_to_addurl_containing___63__.mdwn b/doc/bugs/direct_repository_on_FAT32_fails_to_addurl_containing___63__.mdwn
new file mode 100644
index 000000000..1afb9ac14
--- /dev/null
+++ b/doc/bugs/direct_repository_on_FAT32_fails_to_addurl_containing___63__.mdwn
@@ -0,0 +1,44 @@
+### Please describe the problem.
+
+git-annex attempts to create files with question marks in them on my direct repository on a FAT32 drive. This fails.
+
+### What steps will reproduce the problem?
+
+git annex addurl 'http://rf.proxycast.org/m/media/273073201426.mp3?c=culture&p=La+t%C3%AAte+au+carr%C3%A9_10212&l3=20131002&l4=&media_url=http%3A%2F%2Fmedia.radiofrance-podcast.net%2Fpodcast09%2F10212-02.10.2013-ITEMA_20531825-0.mp3'
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format sh """
+$ cat /etc/lsb-release
+DISTRIB_ID=Ubuntu
+DISTRIB_RELEASE=12.04
+DISTRIB_CODENAME=precise
+DISTRIB_DESCRIPTION="Ubuntu 12.04.3 LTS"
+
+$ git annex version
+git-annex version: 4.20130922-g7dc188a
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+### 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 addurl 'http://rf.proxycast.org/m/media/273073201426.mp3?c=culture&p=La+t%C3%AAte+au+carr%C3%A9_10212&l3=20131002&l4=&media_url=http%3A%2F%2Fmedia.radiofrance-podcast.net%2Fpodcast09%2F10212-02.10.2013-ITEMA_20531825-0.mp3'
+addurl rf.proxycast.org_m_media_273073201426.mp3_c=culture&p=La+t%C3%AAte+au+carr%C3%A9_10212&l3=20131002&l4=&media_url=http%3A%2F%2Fmedia.radiofrance-podcast.net%2Fpodcast09%2F10212-02.10.2013-ITEMA_20531825-0.mp3 (downloading http://rf.proxycast.org/m/media/273073201426.mp3?c=culture&p=La+t%C3%AAte+au+carr%C3%A9_10212&l3=20131002&l4=&media_url=http%3A%2F%2Fmedia.radiofrance-podcast.net%2Fpodcast09%2F10212-02.10.2013-ITEMA_20531825-0.mp3 ...)
+/media/sixtyfour/audio/.git/annex/tmp/URL--http&c%%rf.proxycast.org%m%media%273073201426.mp3?c=culture&ap=La+t&sC3&sAAte+au+carr&sC3&sA9_10212&al3=20131002&al4=&amedia_url=http&s3A-86e83c2aaa925b3bc337c1d6a27bd300: Argument invalide
+
+git-annex: /media/sixtyfour/audio/.git/annex/transfer/failed/download/00000000-0000-0000-0000-000000000001/URL--http&c%%rf.proxycast.org%m%media%273073201426.mp3?c=culture&ap=La+t&sC3&sAAte+au+carr&sC3&sA9_10212&al3=20131002&al4=&amedia_url=http&s3A-86e83c2aaa925b3bc337c1d6a27bd300: openFile: invalid argument (Invalid argument)
+failed
+git-annex: addurl: 1 failed
+
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__.mdwn b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__.mdwn
new file mode 100644
index 000000000..8ee66da19
--- /dev/null
+++ b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__.mdwn
@@ -0,0 +1,51 @@
+### Please describe the problem.
+
+When I create a directory special remote, with encryption enabled (shared) and a chunk size restriction (any), I can copy files *to* the remote, but git annex can't find/access them afterwards.
+
+If I do the same, just without specifying chunk size, it works fine. Restricting chunk size on FAT filesystems to something less that 4GB is necessary (otherwise storing bigger files will just fail).
+
+### What steps will reproduce the problem?
+
+Assume `~/annex` is a normal git annex repository and it contains a file `data.file`.
+
+ # cd ~/annex
+ # mkdir /tmp/remote
+ # git annex initremote dirremote type=directory directory=/tmp/remote encryption=shared chunksize="300 megabytes"
+ initremote dirremote (encryption setup) (shared cipher) ok
+ (Recording state in git...)
+ # git annex copy --to dirremote data.file
+ copy data.file (gpg) (to dirremote...)
+ ok
+ (Recording state in git...)
+ # git annex fsck --from dirremote
+ fsck data.file (gpg) (fixing location log)
+ ** Based on the location log, data.file
+ ** was expected to be present, but its content is missing.
+ failed
+ (Recording state in git...)
+ git-annex: fsck: 1 failed
+
+The file is actually in the remote, e.g. `ls -R /tmp/remote` (shortened output):
+
+ /tmp/remote/be5/af7/GPGHMACSHA1--cb23b50579bf69be9cdc0243b6fda1f66218eb43:
+ GPGHMACSHA1--cb23b50579bf69be9cdc0243b6fda1f66218eb43
+ GPGHMACSHA1--cb23b50579bf69be9cdc0243b6fda1f66218eb43.chunkcount
+
+### What version of git-annex are you using? On what operating system?
+
+- mac OS X (10.8.5)
+- git-annex version: 4.20131002-gf25991c
+- `PATH` variable has `/Applications/git-annex.app/Contents/MacOS/bundle` at the front, so if git-annex comes with a binary, it is used
+
+
+### 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.
+"""]]
+
+> [[done]]; see my comment. --[[Joey]]
diff --git a/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_1_69dfbf566c75396cdaaf5ad70f1a94a8._comment b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_1_69dfbf566c75396cdaaf5ad70f1a94a8._comment
new file mode 100644
index 000000000..e068501ad
--- /dev/null
+++ b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_1_69dfbf566c75396cdaaf5ad70f1a94a8._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-26T19:06:38Z"
+ content="""
+There was a bug that caused it not to write the chunkcount file.
+I have fixed it, and put in a workaround so fsck, etc, will
+see that the file is stored on the remote despite there being no
+chunkcount file present.
+
+I was initially puzzled by your output showing the chunkcount file being present.
+However, the bug also caused it to write a chunkcount file when chunking was disabled (ie, the logic for when to write the file was inverted).
+So, I think that the ls you show is after you set up the remote without specifying chunk size, and copied a file to it.
+
+Please test with the next autobuild of git-annex (should be one within an hour my my posting this comment) and verify it can now see the files you stored on the remote with chunking.
+
+
+"""]]
diff --git a/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_2_8d09cc0e06548c4ebde7956edd1b5d85._comment b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_2_8d09cc0e06548c4ebde7956edd1b5d85._comment
new file mode 100644
index 000000000..81d6b35a3
--- /dev/null
+++ b/doc/bugs/directory_remote_+_shared_encryption_+_chunk_size___61___lost_files__63__/comment_2_8d09cc0e06548c4ebde7956edd1b5d85._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://jspk.clavid.com/"
+ nickname="flabbergast"
+ subject="comment 2"
+ date="2013-10-28T09:36:19Z"
+ content="""
+Thanks! I've checked now and the problem is gone.
+"""]]
diff --git a/doc/bugs/encrpyted_ssh_remote_on_macosx.mdwn b/doc/bugs/encrpyted_ssh_remote_on_macosx.mdwn
new file mode 100644
index 000000000..ed269277c
--- /dev/null
+++ b/doc/bugs/encrpyted_ssh_remote_on_macosx.mdwn
@@ -0,0 +1,42 @@
+### Please describe the problem.
+Could not get ssh-askpass running on macosx.
+Transfered the publich key with scp.
+certificate based ssh from macosx to ssh server (debian testing) works.
+After successfull login to ssh server git annex stops with the following errors:
+
+Browser Error Message:
+user error (gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--gen-random","--armor","1","512"] exited 2)
+
+### What steps will reproduce the problem?
+1. git annex on debian gnu linux
+2. git annex on macosx
+3. set up "share with a friend"
+4. create rsa keys on macosx "ssh-kegen -t rsa"
+5. scp public key to server with hosts encrypted ssh remote
+6. configure the server use a encrypted ssh remote in tranport mode
+
+### What version of git-annex are you using? On what operating system?
+current debian testing (20130827)
+macosx 20130827
+### 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
+
+(scanning...) [2013-09-28 17:39:25 CEST] Watcher: Performing startup scan
+(started...) [2013-09-28 17:39:26 CEST] XMPPSendPack: Syncing with jlueters
+Everything up-to-date
+[2013-09-28 17:39:30 CEST] XMPPSendPack: Unable to download files from jlueters.
+
+(encryption setup) gpg: /Users/lambert/.gnupg/gpg.conf:241: invalid auto-key-locate list
+28/Sep/2013:17:40:06 +0200 [Error#yesod-core] user error (gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--gen-random","--armor","1","512"] exited 2) @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+(encryption setup) gpg: /Users/lambert/.gnupg/gpg.conf:241: invalid auto-key-locate list
+28/Sep/2013:17:40:48 +0200 [Error#yesod-core] user error (gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--gen-random","--armor","1","512"] exited 2) @(yesod-core-1.1.8.3:Yesod.Internal.Core ./Yesod/Internal/Core.hs:550:5)
+
+
+
+# End of transcript or log.
+"""]]
+
+> [[dup|done]] --[[Joey]]
diff --git a/doc/bugs/encrpyted_ssh_remote_on_macosx/comment_1_46c37aacb7ae41864488fb7c7d87d437._comment b/doc/bugs/encrpyted_ssh_remote_on_macosx/comment_1_46c37aacb7ae41864488fb7c7d87d437._comment
new file mode 100644
index 000000000..948b2c110
--- /dev/null
+++ b/doc/bugs/encrpyted_ssh_remote_on_macosx/comment_1_46c37aacb7ae41864488fb7c7d87d437._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 1"
+ date="2013-09-29T19:13:59Z"
+ content="""
+This is a duplicate of this bug report: [[Error_creating_encrypted_cloud_repository: \"internal_server_error\"]]
+
+To work around, you need to edit ~/.gnupg/gpg.conf and remove or edit the `auto-key-locate` line.
+"""]]
diff --git a/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__.mdwn b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__.mdwn
new file mode 100644
index 000000000..dae654d13
--- /dev/null
+++ b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__.mdwn
@@ -0,0 +1,63 @@
+### What steps will reproduce the problem?
+[[!format sh """
+C:\Users\Bruno>mkdir annex
+
+C:\Users\Bruno>cd annex
+
+C:\Users\Bruno\annex>git init
+Initialized empty Git repository in C:/Users/Bruno/annex/.git/
+
+C:\Users\Bruno\annex>git annex init
+init
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ok
+(Recording state in git...)
+
+C:\Users\Bruno\annex>echo test > test
+
+C:\Users\Bruno\annex>git annex add .
+add test (checksum...) ok
+(Recording state in git...)
+
+C:\Users\Bruno\annex>git commit -a -m added
+[master (root-commit) 2eea610] added
+ 1 file changed, 1 insertion(+)
+ create mode 120000 test
+
+C:\Users\Bruno\annex>git annex sync
+(Recording state in git...)
+fatal: unable to access '../../../../C:\Users\Bruno\annex\.git/config': Invalid argument
+
+git-annex: user error (xargs ["-0","git","--git-dir=C:\\Users\\Bruno\\annex\\.git","--work-tree=C:\\Users\\Bruno\\annex","add","-f"] exited 123)
+failed
+git-annex: sync: 1 failed
+"""]]
+
+### What version of git-annex are you using? On what operating system?
+Windows 8 (64 bits)
+
+git version 1.8.4.msysgit.0
+
+[[!format sh """
+git-annex version: 4.20131008-ge115441
+build flags: 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 glacier hook
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 2
+"""]]
+
+### Please provide any additional information below.
+C:\Users\Bruno\annex\.git\config exists
+
+> xargs was one problem; also msysgit seems to just not
+> accept DOS style paths anymore in --git-dir or --git-work-tree.
+> megaweird. [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_1_e6f39b2ef55b0daa491f4b6329a906bc._comment b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_1_e6f39b2ef55b0daa491f4b6329a906bc._comment
new file mode 100644
index 000000000..cc616aae9
--- /dev/null
+++ b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_1_e6f39b2ef55b0daa491f4b6329a906bc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-16T20:42:07Z"
+ content="""
+I don't know what to make of this bug report. You say that \"C:\Users\Bruno\annex.git\config\" exists, but you show the creation of a \"C:\Users\Bruno\annex\", and not the other repository. I cannot reproduce it, even if I first \"git init --bare annex.git\".
+"""]]
diff --git a/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_2_b47d6d188f38a8e4ca5ef5f70afadf6a._comment b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_2_b47d6d188f38a8e4ca5ef5f70afadf6a._comment
new file mode 100644
index 000000000..a40e9cbe5
--- /dev/null
+++ b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_2_b47d6d188f38a8e4ca5ef5f70afadf6a._comment
@@ -0,0 +1,48 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkGCmVc5qIJaQQgG82Hc5zzBdAVdhe2JEM"
+ nickname="Bruno"
+ subject="comment 2"
+ date="2013-10-16T22:47:46Z"
+ content="""
+There's no other repo yet. I have the same problem when I try to sync between two repos but I simplified the instructions to reproduce the bug easily.
+
+Here's the instructions on Debian :
+[[!format sh \"\"\"
+bruno@debian:~$ mkdir annex
+bruno@debian:~$ cd annex
+bruno@debian:~/annex$ git init
+Initialized empty Dépôt git dans /home/bruno/annex/.git/
+bruno@debian:~/annex$ git annex init
+init ok
+(Recording state in git...)
+bruno@debian:~/annex$ echo test > test
+bruno@debian:~/annex$ git annex add .
+add test (checksum...) ok
+(Recording state in git...)
+bruno@debian:~/annex$ git commit -a -m added
+[master (root-commit) 631049d] added
+ 1 file changed, 1 insertion(+)
+ create mode 120000 test
+bruno@debian:~/annex$ git annex sync
+commit
+ok
+bruno@debian:~/annex$\"\"\"]]
+
+It seems --git-dir wants 'c:/...' instead of 'c:\\...'.
+
+[[!format sh \"\"\"
+C:\Users\Bruno\annex>git --git-dir=C:\\Users\\Bruno\\annex\\.git --work-tree=C:\\Users\\Bruno\\annex add -f test
+fatal: unable to access '../../../../C:\\Users\\Bruno\\annex\\.git/config': Invalid argument
+
+C:\Users\Bruno\annex>git --git-dir=C:/Users/Bruno/annex/.git --work-tree=C:\\Users\\Bruno\\annex add -f test
+
+C:\Users\Bruno\annex>\"\"\"]]
+
+It's weird that I don't have any problem with the following command:
+[[!format sh \"\"\"C:\Users\Bruno\annex>git --git-dir=C:\\Users\\Bruno\\annex\\.git --work-tree=C:\\Users\\Bruno\\annex config -l
+core.symlinks=false
+core.autocrlf=true
+[...]\"\"\"]]
+
+Maybe there's a problem with `git version 1.8.4.msysgit.0`.
+"""]]
diff --git a/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_4_b533b1de535a057b7ebf99afc92691ed._comment b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_4_b533b1de535a057b7ebf99afc92691ed._comment
new file mode 100644
index 000000000..ac4a9e91a
--- /dev/null
+++ b/doc/bugs/fatal:_unable_to_access___39__..__47__..__47__..__47__..__47__C:__92__Users__92____91__...__93____92__annex__92__.git__47__config__39__:_Invalid_argument___40__Windows__41__/comment_4_b533b1de535a057b7ebf99afc92691ed._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 4"
+ date="2013-10-17T21:49:10Z"
+ content="""
+So this is a problem with msysgit 1.8.4. I have been able to reproduce it with that version. 1.8.3 did not have the problem.
+
+Seems to perhaps be due to the cygwin xargs flipping git into cygwin path mode somehow. (How all this works is massively complex and confusing to me.)
+All the other calls to git with identical parameters work fine. I can also reproduce the problem using some old git 1.7.x in the cygwin terminal.
+
+BTW, I noticed in your example that you ran \"git commit -a\". You should **never** do that in a [[direct mode]] repository. Read the direct mode documentation to understand why.
+"""]]
diff --git a/doc/bugs/file_modification_times.mdwn b/doc/bugs/file_modification_times.mdwn
new file mode 100644
index 000000000..2f75dcab7
--- /dev/null
+++ b/doc/bugs/file_modification_times.mdwn
@@ -0,0 +1,13 @@
+### Please describe the problem.
+The files created in another remote when syncing is "now" rather than keeping the modification time of the source file. As such, git-annex assistant is removing an important bit of information about the file.
+
+### What steps will reproduce the problem?
+1) create two repositories in your computer using webapp
+2) add files to RepoA, see that they are synced to the RepoB.
+3) check the file modification times from any file manager. you will see that while files in RepoA carry correct modification time, synced file in RepoB carries current time.
+
+### What version of git-annex are you using? On what operating system?
+Ubuntu 13.10 32bit version 4.20130815 from apt-get.
+
+> duplicate of [[todo/add_metadata_to_annexed_files]] --[[Joey]]
+> [[done]]
diff --git a/doc/bugs/gcrypt_initremote_pushes_git-annex_but_not_master.mdwn b/doc/bugs/gcrypt_initremote_pushes_git-annex_but_not_master.mdwn
new file mode 100644
index 000000000..c256778c8
--- /dev/null
+++ b/doc/bugs/gcrypt_initremote_pushes_git-annex_but_not_master.mdwn
@@ -0,0 +1,19 @@
+git-annex 4.20130911 on Debian Wheezy.
+
+Using `git annex initremote type=gcrypt` as described [here](http://git-annex.branchable.com/tips/fully_encrypted_git_repositories_with_gcrypt/) creates the repository and pushes the `git-annex` branch to it. It doesn't push `master` (or more generally: the currently checked out branch), as I have verified using `git remote show`.
+
+Manually pushing the branch makes `git annex sync` sync both branches with the gcrypt remote.
+
+I think that it should push the current branch upon creation of the special remote, since for at least me, the whole reason for wanting `git-remote-gcrypt` is that metadata as well as data can be stored encrypted on an SSH server.
+
+Thanks for considering this.
+
+> The git-annex branch is pushed by initremote because I have to push
+> *something* to determine the gcrypt-id. However, this is an implementation
+> detail, and not a feature of initremote. (It's more like a bug of
+> git-remote-gcrypt.)
+>
+> `git annex sync` will always push your currently checked out branch,
+> as well as the git-annex branch, no matter what `initremote` has done.
+>
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/get_from_bup-remote_with_pubkey_failing.mdwn b/doc/bugs/get_from_bup-remote_with_pubkey_failing.mdwn
new file mode 100644
index 000000000..5ec1aa9aa
--- /dev/null
+++ b/doc/bugs/get_from_bup-remote_with_pubkey_failing.mdwn
@@ -0,0 +1,93 @@
+### Please describe the problem.
+
+I'm unable to 'git annex get' a file from a bup-remote with encryption set to 'pubkey'.
+
+### What steps will reproduce the problem?
+
+I added a bup-remote using [these instructions](http://git-annex.branchable.com/walkthrough/using_bup/):
+
+ bash-3.2$ git annex initremote mybup type=bup encryption=pubkey keyid=0xABE8244505D63E81 buprepo=gumdrop:/home/gert/.bup
+
+ # now adding files and moving them:
+ bash-3.2$ mkdir orgmode && touch orgmode/some.org
+ bash-3.2$ git annex add orgmode/some.org
+ add orgmode/some.org (checksum...) ok
+ (Recording state in git...)
+ bash-3.2$ git commit
+ [master bce8c83] Some.org
+ 1 file changed, 1 insertion(+)
+ create mode 120000 orgmode/some.org
+ bash-3.2$ git annex move orgmode/ --to=mybup
+ move orgmode/another.org (gpg)
+ U moet een geheime zin opgeven om de geheime sleutel te gebruiken
+ van: “email”
+ 4096-bit RSA key, ID 0xFF8DE378DE223820, created 2013-11-10
+ (sub-sleutel bij hoofd sleutel ID 0xE9B90528FDA4E1E6)
+
+ (checking mybup...) ok
+ (Recording state in git...)
+ bash-3.2$ less orgmode/another.org
+ orgmode/another.org: No such file or directory
+ bash-3.2$ git annex get orgmode/another.org --debug
+ [2013-11-13 16:18:07 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","ls-files","--cached","-z","--","orgmode/another.org"]
+ get orgmode/another.org [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","show-ref","git-annex"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","show-ref","--hash","refs/heads/git-annex"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..f25f9bb2b78a8b9c4b64087f1378c68fb5c0a2f1","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..1b0a3dd72be437d800e58d659837d6e528cbbc39","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..f62419efea58245d232a52ceaf0eaefe3b0fdced","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..eb6f0cd983d9a3637e984aa815537fe20a5c2a69","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..5362118e643462a0875bfe31d493ffe64413f2d8","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] read: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","log","refs/heads/git-annex..e5afaf82ce25f60a108c0ae873b6fd57c5d28ca7","--oneline","-n1"]
+ [2013-11-13 16:18:08 CET] chat: git ["--git-dir=/Users/gert/annex/.git","--work-tree=/Users/gert/annex","cat-file","--batch"]
+ [2013-11-13 16:18:08 CET] read: git ["config","--null","--list"]
+ (from mybup...) (gpg) [2013-11-13 16:18:08 CET] chat: gpg ["--quiet","--trust-model","always","--decrypt"]
+
+ U moet een geheime zin opgeven om de geheime sleutel te gebruiken
+ van: “<email>”
+ 4096-bit RSA key, ID 0xFF8DE378DE223820, created 2013-11-10
+ (sub-sleutel bij hoofd sleutel ID 0xE9B90528FDA4E1E6)
+
+ [2013-11-13 16:18:15 CET] read: bup ["join","-r","gumdrop:/home/gert/.bup","GPGHMACSHA1--67aec1b62d05d000442cf8e7d9df8d327eaf26d5"]
+ [2013-11-13 16:18:15 CET] chat: gpg ["--quiet","--trust-model","always","--batch","--decrypt"]
+ gpg: kan geheime zin niet opvragen in batch modus
+ gpg: decoderen mislukt: secret key not available
+
+ Unable to access these remotes: mybup
+
+ Try making some of these repositories available:
+ 080e97d2-4f82-4292-acb7-a48d82009258 -- mybup (mybupmy bup repository at gumdrop)
+
+ (Note that these git remotes have annex-ignore set: origin)
+ failed
+ git-annex: get: 1 failed
+
+### What version of git-annex are you using? On what operating system?
+
+Running git-annex version 4.20131105-g136b030 on OSX 10.8.5.
+
+### Please provide any additional information below.
+
+My ideas:
+
+"Unable to access these remotes: mybup" is weird, I just moved files there.
+
+"secret key not available" makes me think it's looking for the primary secret key (which is indeed offline).
+When I encrypt a file with the same key I used to create the remote it just works:
+
+ $ gpg --armor --recipient 0xABE8244505D63E81 --encrypt file.txt
+ $ gpg --decrypt file.txt.asc
+
+When prompting for my passphrase it states "4096-bit RSA key, ID 0xFF8DE378DE223820, created 2013-11-10".
+That is a different subkey than what I entered when I setting up the remote.
+
+My keys/subkeys:
+
+ pub 4096R/0xE9B90528FDA4E1E6 aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: SC
+ vertrouwen: ultimate geldigheid: ultimate
+ sub 4096R/0x98816CFB398B4666 aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: E
+ sub 4096R/0x91951718D5F11CDD aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: S
+ sub 4096R/0xABE8244505D63E81 aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: E
+ sub 4096R/0xB44520A46B27144D aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: S
+ sub 4096R/0xFF8DE378DE223820 aangemaakt: 2013-11-10 vervaldatum: 2014-11-10 gebruik: E
+
+> This was already fixed in version 4.20131106. [[done]] --[[Joey]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied.mdwn b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied.mdwn
new file mode 100644
index 000000000..260ab9981
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied.mdwn
@@ -0,0 +1,48 @@
+### Please describe the problem.
+I followed the tip on [fully encrypted git repositories with gcrypt](http://git-annex.branchable.com/tips/fully_encrypted_git_repositories_with_gcrypt/) to create encrypted git-annex repository on a ssh server. When I try to checkout the repository, things break as follows:
+
+`git clone gcrypt::ssh://my.server/home/me/encryptedrepo myrepo`
+
+works as expected but when in the myrepo directory,
+
+`git annex enableremote encryptedrepo gitrepo=ssh://my.server/home/me/encryptedrepo`
+
+issues the following text (among normal messages):
+
+`git-annex-shell: gcryptsetup permission denied`
+
+Then while the links are there,
+
+`git annex get --from encryptedrepo`
+
+does nothing (in the sense that the content is not retrieved).
+
+This seems to have everything to do with git-annex-shell as the exact same manipulations but with a local repository work perfectly. Unfortunately, I don't know haskell so [this code](https://github.com/joeyh/git-annex/blob/master/Command/GCryptSetup.hs) is cryptic to me. I can guess there is a problem getting the uuid of the repository, but as far as I can tell the bare distant repo looks fine.
+
+### What steps will reproduce the problem?
+
+Create a standard git annex local repository and then follow the [fully encrypted git repositories with gcrypt tip](http://git-annex.branchable.com/tips/fully_encrypted_git_repositories_with_gcrypt/) to create an encrypted git-annex repository on a ssh server. Then follow the instructions in the same tip to clone the remote repository.
+
+### What version of git-annex are you using? On what operating system?
+Both computers run ubuntu 12.04 with all updates and the latest git annex from the ppa, that is:
+
+git-annex version: 4.20131024
+
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV 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 webdav glacier hook
+
+
+### 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/git-annex-shell:_gcryptsetup_permission_denied/comment_1_f4584158b35b80ece1060308883e2dc4._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_1_f4584158b35b80ece1060308883e2dc4._comment
new file mode 100644
index 000000000..6312a58a5
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_1_f4584158b35b80ece1060308883e2dc4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-02T19:46:28Z"
+ content="""
+It seems to me that the `git-annex-shell` on the remote system must be too old a version to support the gcryptsetup command. You can check this by running `git-annex-shell` there and seeing if it lists gcryptsetup in its usage message.
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_2_a4d7aae848340771a9b8e2c87abeea42._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_2_a4d7aae848340771a9b8e2c87abeea42._comment
new file mode 100644
index 000000000..f2fb4f14f
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_2_a4d7aae848340771a9b8e2c87abeea42._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="comment 2"
+ date="2013-11-02T21:53:37Z"
+ content="""
+The git-annex version on the remote server is the same as the one on the client, the latest one available from the ppa (4.20131024). When I run git-annex-shell on both computers, I obtain:
+[[!format sh \"\"\"
+git-annex-shell: bad parameters
+
+Usage: git-annex-shell [-c] command [parameters ...] [option ...]
+
+Plumbing commands:
+
+commit DIRECTORY commits any staged changes to the git-annex branch
+configlist DIRECTORY outputs relevant git configuration
+dropkey DIRECTORY KEY ... drops annexed content for specified keys
+gcryptsetup DIRECTORY VALUE sets up gcrypt repository
+inannex DIRECTORY KEY ... checks if keys are present in the annex
+recvkey DIRECTORY KEY runs rsync in server mode to receive content
+sendkey DIRECTORY KEY runs rsync in server mode to send content
+transferinfo DIRECTORY KEY updates sender on number of bytes of content received
+\"\"\"]]
+
+Both sides seem to understand the gcryptsetup action. Actually, the message gcryptsetup permission denied comes from git-annex-shell, as far as I understand (and from the haskell source linked in the report).
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_3_06bda101ad584b4b882de8b2e202d679._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_3_06bda101ad584b4b882de8b2e202d679._comment
new file mode 100644
index 000000000..863f401ce
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_3_06bda101ad584b4b882de8b2e202d679._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T23:51:13Z"
+ content="""
+I should have looked at that error message more closely. The gcryptsetup command will print a permission denied if the repository it's being run in already has a annex.uuid or already has a gcrypt id. Probably that latter needs to be relaxed for enableremote to work.
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_4_4fc6b25401b645cabc04b510bdfa6863._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_4_4fc6b25401b645cabc04b510bdfa6863._comment
new file mode 100644
index 000000000..e1049ce60
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_4_4fc6b25401b645cabc04b510bdfa6863._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 4"
+ date="2013-11-03T00:15:30Z"
+ content="""
+While I've fixed this bug, in my testing the bug only caused git-annex to fall back to accessing the remote repository using rsync, rather than using git-annex-shell to talk to it, and so `git annex get --from encryptedrepo` was able to retrieve files that were stored in that remote despite the bug. That may have failed for you for some other reason.
+
+You can set git.encryptedrepo.annex-gcrypt to to \"true\" to make it use the degraded rsync mode, or to \"shell\" to make it use git-annex-shell. Setting it to shell should be all that you need to do to recover from (or indeed, work around this bug).
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_5_4e193306801680bba433e75eb4dcba05._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_5_4e193306801680bba433e75eb4dcba05._comment
new file mode 100644
index 000000000..137638aa5
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_5_4e193306801680bba433e75eb4dcba05._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="comment 5"
+ date="2013-11-03T11:24:28Z"
+ content="""
+There is something very strange that I did not notice in my first report. When I try `git annex get --from encryptedrepo` nothing happens in the sense that git annex is not even trying to connect to the remote (no ssh connection attempt) while git.encryptedrepo.annex-gcrypt is set to true. When I set it to shell, nothing happens either.
+
+Another thing I did not report is that I tried the exact same manipulations with another server on which git annex is not installed. The `gcryptsetup permission denied` message was replaced by a `git-annex-shell not found` (or something similar), as expected. But the rest of the behavior was the same: no way to get the actual content with `git annex get --from`. Again, all of this is with 4.20131024, not with the ongoing version.
+
+I'll try got do more test with the new version.
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_6_76ccdf0542e76e4dbd61f3b3228d40ba._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_6_76ccdf0542e76e4dbd61f3b3228d40ba._comment
new file mode 100644
index 000000000..0ad9768f6
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_6_76ccdf0542e76e4dbd61f3b3228d40ba._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 6"
+ date="2013-11-04T17:12:05Z"
+ content="""
+It's entirely normal for `git annex get --from remote` to skip files that it does not think are present on the remote.
+
+What does `git annex whereis` say?
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_7_cd964d0a375c5cba299bf2bbbbb86acb._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_7_cd964d0a375c5cba299bf2bbbbb86acb._comment
new file mode 100644
index 000000000..3a24f4349
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_7_cd964d0a375c5cba299bf2bbbbb86acb._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="comment 7"
+ date="2013-11-04T18:54:54Z"
+ content="""
+`git annex whereis` says the files are not on the remote git, while they are because of the copy. If I do _exactly_ what's on the tip, that is if I clone the encrypted git just after having done `git annex copy --to encryptedbackup`, the remotes seems to ignore that it has the data. To have it working, I had to call `git annex sync` (push will do, I guess) in the original remote after doing the `git annex copy`. Then I can `git pull` and `git annex whereis` knows where the files are (or I can clone the encrypted remote after doing the sync/pull).
+
+It seems a bit strange that the copy command does not record the propagation of the file to the encrypted git. I guess this is because gcrypt is the only special remote that stores also the git part, right? Would that be a good idea (and possible) to handle it in a special way?
+
+Thanks Joey for everything, by the way, both the software and the amazing support via email and the website.
+"""]]
diff --git a/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_8_9bac87c85deb5bb15795df28533d0cde._comment b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_8_9bac87c85deb5bb15795df28533d0cde._comment
new file mode 100644
index 000000000..da2fef585
--- /dev/null
+++ b/doc/bugs/git-annex-shell:_gcryptsetup_permission_denied/comment_8_9bac87c85deb5bb15795df28533d0cde._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 8"
+ date="2013-11-04T19:14:04Z"
+ content="""
+Right -- Normally a special remote doesn't include a git repository. And when using a regular git remote, `git-annex-shell` is used to receive files into the repository and it records immediately that the repo has the file so there's no need to sync in that case. So gcrypt is special in this way.
+
+For now, I have fixed the tip to show syncing after sending files to gcrypt. It might be the case that it would make sense to do a push of the git-annex branch automatically in that case, will have to think about that and see if people get tripped up on this.
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long.mdwn b/doc/bugs/git-annex:_Argument_list_too_long.mdwn
new file mode 100644
index 000000000..f12d5da65
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long.mdwn
@@ -0,0 +1,40 @@
+### Please describe the problem.
+
+Creating a SSH remote git-annex repository using the assisstant gives transcript:
+
+Initialized empty shared Git repository in /home/flindner/annex2/
+exec: 76: git-annex: Argument list too long
+
+### What steps will reproduce the problem?
+
+Using assistent: Creating a new empty local repository. Next, add another remote server repository using SSH. Checking the server went fine. I choose creating git repository. After about 5 minutes the error message above appears. In that time on the server runshell and git take plenty of CPU power but almost no memory. The directory on the server is created, but pairing was not successfull.
+
+### What version of git-annex are you using? On what operating system?
+
+Local: git-annex-standalone 4.20130909-1 from Archlinux AUR
+Remote: git-annex-standalone-i386.tar.gz as of 13. sept. 13. on Debian Squeeze.
+
+### 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
+
+daemon.log is empty.
+
+Log from the web GUI:
+
+[2013-09-13 12:34:11 CEST] main: starting assistant version 4.20130827-g4f18612
+
+ No known network monitor available through dbus; falling back to polling
+(scanning...) [2013-09-13 12:34:11 CEST] Watcher: Performing startup scan
+(started...)
+
+
+# End of transcript or log.
+"""]]
+
+> [[done]]; I have added a guard to runshell to detect when it has
+> started to loop. Although I don't understand how a system could be
+> misconfigured to let that happen, without going far out of your way to
+> mess it up, it's a failure mode that's worth guarding against. --[[Joey]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_1_3f83ea525436b2379ab29a0f860c4669._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_1_3f83ea525436b2379ab29a0f860c4669._comment
new file mode 100644
index 000000000..43f4aa98b
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_1_3f83ea525436b2379ab29a0f860c4669._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 1"
+ date="2013-09-13T15:31:35Z"
+ content="""
+Can you add set -x near the top of the server's runshell script and run this again also with debugging enabled in the local assistant, and post the log, please.
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_2_b417c94169378ef7d0d278ebae517fa1._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_2_b417c94169378ef7d0d278ebae517fa1._comment
new file mode 100644
index 000000000..cd90d9c3b
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_2_b417c94169378ef7d0d278ebae517fa1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 2"
+ date="2013-09-14T08:49:23Z"
+ content="""
+Is there any way to get the transcript from a log file, not from the web page? The output is so enormous that it crashed my browser out of memory (which is 16 GiB) when I tried to paste it. daemon.log contains no interesting output.
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_3_fa925cca216cb810ad80482b19fc6053._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_3_fa925cca216cb810ad80482b19fc6053._comment
new file mode 100644
index 000000000..e182ca2c3
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_3_fa925cca216cb810ad80482b19fc6053._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 3"
+ date="2013-09-15T23:08:48Z"
+ content="""
+Ok, I managed to get the transcript. It is located at <http://xgm.de/upload/transcript.log> (partly) resp. <http://xgm.de/upload/transcript.log.gz> (complete). Looks like the same script is executed again and again with an ever growing LD_LIBRARY_PATH argument list. The same happens when I simply run \"git-annex\" on the shell of the server. \"runshell\" standalone works fine.
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_4_8bd2996107b2d272c32810658e07e715._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_4_8bd2996107b2d272c32810658e07e715._comment
new file mode 100644
index 000000000..033e695f5
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_4_8bd2996107b2d272c32810658e07e715._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 4"
+ date="2013-09-15T23:10:38Z"
+ content="""
+Addendum: git inside runshells works, git-annex not.
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_5_378de7d7503a64611eab62f2f5cffef3._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_5_378de7d7503a64611eab62f2f5cffef3._comment
new file mode 100644
index 000000000..b10c66c81
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_5_378de7d7503a64611eab62f2f5cffef3._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 5"
+ date="2013-09-16T09:00:34Z"
+ content="""
+Ok, bug can be closed, it was never a bug (at least not in git-annex). I was using the i386 build on a x86_64 machine.
+
+Server is virtual machine from Strato.
+
+$ uname -a
+Linux h1774498.stratoserver.net 2.6.32-042stab078.27 #1 SMP Mon Jul 1 20:48:07 MSK 2013 i686 GNU/Linux
+
+Since there was no x86_64 in the uname output, I thought it was a i386 machine. The git-annex binaries gave a \"File not found\" error message, the git binaries worked. Nothing I connected to a wrong architecture... Sorry for the hassle!
+"""]]
diff --git a/doc/bugs/git-annex:_Argument_list_too_long/comment_6_a94e17151348d02999442dd1219babfb._comment b/doc/bugs/git-annex:_Argument_list_too_long/comment_6_a94e17151348d02999442dd1219babfb._comment
new file mode 100644
index 000000000..a788f2c8e
--- /dev/null
+++ b/doc/bugs/git-annex:_Argument_list_too_long/comment_6_a94e17151348d02999442dd1219babfb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 6"
+ date="2013-09-19T17:31:46Z"
+ content="""
+I have tried to reproduce this bug, running the amd64 build on i386, and cannot. When I run the git-annex shell script included in the standalone bundle, it runs runshell, which in turn tries to run bin/git-annex. Since the architecture is wrong, that fails.
+
+I suppose your shell could instead, if presented with a binary of the wrong architecture, skip it and keep searching PATH for another one. That would be a most odd behavior, but if that were the case and you put the git-annex script into PATH, it would lead to what you describe.
+"""]]
diff --git a/doc/bugs/git-annex:_fd:14:_hGetLine:_end_of_file.mdwn b/doc/bugs/git-annex:_fd:14:_hGetLine:_end_of_file.mdwn
index 1e9f3aec4..0d773b52c 100644
--- a/doc/bugs/git-annex:_fd:14:_hGetLine:_end_of_file.mdwn
+++ b/doc/bugs/git-annex:_fd:14:_hGetLine:_end_of_file.mdwn
@@ -1,3 +1,5 @@
+[[!tag moreinfo]]
+
### Please describe the problem.
git-annex webapp won't run
diff --git a/doc/bugs/git-annex:_status:_1_failed.mdwn b/doc/bugs/git-annex:_status:_1_failed.mdwn
new file mode 100644
index 000000000..65f00469c
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed.mdwn
@@ -0,0 +1,25 @@
+Hi
+
+I have a 1 To repository on my local linux box
+
+when i try :
+
+ git annex status
+
+i get :
+
+ git-annex: /media/malima/nazare/.git/annex/tmp/0723300. Everywhere I Dub --: getFileStatus: does not exist (No such file or directory)
+ failed
+
+how could i fix this issue ?
+
+many thanks for help
+
+> [[done]]; I managed to reproduce this bug by making a temp file named
+> ".git/annex/tmp/foo-", or indeed with any dash in it. This is enough
+> to make git-annex think it's a key, but badly formed enough that
+> it fails trying to use that key. Fixed to ignore such non-key files.
+>
+> I'm unsure why `.git/annex/tmp` would have such files in it.
+> Perhaps the assistant was running, but crashed while adding files?
+> --[[Joey]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_10_7cd9de88e55633fc75460f4fe0400f09._comment b/doc/bugs/git-annex:_status:_1_failed/comment_10_7cd9de88e55633fc75460f4fe0400f09._comment
new file mode 100644
index 000000000..556982e34
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_10_7cd9de88e55633fc75460f4fe0400f09._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="204.8.156.142"
+ subject="comment 10"
+ date="2013-10-15T18:49:26Z"
+ content="""
+`git annex status` complains about `.git/annex/tmp/problematic_file--`. That file doesn't exist, but `.git/annex/tmp/problematic_file-` (with one dash) does. And the file itself (no dashes) does exist in a subdir of the annex.
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_11_504a944aab34155046f2fd82c2878f3e._comment b/doc/bugs/git-annex:_status:_1_failed/comment_11_504a944aab34155046f2fd82c2878f3e._comment
new file mode 100644
index 000000000..45ee3a050
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_11_504a944aab34155046f2fd82c2878f3e._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="96.44.189.101"
+ subject="comment 11"
+ date="2013-10-27T00:59:56Z"
+ content="""
+I've tried a few things and found a workaround for the problem. TL;DR: `git annex dropunused`
+
+First I created a new annex with the same data. This time I used `git annex add` instead of having the assistant add the files. Adding went fine (no status error). Only when I started the assistant I got the error right away, with exactly the same file as the last time.
+
+When I removed the file from the annex, the error remained, but this time with a different problematic file in the same directory.
+
+Then I stumbled upon [this forum post](http://git-annex.branchable.com/forum/dot_git_slash_annex_slash_tmp/). It relates to this bug in that the files git-annex is complaining about are located in .git/annex/tmp. `git annex unused` returned about 130 entries (of about 1,200 files total). The last entry was my problematic file. The second-to-last entry was the file that gave me the same error when I removed the original problematic file. This lets me assume that the bug causes `git annex status' to produce 130 errors, of which only the last one gets displayed.
+
+So I ran `git annex dropunused 1-130 --force`. (The command wouldn't run without `--force`, saying that it couldn't make sure if numcopies were being met. This may or may not be related to network problems I'm having lately.) Anyway, now the error was finally gone and the status output didn't complain anymore.
+
+Weird stuff.
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_1_c235cc83c75474e6393e08d2d94b119d._comment b/doc/bugs/git-annex:_status:_1_failed/comment_1_c235cc83c75474e6393e08d2d94b119d._comment
new file mode 100644
index 000000000..a5a378c99
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_1_c235cc83c75474e6393e08d2d94b119d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T19:38:50Z"
+ content="""
+You might try moving the .git/annex/transfer/ directory out of the way.
+
+What version of git-annex do you have installed?
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_2_932f6aaa712298a47868002872e16310._comment b/doc/bugs/git-annex:_status:_1_failed/comment_2_932f6aaa712298a47868002872e16310._comment
new file mode 100644
index 000000000..98fb1d805
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_2_932f6aaa712298a47868002872e16310._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="eezec"
+ ip="93.21.246.236"
+ subject="comment 2"
+ date="2013-09-10T06:05:32Z"
+ content="""
+i have
+ git-annex version: 4.20130815
+
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_3_4bf55320439de152a65e2f21d4a0604b._comment b/doc/bugs/git-annex:_status:_1_failed/comment_3_4bf55320439de152a65e2f21d4a0604b._comment
new file mode 100644
index 000000000..0c3604ad6
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_3_4bf55320439de152a65e2f21d4a0604b._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="eezec"
+ ip="93.21.246.236"
+ subject="comment 3"
+ date="2013-09-11T06:12:20Z"
+ content="""
+Joey .. moving transfer didn't work .. i have the same message when doing
+
+ git annex status
+ ....
+ getFileStatus: does not exist (No such file or directory)
+ ....
+ git-annex: status: 1 failed
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_4_cb2cfb798c6171f77eb7c4c4061c0f0c._comment b/doc/bugs/git-annex:_status:_1_failed/comment_4_cb2cfb798c6171f77eb7c4c4061c0f0c._comment
new file mode 100644
index 000000000..3e4ecb82f
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_4_cb2cfb798c6171f77eb7c4c4061c0f0c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 4"
+ date="2013-09-12T21:10:12Z"
+ content="""
+can you `strace git-annex status` ?
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_5_05c84dde377298adfd3fc20749b3108f._comment b/doc/bugs/git-annex:_status:_1_failed/comment_5_05c84dde377298adfd3fc20749b3108f._comment
new file mode 100644
index 000000000..61af9e9df
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_5_05c84dde377298adfd3fc20749b3108f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="213.61.149.100"
+ subject="comment 5"
+ date="2013-10-13T06:33:24Z"
+ content="""
+I use v4.20130909 and get the same error when running `git-annex status`. Does it matter that my filename in question is shown to have two dashes (--) at the end, just as in OP's case? Other files in .git/annex/tmp only have one dash at the end.
+
+Joey, I straced the command and sent the output to your kitenet e-mail address. Hope it helps.
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_6_bb5141e29c665bc0bb82611ea27d4be8._comment b/doc/bugs/git-annex:_status:_1_failed/comment_6_bb5141e29c665bc0bb82611ea27d4be8._comment
new file mode 100644
index 000000000..ab720b6ce
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_6_bb5141e29c665bc0bb82611ea27d4be8._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 6"
+ date="2013-10-13T17:35:20Z"
+ content="""
+What is the last line printed before this error message?
+
+My preliminary analysis is that it is checking the sizes of stale files in .git/annex/tmp, and could fail if a temp file was deleted just as it was running.
+But if so it would be unlikely to happen every time `git annex status` is run. Or even if it did happen every time (perhaps because you appear to be running the git-annex assistant and it might be adding a lot of files in the background), the filename in the error message would be different every time. I have just committed a fix for that problem to git, but am not 100% sure it's really the problem that you're seeing.
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_7_5fd39168c9e1bf43909ee0ab3c75c40c._comment b/doc/bugs/git-annex:_status:_1_failed/comment_7_5fd39168c9e1bf43909ee0ab3c75c40c._comment
new file mode 100644
index 000000000..54f87581c
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_7_5fd39168c9e1bf43909ee0ab3c75c40c._comment
@@ -0,0 +1,35 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="37.130.227.133"
+ subject="comment 7"
+ date="2013-10-13T22:14:05Z"
+ content="""
+Yes, I run the assistant in the background. The error came up after I ran
+
+ git init
+ git annex init
+ git annex direct
+ git annex assistant
+
+in a directory containing a lot of files (around 80G). Right away, `git annex status` gave me the error below. The file name in question never changed during the process of adding files and hasn't changed after all files have been added.
+
+Here's the complete command line output:
+
+ $ git annex status
+ supported backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+ supported remote types: git gcrypt S3 bup directory rsync web glacier hook
+ repository mode: direct
+ trusted repositories: 0
+ semitrusted repositories: 2
+ 00000000-0000-0000-0000-000000000001 -- web
+ c1bb8eb9-fb0c-4bac-b0df-37df25b2d1e7 -- here
+ untrusted repositories: 0
+ transfers in progress: none
+ available local disk space: 1.74 terabytes (+10 gigabytes reserved)
+
+ git-annex: /storage/media/.git/annex/tmp/problematic_file--: getFileStatus: does not exist (No such file or directory)
+ failed
+ git-annex: status: 1 failed
+
+
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_8_e493f6bddb0bfcd9478d5f4d9fc170e0._comment b/doc/bugs/git-annex:_status:_1_failed/comment_8_e493f6bddb0bfcd9478d5f4d9fc170e0._comment
new file mode 100644
index 000000000..e4fae1f31
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_8_e493f6bddb0bfcd9478d5f4d9fc170e0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="204.8.156.142"
+ subject="comment 8"
+ date="2013-10-14T17:49:05Z"
+ content="""
+Quick question: Is there any way to get rid of the error in the existing repository (e.g. remove the problematic tmp file entry) so I can get a complete status output? Bonus points if I don't have to annex every single file anew. `git annex fsck` doesn't work, as doesn't `git annex fix` (it's a direct repo).
+"""]]
diff --git a/doc/bugs/git-annex:_status:_1_failed/comment_9_573377d444aee0895b231082bc6839a4._comment b/doc/bugs/git-annex:_status:_1_failed/comment_9_573377d444aee0895b231082bc6839a4._comment
new file mode 100644
index 000000000..208f178a3
--- /dev/null
+++ b/doc/bugs/git-annex:_status:_1_failed/comment_9_573377d444aee0895b231082bc6839a4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 9"
+ date="2013-10-15T17:51:04Z"
+ content="""
+Does the file that it's complaining about exist?
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3.mdwn b/doc/bugs/git-annex_broken_on_Android_4.3.mdwn
index da1f7fd28..4c1b356fb 100644
--- a/doc/bugs/git-annex_broken_on_Android_4.3.mdwn
+++ b/doc/bugs/git-annex_broken_on_Android_4.3.mdwn
@@ -1,3 +1,7 @@
As per [[install/Android/#comment-e218073735d67691a2c3f66cc53ca6ac]] and [[install/Android/#comment-29bd13ab9cb830ffcd7850b84fb111c8]] :
git-annex is broken on Android 4.3; both on Nexus 4 and Nexus 7.
+
+> [[Fixed|done]]. A 4.3 build of the apk is now available.
+> (Unfortunately the fix breaks support for older versions of Android,
+> so two versions of the apk have to be built now.) --[[Joey]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_10_e47c073f1614f7b57f86acedeeb1cadc._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_10_e47c073f1614f7b57f86acedeeb1cadc._comment
new file mode 100644
index 000000000..5d56dc84c
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_10_e47c073f1614f7b57f86acedeeb1cadc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm7qEQF8yzbY0_PHq3QERHxUGuXmW6qw8o"
+ nickname="Anton"
+ subject="comment 10"
+ date="2013-11-10T22:10:49Z"
+ content="""
+I can confirm that the Hello World program works with the Nexus 7 2013, running Android 4.3.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_11_ce34578c45060b7c8b759efd1c1d8df8._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_11_ce34578c45060b7c8b759efd1c1d8df8._comment
new file mode 100644
index 000000000..d84a59b76
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_11_ce34578c45060b7c8b759efd1c1d8df8._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Hooray!"
+ date="2013-11-10T22:21:46Z"
+ content="""
+I have a Nexus 7 (2013) with 4.3 that I'll test it on---I expect that my test will be successful.
+
+I'll also run the test on my Nexus 5, running 4.4.
+
+Getting git-annex working on 4.3 was the last thing keeping me from being able to ditch Dropbox entirely. I'm so glad to hear there's some potential progress.
+
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_12_75965395dc33046ce34ac5ba972b7d64._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_12_75965395dc33046ce34ac5ba972b7d64._comment
new file mode 100644
index 000000000..3f520d7e4
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_12_75965395dc33046ce34ac5ba972b7d64._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 12"
+ date="2013-11-10T22:23:49Z"
+ content="""
+Full rebuild in progress (takes about 6 hours +- manual fixing).
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_13_f07bc76dd3c5580fc0855a33ae835c8d._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_13_f07bc76dd3c5580fc0855a33ae835c8d._comment
new file mode 100644
index 000000000..f2a57f731
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_13_f07bc76dd3c5580fc0855a33ae835c8d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Oh, and if a 4.3 device would be helpful..."
+ date="2013-11-10T22:28:48Z"
+ content="""
+I have Samsung Epic 4G (epic_mtd) that I'm no longer using and would be quite happy to send you---it's older, and slow, but it is at least currently supported by CyanogenMod, so it should be possible to install 10.2 milestone builds on it and at least do basic testing.
+
+Hell, if it would really facilitate Android support, I'd happily pick up something like a B&N Nook HD+ and send it to you---that should be similarly amenable to CM installs and testing.
+
+Though I will also understand if you don't necessarily want to have a bunch of superfluous hardware laying around.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_14_637c59becc68a1e4f60069d8873489ff._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_14_637c59becc68a1e4f60069d8873489ff._comment
new file mode 100644
index 000000000..6336a3bd4
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_14_637c59becc68a1e4f60069d8873489ff._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Works on KitKat"
+ date="2013-11-10T23:15:28Z"
+ content="""
+I skipped testing on my Nexus 7, figuring that would be duplicative, and instead ran it on my Nexus 5, and it worked great.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_15_d80b87055f72873f5678a01d2630bea4._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_15_d80b87055f72873f5678a01d2630bea4._comment
new file mode 100644
index 000000000..6bca41b3a
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_15_d80b87055f72873f5678a01d2630bea4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 15"
+ date="2013-11-11T04:34:21Z"
+ content="""
+6 hours later, and: <http://downloads.kitenet.net/git-annex/autobuild/android/git-annex.apk>
+
+testing appreciated!
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_16_57ac84868b223b30f005704eefa01b8d._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_16_57ac84868b223b30f005704eefa01b8d._comment
new file mode 100644
index 000000000..204845eb5
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_16_57ac84868b223b30f005704eefa01b8d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~subito"
+ nickname="subito"
+ subject="Nexus 5 Android 4.4"
+ date="2013-11-11T10:07:07Z"
+ content="""
+Does not work for me. Same error as in the original Bug report.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_17_a41f4d8a72c07ad770e6479e9b8c7f1d._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_17_a41f4d8a72c07ad770e6479e9b8c7f1d._comment
new file mode 100644
index 000000000..9712f5944
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_17_a41f4d8a72c07ad770e6479e9b8c7f1d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Same error as before, Nexus 5 and 7"
+ date="2013-11-11T13:06:17Z"
+ content="""
+Unfortunately, my experience mirrors subito's---same error as before on both 4.3 and 4.4.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_18_7d36637f11cda51de395303d5c1c6a3f._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_18_7d36637f11cda51de395303d5c1c6a3f._comment
new file mode 100644
index 000000000..2dc32cf15
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_18_7d36637f11cda51de395303d5c1c6a3f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 18"
+ date="2013-11-11T13:27:49Z"
+ content="""
+Hmm, maybe the problem is caused by stripping the program? If so, this should fail the same way: <http://tmp.kitenet.net/hello.stripped>
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_19_c8609c3f7f62ae5427fd8c60bc9546ed._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_19_c8609c3f7f62ae5427fd8c60bc9546ed._comment
new file mode 100644
index 000000000..2f22ad21c
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_19_c8609c3f7f62ae5427fd8c60bc9546ed._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Unfortunately, it would not appear that easy..."
+ date="2013-11-11T14:33:05Z"
+ content="""
+The stripped binary for hello worked fine.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_20_0886bca6d0c6a9415a7794d256be2e9d._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_20_0886bca6d0c6a9415a7794d256be2e9d._comment
new file mode 100644
index 000000000..2b547d9a7
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_20_0886bca6d0c6a9415a7794d256be2e9d._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 20"
+ date="2013-11-11T16:23:11Z"
+ content="""
+To bisect the problem space further, in case the apk build machinery is at fault, here's a git-annex binary not included in an apk. (Run same as the hello world.)
+
+<http://tmp.kitenet.net/git-annex.bin>
+
+And here's a more minimal git-annex binary (trying to look identical to hello world from the linker's perspective, just a bit larger..).
+
+<http://tmp.kitenet.net/git-annex-min.bin>
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_21_2b39729f95c9c4bba620ecdd3d1558ed._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_21_2b39729f95c9c4bba620ecdd3d1558ed._comment
new file mode 100644
index 000000000..551334819
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_21_2b39729f95c9c4bba620ecdd3d1558ed._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmqz6wCn-Q1vzrsHGvEJHOt_T5ZESilxhc"
+ nickname="Sören"
+ subject="Galaxy S4 Android 4.3"
+ date="2013-11-11T18:47:23Z"
+ content="""
+hello and hello.stripped both work here but the git-annex binaries don't (still the same error as in the bug report).
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_22_8d90d92951919aa70638b31e9248bec5._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_22_8d90d92951919aa70638b31e9248bec5._comment
new file mode 100644
index 000000000..e4937e0f8
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_22_8d90d92951919aa70638b31e9248bec5._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Both fail..."
+ date="2013-11-11T18:53:34Z"
+ content="""
+Same linking issue for both.
+
+I don't *think* it should make any difference at all, but to spare myself a little bit of typing on this soft keyboard, I'm using a small variation on your script; I'm sharing it so other testers can use it, too, and so someone can point out if I'm doing something wrong:
+
+ D=/data/data/ga/androidterm/tmp/gatest
+ cp <file> $D
+ chmod +x $D
+ $D
+
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_23_6398271f5cd9e94996202ef3bce6f6ed._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_23_6398271f5cd9e94996202ef3bce6f6ed._comment
new file mode 100644
index 000000000..05cb634e6
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_23_6398271f5cd9e94996202ef3bce6f6ed._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 23"
+ date="2013-11-11T19:14:59Z"
+ content="""
+Script variation is ok.
+
+So, it's looking like perhaps a problem with the way cabal links the executable, which I notice is a two stage process, vs the way ghc links it with --make.
+
+To narrow down, here is hello built using cabal:
+
+<http://tmp.kitenet.net/hello-cabal>
+
+Here is git-annex built not using cabal:
+
+<http://tmp.kitenet.net/git-annex-byhand>
+
+(For my own reference, it's also built without WITH_CLIBS.)
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_24_c9e399833cc6235077161f490dfa866f._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_24_c9e399833cc6235077161f490dfa866f._comment
new file mode 100644
index 000000000..c8fea212b
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_24_c9e399833cc6235077161f490dfa866f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmqz6wCn-Q1vzrsHGvEJHOt_T5ZESilxhc"
+ nickname="Sören"
+ subject="comment 24"
+ date="2013-11-11T19:56:04Z"
+ content="""
+hello-cabal working, git-annex-byhand not.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_25_cf093737eefb2b99f6f0eac9bf3e74b3._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_25_cf093737eefb2b99f6f0eac9bf3e74b3._comment
new file mode 100644
index 000000000..e28a9508b
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_25_cf093737eefb2b99f6f0eac9bf3e74b3._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="I got the same results as Sören."
+ date="2013-11-11T20:37:08Z"
+ content="""
+cabal doesn't seem to be the culprit.
+
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_26_c122ce53175fc9e0e114a8acd2385c0d._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_26_c122ce53175fc9e0e114a8acd2385c0d._comment
new file mode 100644
index 000000000..1c72cd27b
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_26_c122ce53175fc9e0e114a8acd2385c0d._comment
@@ -0,0 +1,29 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="finally getting debugger spun up"
+ date="2013-11-12T01:08:24Z"
+ content="""
+<https://code.google.com/p/android/issues/detail?id=28598> seems relevant (and the patches to fix it seem likely to have led to the linker rejecting this).
+
+So I can probably stop torturing your soft keyboards. I need a binary where `arm-linux-androideabi-4.8/bin/arm-linux-androideabi-readelf -r` does not contain `R_ARM_COPY`. Checking against the binaries so far, this consistently matches the test results, all the git-annex binaries have:
+
+<pre>
+ Offset Info Type Sym.Value Sym. Name
+011d05f0 00004e14 R_ARM_COPY 011d05f0 environ
+</pre>
+
+(Which is itself interesting; I've had to work around some problems with the haskell port not supporting getting the environment (Annex.Branch.withIndex). Possibly because it was copied and the linker screwed that up? <https://github.com/neurocyte/ghc-android/issues/7>)
+
+Ok, here's a binary that meets those criteria. Obtained by passing -z nocopyreloc to the gold linker (ghc options -optl-z -optlnocopyreloc)
+
+<http://tmp.kitenet.net/git-annex-nocopy>
+
+Also, here's a hello world binary that *should* fail. It attempts to read and print the environment, and has the same `R_ARM_COPY` relocation.
+
+<http://tmp.kitenet.net/hello-env-copy>
+
+And, here's a hello world binary that *might* successfully print out the full environment (like `set` does). If it does, I can also remove the ugly hack in Annex.Branch.withIndex. Which would be an unexpected reward.
+
+<http://tmp.kitenet.net/hello-env-nocopy>
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_27_237e41e61781bb058f5fd39362a904e4._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_27_237e41e61781bb058f5fd39362a904e4._comment
new file mode 100644
index 000000000..dd911955a
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_27_237e41e61781bb058f5fd39362a904e4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="nocopy variants work!"
+ date="2013-11-12T03:17:09Z"
+ content="""
+I tested both the hello-env-nocopy and the git-annex-nocopy binaries successfully. hello-env-copy failed as you predicted.
+
+Yay!
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_28_97f423a41ee9d2d74291594fae20dd4e._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_28_97f423a41ee9d2d74291594fae20dd4e._comment
new file mode 100644
index 000000000..6341aae80
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_28_97f423a41ee9d2d74291594fae20dd4e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 28"
+ date="2013-11-12T03:58:56Z"
+ content="""
+This fix is now in place in the android autobuilds.
+
+Just to be sure, hello-env-nocopy managed to print out multiple environment variables?
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_29_7b3fbe7e38f637fcea511441ac243d93._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_29_7b3fbe7e38f637fcea511441ac243d93._comment
new file mode 100644
index 000000000..1cd4c356f
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_29_7b3fbe7e38f637fcea511441ac243d93._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmqz6wCn-Q1vzrsHGvEJHOt_T5ZESilxhc"
+ nickname="Sören"
+ subject="APK now works too"
+ date="2013-11-12T09:10:49Z"
+ content="""
+I got the same results as Michael. The output of hello-nocopy is a longer list of environment variables.
+Even better, the apk from the autobuilder now seems to work fine as well, including the webapp.
+Great work! Thanks for digging into this.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_2_53e2d095b2501844cadec910de286814._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_2_53e2d095b2501844cadec910de286814._comment
new file mode 100644
index 000000000..3d5003504
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_2_53e2d095b2501844cadec910de286814._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 2"
+ date="2013-08-28T13:54:00Z"
+ content="""
+On a stock Nexus 7 running the latest OS (4.3), this is still the case as of release 4.20130827.
+
+ Falling back to hardcoded app location; cannot find expected files in /data/app-lib
+ git annex webapp
+ u0_a18@grouper:/sdcard/git-annex.home $ git annex webapp
+ CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?)
+ 1|u0_a18@grouper:/sdcard/git-annex.home $
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_30_26c04584c3c6dacf59e1b6c82042c97c._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_30_26c04584c3c6dacf59e1b6c82042c97c._comment
new file mode 100644
index 000000000..3409b9c4a
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_30_26c04584c3c6dacf59e1b6c82042c97c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnegApaT6kTI0Gxy9SNmI9Og-k_fC_aS7Y"
+ nickname="Michael Alan"
+ subject="Yep, the env was printed"
+ date="2013-11-12T10:18:56Z"
+ content="""
+I would recognize the output of a Show instance anywhere.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_3_ddc9cbae1a721400a9acf2153e18f4f0._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_3_ddc9cbae1a721400a9acf2153e18f4f0._comment
new file mode 100644
index 000000000..14eed81c9
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_3_ddc9cbae1a721400a9acf2153e18f4f0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkgedYqmQb4dJU7UdVuRLwsQE-KlKVrFto"
+ nickname="Chungy"
+ subject="comment 3"
+ date="2013-09-01T00:25:15Z"
+ content="""
+Just confirming the bug on my Verizon Galaxy S 3 with CyanogenMod 10.2 (Android 4.3), it's not Nexus-specific.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_4_593235735e32238094121b1f79355bbd._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_4_593235735e32238094121b1f79355bbd._comment
new file mode 100644
index 000000000..ab721064a
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_4_593235735e32238094121b1f79355bbd._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawntVnR-Z5ghYInvsElbDeADPSuCsF18iTY"
+ nickname="Thomas"
+ subject="comment 4"
+ date="2013-09-01T20:02:59Z"
+ content="""
+Yet another confirmation of the bug on a Samsung Galaxy Note running 4.3 via Cyanogenmod as well.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_5_f806fd5930e90920db24456297465bae._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_5_f806fd5930e90920db24456297465bae._comment
new file mode 100644
index 000000000..cfb75bdd8
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_5_f806fd5930e90920db24456297465bae._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="173.162.44.162"
+ subject="comment 5"
+ date="2013-09-03T14:38:51Z"
+ content="""
+If there's anything we can do to help debug this, please let us know. Have just started using git-annex on android recently & would love to have it on all my devices.
+
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_6_5741b6a5997328fdcd5cc99f841b18d3._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_6_5741b6a5997328fdcd5cc99f841b18d3._comment
new file mode 100644
index 000000000..438e00454
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_6_5741b6a5997328fdcd5cc99f841b18d3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnRai_qFYPVvEgC6i1nlM1bh-C__jbhqS0"
+ nickname="Matthew"
+ subject="Definitely broken Galaxy Nexus GSM 4.3"
+ date="2013-09-12T11:11:34Z"
+ content="""
+Definitely broken in 4.3, stock Galaxy Nexus GSM \"maguro\" release `2013-09-09 12:46`
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_7_3e0d9949dd810069af0b8076807e5924._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_7_3e0d9949dd810069af0b8076807e5924._comment
new file mode 100644
index 000000000..4a3819472
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_7_3e0d9949dd810069af0b8076807e5924._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawknwkXgi8SnK4QT32ANl3GMKvFLyQGeHqo"
+ nickname="Florian"
+ subject="comment 7"
+ date="2013-10-08T16:18:07Z"
+ content="""
+Any comment from on this from one of the maintainers would be great. Apparently this was not fixed in the latest (2013-10-02 18:46) build.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_8_f58897eff6b4693f0c73474ccfe6e733._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_8_f58897eff6b4693f0c73474ccfe6e733._comment
new file mode 100644
index 000000000..52326b8e2
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_8_f58897eff6b4693f0c73474ccfe6e733._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmhfodZquCI_EEl-f3h7HkROTszlsQL6yA"
+ nickname="Joe"
+ subject="Samsung Galaxy S4 also affected"
+ date="2013-11-09T02:47:54Z"
+ content="""
+Verizon just pushed out 4.3 to Samsung Galaxy S4 devices. This issue is affecting me now too.
+"""]]
diff --git a/doc/bugs/git-annex_broken_on_Android_4.3/comment_9_ddba87b2f20d8a63f7b8ebdb9bd13515._comment b/doc/bugs/git-annex_broken_on_Android_4.3/comment_9_ddba87b2f20d8a63f7b8ebdb9bd13515._comment
new file mode 100644
index 000000000..015efd7ce
--- /dev/null
+++ b/doc/bugs/git-annex_broken_on_Android_4.3/comment_9_ddba87b2f20d8a63f7b8ebdb9bd13515._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 9"
+ date="2013-11-10T20:12:47Z"
+ content="""
+I have finally managed to get ghc to build with the newest version of the NDK. I hope this means it will make binaries that work with 4.3, but I don't have a device to test.
+
+Here is a hello world program built with it:
+<http://tmp.kitenet.net/hello>
+
+After downloading it to an Android device, you can test it by opening the
+git-annex terminal, and running: `D=/data/data/ga.androidterm/tmp; cp hello $D; chmod +x $D/hello; $D/hello`
+
+Tested working on android 4.0.4
+
+Also, I have filed a bug upstream about this at <https://github.com/neurocyte/ghc-android/issues/23>
+"""]]
diff --git a/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__.mdwn b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__.mdwn
new file mode 100644
index 000000000..db8abfdce
--- /dev/null
+++ b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__.mdwn
@@ -0,0 +1,58 @@
+### Please describe the problem.
+
+When cloning/syncing a repository (and probably doing some nono's in the process),
+git annex will happily delete files.
+This cost me several files, which just by coincidence were not totally important, still its *very* unsettling.
+
+### What steps will reproduce the problem?
+
+I did not try to exactly reproduce it yet (sorry, no time right now), but here is vaguley what I did (sorry its been a process spread over
+several hours and i was doing lots of other things in parallel so I'm fuzzy about details):
+
+ * have a repository in direct mode on your local harddrive, say ~/myannex
+ * git clone ~/myannex to /usbhd/myannex, git annex init.
+ The usbhd is a FAT, git annex recognizes it as "crippled filessytem".
+ * Git annex get all from ~/myannex. So far, so good.
+ * create several files on ~/myannex, git annex add them
+ * do a git annex add on them, abort it (realizing SHA256E takes forever, so changing to WORM), repeat add
+ (not sure wheter i did a git annex sync here)
+ * create several files on /usbhd/myannex, git annex add them
+ (not sure wheter i did a git annex sync here again)
+
+All repos are in direct mode.
+
+From here on i don't remember the exact order of events, one definite -- probably important -- nono i did,
+was:
+I executed a git annex sync/get on the usbhd in a sub-directory (i.e. not in the git base dir), say /usbhd/myannex/foo/bar/,
+so it went on creating /usbhd/myannex/foo/bar/foo, which of course was not intended.
+However /usbhd/myannex/foo/bar/foo contained FAT-crippled-symlinks to the new files in ~/myannex (good).
+
+In order to avoid a potential messy situation i just renamed /usbhd/myannex/foo to /usbhd/myannex/foo_bak
+(which I just realize while writing this, saved me the hash values of my files, yay :))
+
+However when I tried to repeat the procedure, it seems that the new files would not appear on the usbhd (for a reason i totally don't get, maybe I synced back before realizing my sub-foo mistake).
+When I synced usbhd -> ~/myannex again, git-annex happily deleted my new files there which obviously quite upset me.
+
+Again, sorry for this horribly chaotic description,
+I'll try and deliver a more reproducible description, but for the next 2 weeks at least I'm too busy for that.
+
+
+
+### What version of git-annex are you using? On what operating system?
+
+Archlinux,
+3.9.2-1-ARCH #1 SMP PREEMPT Sat May 11 20:31:08 CEST 2013 x86_64 GNU/Linux
+
+aur/git-annex-bin 4.20131002-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
+
+
+# End of transcript or log.
+"""]]
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_1_5dd4d1cec069c13184f5dd9efca6721b._comment b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_1_5dd4d1cec069c13184f5dd9efca6721b._comment
new file mode 100644
index 000000000..a8994ba9a
--- /dev/null
+++ b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_1_5dd4d1cec069c13184f5dd9efca6721b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://droggl.myopenid.com/"
+ ip="92.76.150.86"
+ subject="comment 1"
+ date="2013-10-08T07:46:35Z"
+ content="""
+Just in case you wonder: the most important (in the sense of not backupped elswhere) files where some scripts which i did hash with SHA256E and not with WORM.
+"""]]
diff --git a/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_2_d9b65fe4cb4bfd58f37e7da5350c6401._comment b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_2_d9b65fe4cb4bfd58f37e7da5350c6401._comment
new file mode 100644
index 000000000..8574d974b
--- /dev/null
+++ b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_2_d9b65fe4cb4bfd58f37e7da5350c6401._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="git annex get/sync don't delete files"
+ date="2013-10-10T11:43:29Z"
+ content="""
+AFAIU it's impossible for the 'get' subcommand to delete anything because it only copies files to .git/annex/objects.
+
+'sync' should also never delete files because it only adds files to the annex (i.e. checksums them and sets up the links and directories in .git/annex), commits things to git and pulls/pushes the git-annex specific branches to/from other repos.
+
+So I think some other 'nono' must have messed up your files.
+
+If you ever used (maybe unintentionally) used indirect mode there seem to be a rather high chance that some of your otherwise lost content is still in .git/annex/objects. Did you check if there's are any files in .git/annex/objects ?
+"""]]
diff --git a/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_3_1027187b203addd65af8cf1faf28727d._comment b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_3_1027187b203addd65af8cf1faf28727d._comment
new file mode 100644
index 000000000..d5c08fb4f
--- /dev/null
+++ b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_3_1027187b203addd65af8cf1faf28727d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 3"
+ date="2013-10-16T20:45:25Z"
+ content="""
+At least part of this sounds like [[direct_mode_assistant_in_subdir_confusion]]. The report is too confused for me to tell if that's the whole of the problem.
+
+Note that git-annex stores files in git, so if it did something wrong, you can switch to indirect mode, and use regular git commands to check out a tree from before the problem occurred.
+"""]]
diff --git a/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_4_ac65028203ff0cbdb978200235fb4e9c._comment b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_4_ac65028203ff0cbdb978200235fb4e9c._comment
new file mode 100644
index 000000000..be972fa9a
--- /dev/null
+++ b/doc/bugs/git-annex_happily_deleted_most_of_my_files___36____35____38____33__/comment_4_ac65028203ff0cbdb978200235fb4e9c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 4"
+ date="2013-10-26T19:26:22Z"
+ content="""
+I have moreinfoed this bug, until I hear back with a better problem description.
+
+Using `git log --stat` to investigate any commits where files were removed would probably be a useful way to get a handle on what happened.
+"""]]
diff --git a/doc/bugs/git-annex_merge_stalls.mdwn b/doc/bugs/git-annex_merge_stalls.mdwn
new file mode 100644
index 000000000..98615e352
--- /dev/null
+++ b/doc/bugs/git-annex_merge_stalls.mdwn
@@ -0,0 +1,16 @@
+### Please describe the problem.
+
+Running git-annex merge shows the output "git-annex merge ", followed by a blinking cursor. The command never seems to end.
+
+### What steps will reproduce the problem?
+
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130827-gd04d9bb on MacOS X Mountain Lion
+
+### Please provide any additional information below.
+
+dtruss output at https://www.dropbox.com/s/4b3yqn7ajfz5el2/annex-merge.log
+
+[[!meta title="no indication when git-annex is stuck waiting for a lock"]]
diff --git a/doc/bugs/git-annex_merge_stalls/comment_1_31578a754945bdcb902c62ff58704bcb._comment b/doc/bugs/git-annex_merge_stalls/comment_1_31578a754945bdcb902c62ff58704bcb._comment
new file mode 100644
index 000000000..123212d5d
--- /dev/null
+++ b/doc/bugs/git-annex_merge_stalls/comment_1_31578a754945bdcb902c62ff58704bcb._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T15:45:17Z"
+ content="""
+The relevant part of the log is:
+
+<pre>
+65332/0x53591a: open(\"/Users/gsolsberry/annex/.git/annex/journal.lck\0\", 0x601, 0x1B6) = 8 0
+65332/0x53591a: fcntl(0x8, 0x9, 0x107009D60) = -1 Err#-1
+</pre>
+
+waitToSetLock thinks fcntl is failing to lock the file due to something else having it locked, and retries, leading to the hang.
+
+I'm told on irc that this was installed using the prebuilt image, and that a previous version of it didn't have the problem.
+"""]]
diff --git a/doc/bugs/git-annex_merge_stalls/comment_2_f3b6bf180466b5931bfd20b2f0229422._comment b/doc/bugs/git-annex_merge_stalls/comment_2_f3b6bf180466b5931bfd20b2f0229422._comment
new file mode 100644
index 000000000..2fe9b8ac0
--- /dev/null
+++ b/doc/bugs/git-annex_merge_stalls/comment_2_f3b6bf180466b5931bfd20b2f0229422._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl8B4Ima-VCCJ4y32Gvfii8EmvTyN9tFGM"
+ nickname="Glendon"
+ subject="comment 2"
+ date="2013-09-09T15:54:59Z"
+ content="""
+With latest 20130909 version, the following log from git-annex merge:
+
+https://www.dropbox.com/s/3hklzfsflpxuk5s/annex-merge.log.1
+"""]]
diff --git a/doc/bugs/git-annex_merge_stalls/comment_3_ced9b0d724fb55c756106b64c3721003._comment b/doc/bugs/git-annex_merge_stalls/comment_3_ced9b0d724fb55c756106b64c3721003._comment
new file mode 100644
index 000000000..600044354
--- /dev/null
+++ b/doc/bugs/git-annex_merge_stalls/comment_3_ced9b0d724fb55c756106b64c3721003._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 3"
+ date="2013-09-09T19:35:25Z"
+ content="""
+This problem cleared up after a reboot (and a crash, apparently).
+
+<pre>
+joeyh so, my thought is that perhaps you had a git-annex process before that was holding the lock.
+joeyh for example, if you ran it and ctrl-z'd at just the right time, it could be suspended and holding the lock
+joeyh (or the kernel coud have gotten confused, which given you also had a crash, who knows..)
+dp sounds logical
+joeyh forcing locks is always a problimatic thing
+joeyh but git-annex could certianly notice if it seems to be stalled and print some useful messages
+joeyh and maybe have a way to run with locks forced
+</pre>
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files.mdwn b/doc/bugs/git-annex_opens_too_many_files.mdwn
new file mode 100644
index 000000000..d5830be57
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files.mdwn
@@ -0,0 +1,40 @@
+[[!meta title="network-muticast FD leak fix not deployed to Linux autobuilds yet"]]
+
+### Please describe the problem.
+After running git-annex some minutes, the websites is not responsible any more and it even crashes eventually.
+
+### What steps will reproduce the problem?
+Start the assistant.
+
+### What version of git-annex are you using? On what operating system?
+it-annex version: 4.20130802-g1452ac3
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+
+### 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
+[2013-08-06 13:32:51 CEST] main: starting assistant version 4.20130802-g1452ac3
+
+Already up-to-date.
+(scanning...) [2013-08-06 13:32:51 CEST] Watcher: Performing startup scan
+
+Already up-to-date.
+(started...)
+git-annex: accept: resource exhausted (Too many open files)
+[2013-08-06 19:50:37 CEST] read: git ["--git-dir=/home/christian/git-annex/.git","--work-tree=/home/+christian/git-annex","symbolic-ref","HEAD"]
+git-annex: runInteractiveProcess: pipe: Too many open files
+[2013-08-06 19ND:ea5te1Wm:ao1tn1cS htCeaErtSFuTas]l lcNbreaatcsWkha etcdcr:ha es/rhh:eo dmd:ee /tgc+eihctrt:ie sdct rineaeantt/wegoPirrtko- cacenosnnsen:xe /cr.tegisiootnu/
+racnen[ e2ex0x/1h:3a -uo0sp8te-en0dT6 e (m1Tp9oF:oi5 l1me:a:1n 1yr eCosEpoSeuTnr] c feri eleaexdsh:+)a
+ugsitte d[ "(-T-ogoi tm-adniyr =o/pheonm ef/iclhersi)s
+tian/git-annex/.git","--work-tree=/home/christian/git-annex","symbolic-ref","HEAD"]
+git-annex: runInteractiveProcess: pipe: Too many open files
+git-annex: git: createProcess: resource exhausted (Too many open files)
+[2013-08-06 19:51:11 CEST] NetWatcherFallback: warning NetWatcherFallback crashed: git: createProces+s: resource exhausted (Too many open files)
+[2013-08-06 19:51:11 CEST] DaemonStatus: warning DaemonStatus crashed: /home/christian/git-annex/.gi+t/annex/: openTempFile: resource exhausted (Too many open files)
+
+(system was asleep from 14:00 until 19:50)
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_1_37f6f5838c41c533df4be1f927b9b03d._comment b/doc/bugs/git-annex_opens_too_many_files/comment_1_37f6f5838c41c533df4be1f927b9b03d._comment
new file mode 100644
index 000000000..de5dde9b5
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_1_37f6f5838c41c533df4be1f927b9b03d._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="chrisbra"
+ ip="80.149.220.45"
+ subject="sorry, added some wrapping signs from vim."
+ date="2013-08-06T18:01:40Z"
+ content="""
+[2013-08-06 13:32:51 CEST] main: starting assistant version 4.20130802-g1452ac3
+
+Already up-to-date.
+(scanning...) [2013-08-06 13:32:51 CEST] Watcher: Performing startup scan
+
+Already up-to-date.
+(started...)
+git-annex: accept: resource exhausted (Too many open files)
+[2013-08-06 19:50:37 CEST] read: git [\"--git-dir=/home/christian/git-annex/.git\",\"--work-tree=/home/christian/git-annex\",\"symbolic-ref\",\"HEAD\"]
+git-annex: runInteractiveProcess: pipe: Too many open files
+[2013-08-06 19ND:ea5te1Wm:ao1tn1cS htCeaErtSFuTas]l lcNbreaatcsWkha etcdcr:ha es/rhh:eo dmd:ee /tgceihctrt:ie sdct rineaeantt/wegoPirrtko- cacenosnnsen:xe /cr.tegisiootnu/
+racnen[ e2ex0x/1h:3a -uo0sp8te-en0dT6 e (m1Tp9oF:oi5 l1me:a:1n 1yr eCosEpoSeuTnr] c feri eleaexdsh:)a
+ugsitte d[ \"(-T-ogoi tm-adniyr =o/pheonm ef/iclhersi)s
+tian/git-annex/.git\",\"--work-tree=/home/christian/git-annex\",\"symbolic-ref\",\"HEAD\"]
+git-annex: runInteractiveProcess: pipe: Too many open files
+git-annex: git: createProcess: resource exhausted (Too many open files)
+[2013-08-06 19:51:11 CEST] NetWatcherFallback: warning NetWatcherFallback crashed: git: createProcess: resource exhausted (Too many open files)
+[2013-08-06 19:51:11 CEST] DaemonStatus: warning DaemonStatus crashed: /home/christian/git-annex/.git/annex/: openTempFile: resource exhausted (Too many open files)
+
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_2_347ef233b9845b84d7c4d49ed166e797._comment b/doc/bugs/git-annex_opens_too_many_files/comment_2_347ef233b9845b84d7c4d49ed166e797._comment
new file mode 100644
index 000000000..381d425fc
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_2_347ef233b9845b84d7c4d49ed166e797._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 2"
+ date="2013-08-07T15:59:59Z"
+ content="""
+What operating system is this?
+
+Can you see which files the git-annex process has open?
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_3_d5f644d97cd2db471deb5dcd728cae60._comment b/doc/bugs/git-annex_opens_too_many_files/comment_3_d5f644d97cd2db471deb5dcd728cae60._comment
new file mode 100644
index 000000000..fbd3bce8f
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_3_d5f644d97cd2db471deb5dcd728cae60._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="chrisbra"
+ ip="212.121.153.12"
+ subject="This is ubuntu 12.10"
+ date="2013-08-12T13:30:00Z"
+ content="""
+This is ubuntu 12.10 and seems to be the same problem which has been mentioned before (resource exhausted or similar)
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_4_c03bde64be8fdd962826bc7afa07d2a9._comment b/doc/bugs/git-annex_opens_too_many_files/comment_4_c03bde64be8fdd962826bc7afa07d2a9._comment
new file mode 100644
index 000000000..b4c458706
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_4_c03bde64be8fdd962826bc7afa07d2a9._comment
@@ -0,0 +1,137 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlmRpGORNKWimtzqItvwm4I6cn16vx8OvU"
+ nickname="hayden"
+ subject="Many network sockets with associated fds hanging around"
+ date="2013-08-15T18:00:42Z"
+ content="""
+I see something similar in logs and after roughly 10 mins the web-apps dies.
+So I think I hit the same as the above user.
+Sometimes I get thread deaths and restart requests but the root cause appears to match the scenario mentioned over.
+Often the webapp just hangs. But always when it hits the fd ulimit... 1024 on this system.
+
+git-annex version is 4.20130802-g1452ac3 and I used the static-linked linux tar.gz linux-binary download.
+
+Test setup is a from scratch assistant startup on Ubuntu 12.04.
+Not exactly a clean ubuntu though, so maybe difficult to duplicate troubles at your end.
+
+I fired up the web-app with a cleaned out config. No signs of leaks until an annex is created.
+On creation of an empty annex I get fd leaks a about 1 per second after a repository is created.
+Strace'ing the main process only shows 8-bytes writes (see below) at the same rate as the leak.
+Sometimes the fd-leak stops before the resource limit, sometimes not.
+Creating a new annex on top of an existing directory tree with many files is pretty reliable trigger though.
+Startup scan finishes and fds leak away until the ulimit is hit.
+
+ hayden@orca:~/gamma$ ls /proc/26319/fd
+ 0 10 12 14 16 18 2 21 23 25 27 29 30 32 34 36 38 4 41 43 45 6 8
+ 1 11 13 15 17 19 20 22 24 26 28 3 31 33 35 37 39 40 42 44 5 7 9
+ hayden@orca:~/gamma$ ls /proc/26319/fd
+ 0 10 12 14 16 18 2 21 23 25 27 29 30 32 34 36 38 4 41 43 45 6 8
+ 1 11 13 15 17 19 20 22 24 26 28 3 31 33 35 37 39 40 42 44 5 7 9
+ hayden@orca:~/gamma$ ls /proc/26319/fd
+ 0 10 12 14 16 18 2 21 23 25 27 29 30 32 34 36 38 4 41 43 45 5 7 9
+ 1 11 13 15 17 19 20 22 24 26 28 3 31 33 35 37 39 40 42 44 46 6 8
+
+ hayden@orca:~/gamma$ ls /proc/26319/fd/43
+ /proc/26319/fd/43
+
+ hayden@orca:~/gamma$ ls -l /proc/26319/fd/43
+ ls -l /proc/26319/fd/43
+ lrwx------ 1 hayden hayden 64 Aug 14 21:10 /proc/26319/fd/43 -> socket:[568994]
+
+ hayden@orca:~/gamma$ lsof | grep 568994
+ git-annex 26319 hayden 43u IPv4 568994 0t0 UDP 224.0.0.251:55556
+
+ hayden@orca:~/gamma$ uname -a
+ Linux orca 3.2.0-25-generic #40-Ubuntu SMP Wed May 23 20:30:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
+
+ hayden@orca:~/gamma$ cat /etc/issue
+ Ubuntu 12.04 LTS \n \l
+
+ hayden@orca:~/gamma$ fuser 55556/udp -a
+ 55556/udp: 4415 26319 27080 27083
+
+ hayden@orca:~/gamma$ ps aux | grep 4415
+ hayden 4415 0.0 0.0 66716 3036 ? S Aug12 0:03 curl -s --head -L http://127.0.0.1:38464/?auth=da9c4aba4cc2db9cf78574753f6e94d8031c6a7bdf8bfe100bde868f57b81fd751965cc9d68a9afac79f826d257a256a04ce62615a7f23cd7c925969dda1c7b8 -w %{http_code}
+ hayden 27458 0.0 0.0 10612 924 pts/0 S+ 21:50 0:00 grep --color=auto 4415
+
+ hayden@orca:~/gamma$ ps aux | grep 26319
+ hayden 26319 0.1 0.7 497188 28560 pts/5 Sl 21:09 0:04 git-annex webapp
+ hayden 26338 3.4 3.4 1035572 137864 pts/5 Sl 21:09 1:25 /usr/lib/firefox/firefox /tmp/webapp26319.html
+ hayden 27460 0.0 0.0 10612 920 pts/0 S+ 21:50 0:00 grep --color=auto 26319
+
+ hayden@orca:~/gamma$ ps aux | grep 27080
+ hayden 27080 0.0 0.0 16476 1288 pts/5 S 21:33 0:00 git --git-dir=/home/hayden/boo/.git --work-tree=/home/hayden/boo cat-file --batch
+ hayden 27462 0.0 0.0 10612 924 pts/0 S+ 21:50 0:00 grep --color=auto 27080
+
+ hayden@orca:~/gamma$ ps aux | grep 27083
+ hayden 27083 0.0 0.0 16476 1060 pts/5 S 21:33 0:00 git --git-dir=/home/hayden/boo/.git --work-tree=/home/hayden/boo check-attr -z --stdin annex.backend annex.numcopies --
+ hayden 27464 0.0 0.0 10612 920 pts/0 S+ 21:51 0:00 grep --color=auto 27083
+
+----> has 579 open fds at this point but this number holds stable over 10 min
+(copy in new tree to provoke)
+(no change)
+----> restart daemon in gui to provoke
+(new process has open fds slowly climbing after startup scan)
+
+straces look like this repeating every second. (clipped down)
+
+ futex(0x34f001c, FUTEX_WAIT_PRIVATE, 51, NULL) = ? ERESTARTSYS (To be restarted)
+ --- SIGVTALRM (Virtual timer expired) @ 0 (0) ---
+ rt_sigreturn(0x1a) = 202
+ futex(0x34f001c, FUTEX_WAIT_PRIVATE, 51, NULL) = ? ERESTARTSYS (To be restarted)
+ --- SIGVTALRM (Virtual timer expired) @ 0 (0) ---
+ rt_sigreturn(0x1a) = 202
+ futex(0x34f001c, FUTEX_WAIT_PRIVATE, 51, NULL) = ? ERESTARTSYS (To be restarted)
+ --- SIGVTALRM (Virtual timer expired) @ 0 (0) ---
+ rt_sigreturn(0x1a) = 202
+ futex(0x34f001c, FUTEX_WAIT_PRIVATE, 51, NULL) = ? ERESTARTSYS (To be restarted)
+ --- SIGVTALRM (Virtual timer expired) @ 0 (0) ---
+ write(6, \"\377\0\0\0\0\0\0\0\", 8) = 8
+ rt_sigreturn(0x2) = 202
+ futex(0x34f001c, FUTEX_WAIT_PRIVATE, 51, NULL^C <unfinished ...>
+ Process 29803 detached
+
+Until after roughly 10 mins...
+
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1017
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1023
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1024
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1024
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1024
+ hayden@orca:~/boo$ ls /proc/29803/fd | wc -l
+ 1024
+
+ hayden@orca:~/boo$ ulimit -a
+ core file size (blocks, -c) 0
+ data seg size (kbytes, -d) unlimited
+ scheduling priority (-e) 0
+ file size (blocks, -f) unlimited
+ pending signals (-i) 31164
+ max locked memory (kbytes, -l) 64
+ max memory size (kbytes, -m) unlimited
+ open files (-n) 1024
+ pipe size (512 bytes, -p) 8
+ POSIX message queues (bytes, -q) 819200
+ real-time priority (-r) 0
+ stack size (kbytes, -s) 8192
+ cpu time (seconds, -t) unlimited
+ max user processes (-u) 31164
+ virtual memory (kbytes, -v) unlimited
+ file locks (-x) unlimited
+ hayden@orca:~/boo$
+
+At this point the webapp hangs but a number of interesting crashes may occur. I've also seen the particular error in the previous users log (on a big tree).
+
+ [2013-08-14 21:56:12 CEST] main: starting assistant version 4.20130802-g1452ac3
+ (scanning...) [2013-08-14 21:56:12 CEST] Watcher: Performing startup scan
+ (started...) DaemonStatus crashed: /home/hayden/boo/.git/annex/: openTempFile: resource exhausted (Too many open files)
+ [2013-08-14 22:06:12 CEST] DaemonStatus: warning DaemonStatus crashed: /home/hayden/boo/.git/annex/: openTempFile: resource exhausted (Too many open files)
+
+Is any of the above helpful? Anything else useful to kick for testing that you'd like done?
+I'd guess this is something weird with my ubuntu setup that provokes this as more users would see it otherwise.
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_5_33a2e783e5355e981497b9861997570b._comment b/doc/bugs/git-annex_opens_too_many_files/comment_5_33a2e783e5355e981497b9861997570b._comment
new file mode 100644
index 000000000..786672eb2
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_5_33a2e783e5355e981497b9861997570b._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 5"
+ date="2013-08-24T17:09:43Z"
+ content="""
+Thanks for an excellent amount of debug information.
+
+I can see what's leaking is UDP connections to 224.0.0.251. That address is used for the \"local pairing\" option in the webapp.
+
+I was able to reproduce the problem by disabling all network interfaces except `lo`. The PairListener then failed to open a multicast listening socket. When it fails that way, it retried every second, as you noticed. And there is a socket leak in that failure mode.
+
+I wonder if you're seeing this even when on the network? If so, perhaps your Ubuntu system has something going on that prevents opening a multicast listening socket on even `eth0` or `wlan0` or whatever.
+
+Unfortunately, the actual socket leak bug is in the [network-multicast](http://hackage.haskell.org/package/network-multicast) library, and not in git-annex. I have filed an upstream bug report: <https://github.com/audreyt/network-multicast/issues/4>
+
+Hopefully that will be dealt with soon. There is a workaround I could do in git-annex: If it fails (leaking one socket), it could wait until the NetworkListener indicated a new network interface was opened, before trying again (possibly leaking one socket again). This would change it from a 1 per second leak to a 1 per change of network leak at worst, which is probably much less likely to cause problems.
+"""]]
diff --git a/doc/bugs/git-annex_opens_too_many_files/comment_6_b3a5a4e4ca29c5cd2840bfeb4c63ea68._comment b/doc/bugs/git-annex_opens_too_many_files/comment_6_b3a5a4e4ca29c5cd2840bfeb4c63ea68._comment
new file mode 100644
index 000000000..60c268fc0
--- /dev/null
+++ b/doc/bugs/git-annex_opens_too_many_files/comment_6_b3a5a4e4ca29c5cd2840bfeb4c63ea68._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 6"
+ date="2013-08-24T18:38:56Z"
+ content="""
+My NetListener workaround turned out to not be portable enough.
+
+However, I have sent a patch to fix the FD leak: <https://github.com/audreyt/network-multicast/pull/6>
+Hopefully it gets applied soon.
+
+I have also made the PairListener only retry every 60 seconds. Which makes the leak 1/60th as bad, for whatever that's worth.
+
+Once a fix for this gets into Debian, I need to remember to backport it to stable, and update the autobuilders to use it. Also need to remember to update the Android autobuilder. Leaving this bug report open until that happens.
+"""]]
diff --git a/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__.mdwn b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__.mdwn
new file mode 100644
index 000000000..a682c12cc
--- /dev/null
+++ b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__.mdwn
@@ -0,0 +1,358 @@
+### Please describe the problem.
+
+I installed the git-annex app for MacOSX (10.8.4)
+
+### What steps will reproduce the problem?
+
+- Created a repository
+- In the configuration, entered my google username/password
+
+### What version of git-annex are you using? On what operating system?
+
+bundle version: 0.0.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
+
+Process: git-annex [12934]
+Path: /Applications/git-annex.app/Contents/MacOS/bundle/git-annex
+Identifier: git-annex
+Version: 0
+Code Type: X86-64 (Native)
+Parent Process: ??? [1]
+User ID: 502
+
+Date/Time: 2013-08-17 12:27:12.495 -0700
+OS Version: Mac OS X 10.8.4 (12E55)
+Report Version: 10
+Sleep/Wake UUID: 6DB42174-0147-4C8B-B83E-F305823297CA
+
+Interval Since Last Report: 294009 sec
+Crashes Since Last Report: 4
+Per-App Crashes Since Last Report: 4
+Anonymous UUID: 0D492F72-DAE5-360C-A6D6-ECB38FD53115
+
+Crashed Thread: 3
+
+Exception Type: EXC_BAD_ACCESS (SIGSEGV)
+Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
+
+VM Regions Near 0:
+-->
+ __TEXT 000000010b5e6000-000000010e08d000 [ 42.7M] r-x/rwx SM=COW /Applications/git-annex.app/Contents/MacOS/bundle/git-annex
+
+Thread 0:: Dispatch queue: com.apple.main-thread
+0 libsystem_kernel.dylib 0x00007fff931400fa __psynch_cvwait + 10
+1 libsystem_c.dylib 0x00007fff86adffe9 _pthread_cond_wait + 869
+2 git-annex 0x000000010df20179 0x10b5e6000 + 43229561
+3 git-annex 0x000000010defc8eb 0x10b5e6000 + 43084011
+4 git-annex 0x000000010df0bc86 0x10b5e6000 + 43146374
+5 git-annex 0x000000010df0c6fb 0x10b5e6000 + 43149051
+6 git-annex 0x000000010df07b46 0x10b5e6000 + 43129670
+7 git-annex 0x000000010df07c69 0x10b5e6000 + 43129961
+8 git-annex 0x000000010bcff518 0x10b5e6000 + 7443736
+9 libdyld.dylib 0x00007fff8c3e47e1 start + 1
+
+Thread 1:
+0 libsystem_kernel.dylib 0x00007fff931400fa __psynch_cvwait + 10
+1 libsystem_c.dylib 0x00007fff86adffe9 _pthread_cond_wait + 869
+2 git-annex 0x000000010df20179 0x10b5e6000 + 43229561
+3 git-annex 0x000000010defc8eb 0x10b5e6000 + 43084011
+4 git-annex 0x000000010df0bc86 0x10b5e6000 + 43146374
+5 git-annex 0x000000010df0c5e0 0x10b5e6000 + 43148768
+6 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+7 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 2:
+0 libsystem_kernel.dylib 0x00007fff931400fa __psynch_cvwait + 10
+1 libsystem_c.dylib 0x00007fff86adffe9 _pthread_cond_wait + 869
+2 git-annex 0x000000010df20179 0x10b5e6000 + 43229561
+3 git-annex 0x000000010defc8eb 0x10b5e6000 + 43084011
+4 git-annex 0x000000010df0bc86 0x10b5e6000 + 43146374
+5 git-annex 0x000000010df0c5e0 0x10b5e6000 + 43148768
+6 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+7 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 3 Crashed:
+0 libsystem_c.dylib 0x00007fff86ae0bf9 pthread_mutex_lock + 20
+1 H 0x000000010e9fd29f gnutls_system_mutex_lock + 12
+2 H 0x000000010ea7fa29 wrap_nettle_rnd_refresh + 20
+3 H 0x000000010e9fee89 gnutls_deinit + 42
+4 git-annex 0x000000010caf0a3a 0x10b5e6000 + 22063674
+
+Thread 4:
+0 libsystem_kernel.dylib 0x00007fff93140d2a kevent64 + 10
+1 git-annex 0x000000010deab5fa 0x10b5e6000 + 42751482
+
+Thread 5:
+0 libsystem_kernel.dylib 0x00007fff931400fa __psynch_cvwait + 10
+1 libsystem_c.dylib 0x00007fff86adffe9 _pthread_cond_wait + 869
+2 git-annex 0x000000010df20179 0x10b5e6000 + 43229561
+3 git-annex 0x000000010defc8eb 0x10b5e6000 + 43084011
+4 git-annex 0x000000010df0bc86 0x10b5e6000 + 43146374
+5 git-annex 0x000000010df0c5e0 0x10b5e6000 + 43148768
+6 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+7 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 6:: Dispatch queue: com.apple.libdispatch-manager
+0 libsystem_kernel.dylib 0x00007fff93140d16 kevent + 10
+1 libdispatch.dylib 0x00007fff8e6fedea _dispatch_mgr_invoke + 883
+2 libdispatch.dylib 0x00007fff8e6fe9ee _dispatch_mgr_thread + 54
+
+Thread 7:
+0 libsystem_kernel.dylib 0x00007fff9313e686 mach_msg_trap + 10
+1 libsystem_kernel.dylib 0x00007fff9313dc42 mach_msg + 70
+2 com.apple.CoreFoundation 0x00007fff8c1e2233 __CFRunLoopServiceMachPort + 195
+3 com.apple.CoreFoundation 0x00007fff8c1e7916 __CFRunLoopRun + 1078
+4 com.apple.CoreFoundation 0x00007fff8c1e70e2 CFRunLoopRunSpecific + 290
+5 com.apple.CoreFoundation 0x00007fff8c1f5dd1 CFRunLoopRun + 97
+6 git-annex 0x000000010c72b3ec 0x10b5e6000 + 18109420
+7 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+8 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 8:
+0 libsystem_kernel.dylib 0x00007fff9313e686 mach_msg_trap + 10
+1 libsystem_kernel.dylib 0x00007fff9313dc42 mach_msg + 70
+2 com.apple.CoreFoundation 0x00007fff8c1e2233 __CFRunLoopServiceMachPort + 195
+3 com.apple.CoreFoundation 0x00007fff8c1e7916 __CFRunLoopRun + 1078
+4 com.apple.CoreFoundation 0x00007fff8c1e70e2 CFRunLoopRunSpecific + 290
+5 com.apple.CoreFoundation 0x00007fff8c1f5dd1 CFRunLoopRun + 97
+6 git-annex 0x000000010c72b3ec 0x10b5e6000 + 18109420
+7 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+8 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 9:
+0 libsystem_kernel.dylib 0x00007fff9313e686 mach_msg_trap + 10
+1 libsystem_kernel.dylib 0x00007fff9313dc42 mach_msg + 70
+2 com.apple.CoreFoundation 0x00007fff8c1e2233 __CFRunLoopServiceMachPort + 195
+3 com.apple.CoreFoundation 0x00007fff8c1e7916 __CFRunLoopRun + 1078
+4 com.apple.CoreFoundation 0x00007fff8c1e70e2 CFRunLoopRunSpecific + 290
+5 com.apple.CoreFoundation 0x00007fff8c1f5dd1 CFRunLoopRun + 97
+6 git-annex 0x000000010c72b3ec 0x10b5e6000 + 18109420
+7 libsystem_c.dylib 0x00007fff86adb7a2 _pthread_start + 327
+8 libsystem_c.dylib 0x00007fff86ac81e1 thread_start + 13
+
+Thread 3 crashed with X86 Thread State (64-bit):
+ rax: 0x000000010eaaca28 rbx: 0x00007f9dc38000c0 rcx: 0x000000010f87ce00 rdx: 0x000000010e3c28f0
+ rdi: 0x0000000000000000 rsi: 0x001c4500001c4500 rbp: 0x000000010f87ce10 rsp: 0x000000010f87cdd0
+ r8: 0x0000000000002060 r9: 0x000000010f87ce00 r10: 0x000000010eabf328 r11: 0x000000010e9fee5f
+ r12: 0x000000010f5585d8 r13: 0x000000010e3c2798 r14: 0x0000000000000000 r15: 0x000000010f548140
+ rip: 0x00007fff86ae0bf9 rfl: 0x0000000000010202 cr2: 0x0000000000000000
+Logical CPU: 0
+
+Binary Images:
+ 0x10b5e6000 - 0x10e08cff7 +git-annex (0) <2C4C13B3-4830-322A-A144-9E51B386EB1E> /Applications/git-annex.app/Contents/MacOS/bundle/git-annex
+ 0x10e85a000 - 0x10e957ff7 +E (22.3) <47B09CB2-C636-3024-8B55-6040F7829B4C> /Applications/git-annex.app/Contents/MacOS/bundle/E
+ 0x10e990000 - 0x10e9a4fff +F (0) <FA90B1B1-A866-3A6C-BB97-06955F4C8C0B> /Applications/git-annex.app/Contents/MacOS/bundle/F
+ 0x10e9ab000 - 0x10e9d8ff7 +G (0) <D80652C0-9A55-351C-8EAF-2364359BA0A2> /Applications/git-annex.app/Contents/MacOS/bundle/G
+ 0x10e9de000 - 0x10eaabfdf +H (0) <29C3AFF5-8EFB-3A16-81F6-0DA6CF2675A6> /Applications/git-annex.app/Contents/MacOS/bundle/H
+ 0x10eadd000 - 0x10eaefff7 +B (43) <2A1551E8-A272-3DE5-B692-955974FE1416> /Applications/git-annex.app/Contents/MacOS/bundle/B
+ 0x10eaf7000 - 0x10ebecfff +D (34) <FEE8B996-EB44-37FA-B96E-D379664DEFE1> /Applications/git-annex.app/Contents/MacOS/bundle/D
+ 0x10ec01000 - 0x10ed1992f +I (532.2) <90D31928-F48D-3E37-874F-220A51FD9E37> /Applications/git-annex.app/Contents/MacOS/bundle/I
+ 0x10ed3d000 - 0x10ef3dfff +S (491.11.3) <5783D305-04E8-3D17-94F7-1CEAFA975240> /Applications/git-annex.app/Contents/MacOS/bundle/S
+ 0x10f048000 - 0x10f06dff7 +Z (26) <D86169F3-9F31-377A-9AF3-DB17142052E4> /Applications/git-annex.app/Contents/MacOS/bundle/Z
+ 0x10f0a1000 - 0x10f109ff7 +0A (65.1) <20E31B90-19B9-3C2A-A9EB-474E08F9FE05> /Applications/git-annex.app/Contents/MacOS/bundle/0A
+ 0x10f163000 - 0x10f1ccfff +0B (56) <EAA2B53E-EADE-39CF-A0EF-FB9D4940672A> /Applications/git-annex.app/Contents/MacOS/bundle/0B
+ 0x10f235000 - 0x10f248fff +T (0) <C8970714-4C86-3BE6-94D6-4835DCC8A003> /Applications/git-annex.app/Contents/MacOS/bundle/T
+ 0x10f257000 - 0x10f264ff7 +U (0) <DCFF385A-090B-3407-868C-91544A2EFEE1> /Applications/git-annex.app/Contents/MacOS/bundle/U
+ 0x10f26f000 - 0x10f291ff7 +V (0) <51B317C7-94CC-3C58-B515-924BB3AF0BCC> /Applications/git-annex.app/Contents/MacOS/bundle/V
+ 0x10f29b000 - 0x10f2a8ff7 +W (0) <91CF16BE-027F-3FE6-B1EE-6B8BFD51FC1B> /Applications/git-annex.app/Contents/MacOS/bundle/W
+ 0x10f2b4000 - 0x10f310fd7 +X (0) <84D934AF-A321-36C0-BBCF-CD3FDAEB0B95> /Applications/git-annex.app/Contents/MacOS/bundle/X
+ 0x7fff6b1e6000 - 0x7fff6b21a93f dyld (210.2.3) <36CAA36E-72BC-3E48-96D9-B96A2DF77730> /usr/lib/dyld
+ 0x7fff8652a000 - 0x7fff865d0ff7 com.apple.CoreServices.OSServices (557.6 - 557.6) <FFDDD2D8-690D-388F-A48F-4750A792D2CD> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
+ 0x7fff865d1000 - 0x7fff865e8fff libGL.dylib (8.9.2) <B8E5948D-BCF2-3727-B74E-D74B8EDC82D6> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
+ 0x7fff865e9000 - 0x7fff86610fff com.apple.framework.familycontrols (4.1 - 410) <50F5A52C-8FB6-300A-977D-5CFDE4D5796B> /System/Library/PrivateFrameworks/FamilyControls.framework/Versions/A/FamilyControls
+ 0x7fff86611000 - 0x7fff8663cfff libxslt.1.dylib (11.3) <441776B8-9130-3893-956F-39C85FFA644F> /usr/lib/libxslt.1.dylib
+ 0x7fff86649000 - 0x7fff86698ff7 libcorecrypto.dylib (106.2) <CE0C29A3-C420-339B-ADAA-52F4683233CC> /usr/lib/system/libcorecrypto.dylib
+ 0x7fff8669d000 - 0x7fff866a3fff com.apple.DiskArbitration (2.5.2 - 2.5.2) <C713A35A-360E-36CE-AC0A-25C86A3F50CA> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
+ 0x7fff866a4000 - 0x7fff86ac1fff FaceCoreLight (2.4.1) <DDAFFD7A-D312-3407-A010-5AEF3E17831B> /System/Library/PrivateFrameworks/FaceCoreLight.framework/Versions/A/FaceCoreLight
+ 0x7fff86ac7000 - 0x7fff86b93ff7 libsystem_c.dylib (825.26) <4C9EB006-FE1F-3F8F-8074-DFD94CF2CE7B> /usr/lib/system/libsystem_c.dylib
+ 0x7fff86d50000 - 0x7fff86da1ff7 com.apple.SystemConfiguration (1.12.2 - 1.12.2) <581BF463-C15A-363B-999A-E830222FA925> /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
+ 0x7fff86dee000 - 0x7fff86deefff com.apple.Accelerate.vecLib (3.8 - vecLib 3.8) <B5A18EE8-DF81-38DD-ACAF-7076B2A26225> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
+ 0x7fff86def000 - 0x7fff86df4fff com.apple.OpenDirectory (10.8 - 151.10) <CF44120B-9B01-32DD-852E-C9C0E1243FC0> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory
+ 0x7fff86df5000 - 0x7fff86df6fff libDiagnosticMessagesClient.dylib (8) <8548E0DC-0D2F-30B6-B045-FE8A038E76D8> /usr/lib/libDiagnosticMessagesClient.dylib
+ 0x7fff86e0a000 - 0x7fff87201fff libLAPACK.dylib (1073.4) <D632EC8B-2BA0-3853-800A-20DA00A1091C> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
+ 0x7fff87622000 - 0x7fff87650ff7 libsystem_m.dylib (3022.6) <B434BE5C-25AB-3EBD-BAA7-5304B34E3441> /usr/lib/system/libsystem_m.dylib
+ 0x7fff8766c000 - 0x7fff8769dff7 com.apple.DictionaryServices (1.2 - 184.4) <FB0540FF-5034-3591-A28D-6887FBC220F7> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices
+ 0x7fff8769e000 - 0x7fff8769efff libkeymgr.dylib (25) <CC9E3394-BE16-397F-926B-E579B60EE429> /usr/lib/system/libkeymgr.dylib
+ 0x7fff87732000 - 0x7fff87754ff7 libxpc.dylib (140.43) <70BC645B-6952-3264-930C-C835010CCEF9> /usr/lib/system/libxpc.dylib
+ 0x7fff87755000 - 0x7fff877d7ff7 com.apple.Heimdal (3.0 - 2.0) <C94B0C6C-1320-35A1-8143-FE252E7B2A08> /System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal
+ 0x7fff877d8000 - 0x7fff87859fff com.apple.Metadata (10.7.0 - 707.11) <2DD25313-420D-351A-90F1-300E95C970CA> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
+ 0x7fff87cbf000 - 0x7fff87d19fff com.apple.print.framework.PrintCore (8.3 - 387.2) <5BA0CBED-4D80-386A-9646-F835C9805B71> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
+ 0x7fff87e27000 - 0x7fff87e34ff7 com.apple.NetAuth (4.0 - 4.0) <F5BC7D7D-AF28-3C83-A674-DADA48FF7810> /System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth
+ 0x7fff87f54000 - 0x7fff87f68fff com.apple.speech.synthesis.framework (4.1.12 - 4.1.12) <94EDF2AB-809C-3D15-BED5-7AD45B2A7C16> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
+ 0x7fff87f77000 - 0x7fff87f7dff7 libunwind.dylib (35.1) <21703D36-2DAB-3D8B-8442-EAAB23C060D3> /usr/lib/system/libunwind.dylib
+ 0x7fff87fab000 - 0x7fff87fabfff com.apple.Accelerate (1.8 - Accelerate 1.8) <6AD48543-0864-3D40-80CE-01F184F24B45> /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate
+ 0x7fff88161000 - 0x7fff88162ff7 libSystem.B.dylib (169.3) <9089D72D-E714-31E1-80C8-698A8E8B05AD> /usr/lib/libSystem.B.dylib
+ 0x7fff88167000 - 0x7fff88205ff7 com.apple.ink.framework (10.8.2 - 150) <3D8D16A2-7E01-3EA1-B637-83A36D353308> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
+ 0x7fff88222000 - 0x7fff88223ff7 libsystem_sandbox.dylib (220.3) <B739DA63-B675-387A-AD84-412A651143C0> /usr/lib/system/libsystem_sandbox.dylib
+ 0x7fff88224000 - 0x7fff88228ff7 com.apple.TCC (1.0 - 1) <F2F3B753-FC73-3543-8BBE-859FDBB4D6A6> /System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC
+ 0x7fff88229000 - 0x7fff88230fff libcopyfile.dylib (89) <876573D0-E907-3566-A108-577EAD1B6182> /usr/lib/system/libcopyfile.dylib
+ 0x7fff88a6e000 - 0x7fff88a8dff7 libresolv.9.dylib (51) <0882DC2D-A892-31FF-AD8C-0BB518C48B23> /usr/lib/libresolv.9.dylib
+ 0x7fff88a8e000 - 0x7fff88aa1ff7 libbsm.0.dylib (32) <F497D3CE-40D9-3551-84B4-3D5E39600737> /usr/lib/libbsm.0.dylib
+ 0x7fff88bbd000 - 0x7fff88bbdfff com.apple.ApplicationServices (45 - 45) <A3ABF20B-ED3A-32B5-830E-B37831A45A80> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
+ 0x7fff88bce000 - 0x7fff88bf6fff libJPEG.dylib (850) <DC750E1E-BD07-339B-A4A6-D86BFE969F68> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
+ 0x7fff88bf7000 - 0x7fff88bf9fff libquarantine.dylib (52.1) <143B726E-DF47-37A8-90AA-F059CFD1A2E4> /usr/lib/system/libquarantine.dylib
+ 0x7fff88fe0000 - 0x7fff8933ffff com.apple.Foundation (6.8 - 945.18) <1D7E58E6-FA3A-3CE8-AC85-B9D06B8C0AA0> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
+ 0x7fff89340000 - 0x7fff89575ff7 com.apple.CoreData (106.1 - 407.7) <A676E1A4-2144-376B-92B8-B450DD1D78E5> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
+ 0x7fff89576000 - 0x7fff8957dfff libGFXShared.dylib (8.9.2) <398F8D57-EC82-3E13-AC8E-470BE19237D7> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib
+ 0x7fff895d4000 - 0x7fff8a201fff com.apple.AppKit (6.8 - 1187.39) <199962F0-B06B-3666-8FD5-5C90374BA16A> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
+ 0x7fff8a202000 - 0x7fff8a519ff7 com.apple.CoreServices.CarbonCore (1037.6 - 1037.6) <1E567A52-677F-3168-979F-5FBB0818D52B> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
+ 0x7fff8a5e0000 - 0x7fff8a5e7fff com.apple.NetFS (5.0 - 4.0) <82E24B9A-7742-3DA3-9E99-ED267D98C05E> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS
+ 0x7fff8a5e8000 - 0x7fff8a63fff7 com.apple.ScalableUserInterface (1.0 - 1) <F1D43DFB-1796-361B-AD4B-39F1EED3BE19> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/ScalableUserInterface.framework/Versions/A/ScalableUserInterface
+ 0x7fff8a71b000 - 0x7fff8a767ff7 libauto.dylib (185.4) <AD5A4CE7-CB53-313C-9FAE-673303CC2D35> /usr/lib/libauto.dylib
+ 0x7fff8a768000 - 0x7fff8a768fff libOpenScriptingUtil.dylib (148.3) <F8681222-0969-3B10-8BCE-C55A4B9C520C> /usr/lib/libOpenScriptingUtil.dylib
+ 0x7fff8a7e7000 - 0x7fff8a808ff7 libCRFSuite.dylib (33) <736ABE58-8DED-3289-A042-C25AF7AE5B23> /usr/lib/libCRFSuite.dylib
+ 0x7fff8a809000 - 0x7fff8a815fff com.apple.CrashReporterSupport (10.8.3 - 418) <DE6AFE16-D97E-399D-82ED-3522C773C36E> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport
+ 0x7fff8a816000 - 0x7fff8b1a64af com.apple.CoreGraphics (1.600.0 - 332) <5AB32E51-9154-3733-B83B-A9A748652847> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
+ 0x7fff8b1a7000 - 0x7fff8b1befff com.apple.CFOpenDirectory (10.8 - 151.10) <10F41DA4-AD54-3F52-B898-588D9A117171> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory
+ 0x7fff8b242000 - 0x7fff8b285ff7 com.apple.bom (12.0 - 192) <0BF1F2D2-3648-36B7-BE4B-551A0173209B> /System/Library/PrivateFrameworks/Bom.framework/Versions/A/Bom
+ 0x7fff8b286000 - 0x7fff8b2c3fef libGLImage.dylib (8.9.2) <C38649ED-E1C9-315E-9953-F33E8C6A3C89> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
+ 0x7fff8b2c4000 - 0x7fff8b303ff7 com.apple.QD (3.42.1 - 285.1) <77A20C25-EBB5-341C-A05C-5D458B97AD5C> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
+ 0x7fff8b304000 - 0x7fff8b39efff libvMisc.dylib (380.6) <714336EA-1C0E-3735-B31C-19DFDAAF6221> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib
+ 0x7fff8b3b8000 - 0x7fff8b566fff com.apple.QuartzCore (1.8 - 304.3) <F450F2DE-2F24-3557-98B6-310E05DAC17F> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
+ 0x7fff8ba39000 - 0x7fff8ba4cff7 com.apple.LangAnalysis (1.7.0 - 1.7.0) <2F2694E9-A7BC-33C7-B4CF-8EC907DF0FEB> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
+ 0x7fff8bd12000 - 0x7fff8bd1cfff com.apple.speech.recognition.framework (4.1.5 - 4.1.5) <D803919C-3102-3515-A178-61E9C86C46A1> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
+ 0x7fff8c0d6000 - 0x7fff8c0d7ff7 libdnsinfo.dylib (453.19) <14202FFB-C3CA-3FCC-94B0-14611BF8692D> /usr/lib/system/libdnsinfo.dylib
+ 0x7fff8c179000 - 0x7fff8c17efff libcompiler_rt.dylib (30) <08F8731D-5961-39F1-AD00-4590321D24A9> /usr/lib/system/libcompiler_rt.dylib
+ 0x7fff8c1b2000 - 0x7fff8c39cff7 com.apple.CoreFoundation (6.8 - 744.19) <0F7403CA-2CB8-3D0A-992B-679701DF27CA> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+ 0x7fff8c39d000 - 0x7fff8c3c4ff7 com.apple.PerformanceAnalysis (1.16 - 16) <E4888388-F41B-313E-9CBB-5807D077BDA9> /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis
+ 0x7fff8c3e2000 - 0x7fff8c3e5ff7 libdyld.dylib (210.2.3) <F59367C9-C110-382B-A695-9035A6DD387E> /usr/lib/system/libdyld.dylib
+ 0x7fff8c3e6000 - 0x7fff8c3e8fff libCVMSPluginSupport.dylib (8.9.2) <EF1192AC-3357-3A0B-BFAF-6594D7737892> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib
+ 0x7fff8c3e9000 - 0x7fff8c484fff com.apple.CoreSymbolication (3.0 - 117) <50716F74-41C2-3BB9-AC16-12C4D4C2DD1E> /System/Library/PrivateFrameworks/CoreSymbolication.framework/Versions/A/CoreSymbolication
+ 0x7fff8c75b000 - 0x7fff8c75bfff com.apple.CoreServices (57 - 57) <9DD44CB0-C644-35C3-8F57-0B41B3EC147D> /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
+ 0x7fff8cf1f000 - 0x7fff8d094ff7 com.apple.CFNetwork (596.4.3 - 596.4.3) <A57B3308-2F08-3EC3-B4AC-39A3D9F0B9F7> /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
+ 0x7fff8d0ae000 - 0x7fff8d0e4fff libsystem_info.dylib (406.17) <4FFCA242-7F04-365F-87A6-D4EFB89503C1> /usr/lib/system/libsystem_info.dylib
+ 0x7fff8d0e5000 - 0x7fff8d148ff7 com.apple.audio.CoreAudio (4.1.1 - 4.1.1) <9ACD3AED-6C04-3BBB-AB2A-FC253B16D093> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
+ 0x7fff8d156000 - 0x7fff8d16cfff com.apple.MultitouchSupport.framework (235.29 - 235.29) <617EC8F1-BCE7-3553-86DD-F857866E1257> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport
+ 0x7fff8d16d000 - 0x7fff8d171fff libGIF.dylib (850) <D4525F87-759C-338C-B283-BB8DE815D3D5> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
+ 0x7fff8d264000 - 0x7fff8d2aeff7 libGLU.dylib (8.9.2) <1B5511FF-1064-3004-A245-972CE5687D37> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
+ 0x7fff8d2b2000 - 0x7fff8d2dcff7 com.apple.CoreVideo (1.8 - 99.4) <E5082966-6D81-3973-A05A-38AA5B85F886> /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo
+ 0x7fff8d58d000 - 0x7fff8d591fff com.apple.IOSurface (86.0.4 - 86.0.4) <26F01CD4-B76B-37A3-989D-66E8140542B3> /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface
+ 0x7fff8d6de000 - 0x7fff8d78ffff com.apple.LaunchServices (539.9 - 539.9) <07FC6766-778E-3479-8F28-D2C9917E1DD1> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
+ 0x7fff8d7bf000 - 0x7fff8d80eff7 libFontRegistry.dylib (100) <2E03D7DA-9B8F-31BB-8FB5-3D3B6272127F> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib
+ 0x7fff8d80f000 - 0x7fff8d88fff7 com.apple.ApplicationServices.ATS (332 - 341.1) <39B53565-FA31-3F61-B090-C787C983142E> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
+ 0x7fff8d94e000 - 0x7fff8d95bfff com.apple.AppleFSCompression (49 - 1.0) <5508344A-2A7E-3122-9562-6F363910A80E> /System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression
+ 0x7fff8d95c000 - 0x7fff8d99fff7 com.apple.RemoteViewServices (2.0 - 80.6) <5CFA361D-4853-3ACC-9EFC-A2AC1F43BA4B> /System/Library/PrivateFrameworks/RemoteViewServices.framework/Versions/A/RemoteViewServices
+ 0x7fff8dac2000 - 0x7fff8dac8fff libmacho.dylib (829) <BF332AD9-E89F-387E-92A4-6E1AB74BD4D9> /usr/lib/system/libmacho.dylib
+ 0x7fff8dac9000 - 0x7fff8db03ff7 com.apple.GSS (3.0 - 2.0) <970CAE00-1437-3F4E-B677-0FDB3714C08C> /System/Library/Frameworks/GSS.framework/Versions/A/GSS
+ 0x7fff8db09000 - 0x7fff8db12ff7 com.apple.CommerceCore (1.0 - 26.1) <40A129A8-4E5D-3C7A-B299-8CB203C4C65D> /System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Frameworks/CommerceCore.framework/Versions/A/CommerceCore
+ 0x7fff8db13000 - 0x7fff8db15fff com.apple.TrustEvaluationAgent (2.0 - 23) <A97D348B-32BF-3E52-8DF2-59BFAD21E1A3> /System/Library/PrivateFrameworks/TrustEvaluationAgent.framework/Versions/A/TrustEvaluationAgent
+ 0x7fff8de6c000 - 0x7fff8de6eff7 libunc.dylib (25) <92805328-CD36-34FF-9436-571AB0485072> /usr/lib/system/libunc.dylib
+ 0x7fff8de6f000 - 0x7fff8de8eff7 com.apple.ChunkingLibrary (2.0 - 133.3) <8BEC9AFB-DCAA-37E8-A5AB-24422B234ECF> /System/Library/PrivateFrameworks/ChunkingLibrary.framework/Versions/A/ChunkingLibrary
+ 0x7fff8de8f000 - 0x7fff8deeefff com.apple.AE (645.6 - 645.6) <44F403C1-660A-3543-AB9C-3902E02F936F> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
+ 0x7fff8deef000 - 0x7fff8dfecfff libsqlite3.dylib (138.1) <ADE9CB98-D77D-300C-A32A-556B7440769F> /usr/lib/libsqlite3.dylib
+ 0x7fff8e06b000 - 0x7fff8e076ff7 com.apple.bsd.ServiceManagement (2.0 - 2.0) <C12962D5-85FB-349E-AA56-64F4F487F219> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
+ 0x7fff8e077000 - 0x7fff8e086fff com.apple.opengl (1.8.9 - 1.8.9) <6FD163A7-16CC-3D1F-B4B5-B0FDC4ADBF79> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
+ 0x7fff8e087000 - 0x7fff8e092fff com.apple.CommonAuth (3.0 - 2.0) <7A953C1F-8B18-3E46-9BEA-26D9B5B7745D> /System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth
+ 0x7fff8e093000 - 0x7fff8e093fff com.apple.Cocoa (6.7 - 19) <1F77945C-F37A-3171-B22E-F7AB0FCBB4D4> /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa
+ 0x7fff8e1f3000 - 0x7fff8e1f4fff libsystem_blocks.dylib (59) <D92DCBC3-541C-37BD-AADE-ACC75A0C59C8> /usr/lib/system/libsystem_blocks.dylib
+ 0x7fff8e23c000 - 0x7fff8e23cffd com.apple.audio.units.AudioUnit (1.9 - 1.9) <EC55FB59-2443-3F08-9142-7BCC93C76E4E> /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit
+ 0x7fff8e23d000 - 0x7fff8e30fff7 com.apple.CoreText (260.0 - 275.16) <5BFC1D67-6A6F-38BC-9D90-9C712684EDAC> /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
+ 0x7fff8e310000 - 0x7fff8e31eff7 libkxld.dylib (2050.24.15) <A619A9AC-09AF-3FF3-95BF-F07CC530EC31> /usr/lib/system/libkxld.dylib
+ 0x7fff8e31f000 - 0x7fff8e38dff7 com.apple.framework.IOKit (2.0.1 - 755.24.1) <04BFB138-8AF4-310A-8E8C-045D8A239654> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
+ 0x7fff8e39f000 - 0x7fff8e525fff libBLAS.dylib (1073.4) <C102C0F6-8CB6-3B49-BA6B-2EB61F0B2784> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
+ 0x7fff8e553000 - 0x7fff8e597fff libcups.2.dylib (327.6) <9C01D012-6F4C-3B69-B614-1B408B0ED4E3> /usr/lib/libcups.2.dylib
+ 0x7fff8e598000 - 0x7fff8e5a6fff libcommonCrypto.dylib (60027) <BAAFE0C9-BB86-3CA7-88C0-E3CBA98DA06F> /usr/lib/system/libcommonCrypto.dylib
+ 0x7fff8e6fa000 - 0x7fff8e70fff7 libdispatch.dylib (228.23) <D26996BF-FC57-39EB-8829-F63585561E09> /usr/lib/system/libdispatch.dylib
+ 0x7fff8e710000 - 0x7fff8e71eff7 libsystem_network.dylib (77.10) <0D99F24E-56FE-380F-B81B-4A4C630EE587> /usr/lib/system/libsystem_network.dylib
+ 0x7fff8e71f000 - 0x7fff8e741ff7 com.apple.Kerberos (2.0 - 1) <C49B8820-34ED-39D7-A407-A3E854153556> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
+ 0x7fff8e788000 - 0x7fff8e797ff7 libxar.1.dylib (105) <370ED355-E516-311E-BAFD-D80633A84BE1> /usr/lib/libxar.1.dylib
+ 0x7fff8f144000 - 0x7fff8f1d1ff7 com.apple.SearchKit (1.4.0 - 1.4.0) <C7F43889-F8BF-3CB9-AD66-11AEFCBCEDE7> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
+ 0x7fff8f24c000 - 0x7fff8f24ffff libRadiance.dylib (850) <62E3F7FB-03E3-3937-A857-AF57A75EAF09> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib
+ 0x7fff8f533000 - 0x7fff8f7d7ff7 com.apple.CoreImage (8.4.0 - 1.0.1) <CC6DD22B-FFC6-310B-BE13-2397A02C79EF> /System/Library/Frameworks/QuartzCore.framework/Versions/A/Frameworks/CoreImage.framework/Versions/A/CoreImage
+ 0x7fff8f7d8000 - 0x7fff8f840fff libvDSP.dylib (380.6) <CD4C5EEB-9E63-30C4-8103-7A5EAEA0BE60> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
+ 0x7fff8f8ab000 - 0x7fff8f8affff libpam.2.dylib (20) <C8F45864-5B58-3237-87E1-2C258A1D73B8> /usr/lib/libpam.2.dylib
+ 0x7fff8fabb000 - 0x7fff8fb28ff7 com.apple.datadetectorscore (4.1 - 269.3) <5775F0DB-87D6-310D-8B03-E2AD729EFB28> /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/DataDetectorsCore
+ 0x7fff8fc60000 - 0x7fff8fcbcff7 com.apple.Symbolication (1.3 - 93) <97F3B1D2-D81D-3F37-87B3-B9A686124CF5> /System/Library/PrivateFrameworks/Symbolication.framework/Versions/A/Symbolication
+ 0x7fff8fd91000 - 0x7fff8fe6bfff com.apple.backup.framework (1.4.3 - 1.4.3) <6B65C44C-7777-3331-AD9D-438D10AAC777> /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup
+ 0x7fff8fe6c000 - 0x7fff8fe79fff libbz2.1.0.dylib (29) <CE9785E8-B535-3504-B392-82F0064D9AF2> /usr/lib/libbz2.1.0.dylib
+ 0x7fff8fe89000 - 0x7fff8ffdbfff com.apple.audio.toolbox.AudioToolbox (1.9 - 1.9) <62770C0F-5600-3EF9-A893-8A234663FFF5> /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
+ 0x7fff90071000 - 0x7fff90173fff libJP2.dylib (850) <2E43216C-3A5A-3693-820C-38B360698FA0> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
+ 0x7fff90ab4000 - 0x7fff90b79ff7 com.apple.coreui (2.0 - 181.1) <83D2C92D-6842-3C9D-9289-39D5B4554C3A> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI
+ 0x7fff90e1a000 - 0x7fff90e1bfff liblangid.dylib (116) <864C409D-D56B-383E-9B44-A435A47F2346> /usr/lib/liblangid.dylib
+ 0x7fff90f20000 - 0x7fff90fddff7 com.apple.ColorSync (4.8.0 - 4.8.0) <6CE333AE-EDDB-3768-9598-9DB38041DC55> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
+ 0x7fff90fde000 - 0x7fff9105dff7 com.apple.securityfoundation (6.0 - 55115.4) <8676E0DF-295F-3690-BDAA-6C9C1D210B88> /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation
+ 0x7fff9105e000 - 0x7fff910b4fff com.apple.HIServices (1.20 - 417) <BCD36950-013F-35C2-918E-05A93A47BE8C> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
+ 0x7fff910b5000 - 0x7fff910d6fff com.apple.Ubiquity (1.2 - 243.15) <C9A7EE77-B637-3676-B667-C0843BBB0409> /System/Library/PrivateFrameworks/Ubiquity.framework/Versions/A/Ubiquity
+ 0x7fff910de000 - 0x7fff91133ff7 libTIFF.dylib (850) <EDAF0D99-70AF-3B3F-9EFA-9463C91D0E3C> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
+ 0x7fff9125c000 - 0x7fff9127cfff libPng.dylib (850) <203C43BF-FAD3-3CCB-81D5-F2770E36338B> /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
+ 0x7fff9127f000 - 0x7fff91398fff com.apple.ImageIO.framework (3.2.1 - 850) <C3FFCEEB-AA0C-314B-9E94-7005EE48A403> /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
+ 0x7fff9139f000 - 0x7fff913b6fff com.apple.GenerationalStorage (1.1 - 132.3) <FD4A84B3-13A8-3C60-A59E-25A361447A17> /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/GenerationalStorage
+ 0x7fff91582000 - 0x7fff91586fff libCoreVMClient.dylib (32.3) <AD8391D9-56DD-3A78-A294-6A30E6ECE1A2> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib
+ 0x7fff91587000 - 0x7fff915bdfff com.apple.DebugSymbols (98 - 98) <14E788B1-4EB2-3FD7-934B-849534DFC198> /System/Library/PrivateFrameworks/DebugSymbols.framework/Versions/A/DebugSymbols
+ 0x7fff915cd000 - 0x7fff915d5fff liblaunch.dylib (442.26.2) <2F71CAF8-6524-329E-AC56-C506658B4C0C> /usr/lib/system/liblaunch.dylib
+ 0x7fff915d6000 - 0x7fff915e1fff libsystem_notify.dylib (98.5) <C49275CC-835A-3207-AFBA-8C01374927B6> /usr/lib/system/libsystem_notify.dylib
+ 0x7fff91650000 - 0x7fff917ebfef com.apple.vImage (6.0 - 6.0) <FAE13169-295A-33A5-8E6B-7C2CC1407FA7> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage
+ 0x7fff917ec000 - 0x7fff917f4ff7 libsystem_dnssd.dylib (379.38.1) <BDCB8566-0189-34C0-9634-35ABD3EFE25B> /usr/lib/system/libsystem_dnssd.dylib
+ 0x7fff9182d000 - 0x7fff91938fff libFontParser.dylib (84.6) <96C42E49-79A6-3475-B5E4-6A782599A6DA> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib
+ 0x7fff919d8000 - 0x7fff919ddfff libcache.dylib (57) <65187C6E-3FBF-3EB8-A1AA-389445E2984D> /usr/lib/system/libcache.dylib
+ 0x7fff919de000 - 0x7fff919defff com.apple.vecLib (3.8 - vecLib 3.8) <794317C7-4E38-338A-A874-5E18001C8503> /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib
+ 0x7fff919df000 - 0x7fff91cb0ff7 com.apple.security (7.0 - 55179.13) <F428E306-C407-3B55-BA82-E58755E8A76F> /System/Library/Frameworks/Security.framework/Versions/A/Security
+ 0x7fff91d3f000 - 0x7fff9206ffff com.apple.HIToolbox (2.0 - 626.1) <656D08C2-9068-3532-ABDD-32EC5057CCB2> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
+ 0x7fff92084000 - 0x7fff920deff7 com.apple.opencl (2.2.19 - 2.2.19) <3C7DFB2C-B3F9-3447-A1FC-EAAA42181A6E> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL
+ 0x7fff9216c000 - 0x7fff9216dff7 libremovefile.dylib (23.2) <6763BC8E-18B8-3AD9-8FFA-B43713A7264F> /usr/lib/system/libremovefile.dylib
+ 0x7fff9312e000 - 0x7fff93149ff7 libsystem_kernel.dylib (2050.24.15) <A9F97289-7985-31D6-AF89-151830684461> /usr/lib/system/libsystem_kernel.dylib
+ 0x7fff9314d000 - 0x7fff9326dfff com.apple.desktopservices (1.7.4 - 1.7.4) <ED3DA8C0-160F-3CDC-B537-BF2E766AB7C1> /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
+
+External Modification Summary:
+ Calls made by other processes targeting this process:
+ task_for_pid: 1
+ thread_create: 0
+ thread_set_state: 0
+ Calls made by this process:
+ task_for_pid: 0
+ thread_create: 0
+ thread_set_state: 0
+ Calls made by all processes on this machine:
+ task_for_pid: 168404
+ thread_create: 1
+ thread_set_state: 0
+
+VM Region Summary:
+ReadOnly portion of Libraries: Total=109.3M resident=31.8M(29%) swapped_out_or_unallocated=77.5M(71%)
+Writable regions: Total=90.9M written=16.1M(18%) resident=17.5M(19%) swapped_out=0K(0%) unallocated=73.4M(81%)
+
+REGION TYPE VIRTUAL
+=========== =======
+MALLOC 62.5M
+MALLOC guard page 48K
+STACK GUARD 56.0M
+Stack 12.6M
+VM_ALLOCATE 12.0M
+__DATA 13.8M
+__IMAGE 528K
+__LINKEDIT 58.6M
+__TEXT 134.3M
+__UNICODE 544K
+shared memory 308K
+=========== =======
+TOTAL 351.2M
+
+Model: MacBookPro10,1, BootROM MBP101.00EE.B03, 4 processors, Intel Core i7, 2.8 GHz, 16 GB, SMC 2.3f35
+Graphics: Intel HD Graphics 4000, Intel HD Graphics 4000, Built-In, 512 MB
+Graphics: NVIDIA GeForce GT 650M, NVIDIA GeForce GT 650M, PCIe, 1024 MB
+Memory Module: BANK 0/DIMM0, 8 GB, DDR3, 1600 MHz, 0x80AD, 0x484D5434314753364D465238432D50422020
+Memory Module: BANK 1/DIMM0, 8 GB, DDR3, 1600 MHz, 0x80AD, 0x484D5434314753364D465238432D50422020
+AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0xEF), Broadcom BCM43xx 1.0 (5.106.98.100.17)
+Bluetooth: Version 4.1.4f2 12041, 2 service, 18 devices, 1 incoming serial ports
+Network Service: Wi-Fi, AirPort, en0
+Serial ATA Device: APPLE SSD SM768E, 751.28 GB
+USB Device: hub_device, 0x8087 (Intel Corporation), 0x0024, 0x1a100000 / 2
+USB Device: FaceTime HD Camera (Built-in), apple_vendor_id, 0x8510, 0x1a110000 / 3
+USB Device: USB Receiver, 0x046d (Logitech Inc.), 0xc52b, 0x14200000 / 1
+USB Device: hub_device, 0x8087 (Intel Corporation), 0x0024, 0x1d100000 / 2
+USB Device: hub_device, 0x0424 (SMSC), 0x2512, 0x1d180000 / 3
+USB Device: Apple Internal Keyboard / Trackpad, apple_vendor_id, 0x0262, 0x1d182000 / 5
+USB Device: BRCM20702 Hub, 0x0a5c (Broadcom Corp.), 0x4500, 0x1d181000 / 4
+USB Device: Bluetooth USB Host Controller, apple_vendor_id, 0x8286, 0x1d181300 / 6
+
+# End of transcript or log.
+"""]]
+
+> This got fixed in haskell gnutls 0.1.5. I have updated the Mtn Lion
+> autobuilder and it will be in tonight's build. [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_1_97abb8442329d19c9687002f43afac74._comment b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_1_97abb8442329d19c9687002f43afac74._comment
new file mode 100644
index 000000000..4dcc5412c
--- /dev/null
+++ b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_1_97abb8442329d19c9687002f43afac74._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-26T19:51:48Z"
+ content="""
+So this is a crash in the gnutls library used for XMPP. Someone else using OSX reported a similar crash to me by email, reproducible reliably by setting up xmpp with google. This is great debugging info:
+
+<pre>
+Thread 3 Crashed:
+0 libsystem_c.dylib 0x00007fff86ae0bf9 pthread_mutex_lock + 20
+1 H 0x000000010e9fd29f gnutls_system_mutex_lock + 12
+2 H 0x000000010ea7fa29 wrap_nettle_rnd_refresh + 20
+3 H 0x000000010e9fee89 gnutls_deinit + 42
+4 git-annex 0x000000010caf0a3a 0x10b5e6000 + 22063674
+</pre>
+
+Looks like `gnutls_deinit` was called and it crashed there, inside pthread code. So I think git-annex has already managed to connect to the XMPP server (to test it) and the cleanup is where it's crashing.
+
+This is the second time I have seen a gnutls-related crash using XMPP. The other one was tracked down by John Millikin to a resource allocation bug in haskell-gnutls and fixed.
+
+I have written a test case that reproduces the problem -- just forking a dozen threads that each try to connect to the google xmpp server and then close the connection. After a dozen or so succeed, one will reliably cause a segfault. Forwarded this test case to John.
+"""]]
diff --git a/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_2_3405f3cd699860ee239cf23ade19e92c._comment b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_2_3405f3cd699860ee239cf23ade19e92c._comment
new file mode 100644
index 000000000..18b2b7a52
--- /dev/null
+++ b/doc/bugs/git-annex_quit_unexpectedly___40__macosx__41__/comment_2_3405f3cd699860ee239cf23ade19e92c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.7"
+ subject="comment 2"
+ date="2013-08-29T18:15:08Z"
+ content="""
+I now have a test case that shows that this can happen reliably on OSX if you enter the wrong XMPP password repeatedly. It might also happen if you just enter the wrong password once, with a server like google's, since the assistant will try falling back to different servers. John is aware of this haskell-gnutls problem.
+
+John also found, and we hope fixed (but it's hard to tell) a bug in haskell-gnutls that caused a crash maybe 1 time in 10 under some conditions on OSX, when the right password was entered.
+"""]]
diff --git a/doc/bugs/git-annex_sync_may_fail_when_the_directory_I__39__m_in_disepeared.mdwn b/doc/bugs/git-annex_sync_may_fail_when_the_directory_I__39__m_in_disepeared.mdwn
new file mode 100644
index 000000000..7a2690be2
--- /dev/null
+++ b/doc/bugs/git-annex_sync_may_fail_when_the_directory_I__39__m_in_disepeared.mdwn
@@ -0,0 +1,15 @@
+### Please describe the problem.
+While running git annex sync, it may failed if one did run it on some deep directory, and the sync remove this direcory.
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 4.20130815
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+
+on Debian Gnu Linux sid
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/git_annex_add_error_with_Andrew_File_System.mdwn b/doc/bugs/git_annex_add_error_with_Andrew_File_System.mdwn
new file mode 100644
index 000000000..bdddd96e2
--- /dev/null
+++ b/doc/bugs/git_annex_add_error_with_Andrew_File_System.mdwn
@@ -0,0 +1,28 @@
+### Please describe the problem.
+I have a git annex clone on Andrew File System. I obtain an error when I try
+to add a file to the annex:
+
+git-annex: test: createLink: unsupported operation (Invalid cross-device link)
+
+### What steps will reproduce the problem?
+Create a test file with touch and add it with git annex add.
+
+### What version of git-annex are you using? On what operating system?
+git-annex 4.20130723 on Debian sid.
+
+### Please provide any additional information below.
+
+[[!format sh """
+gio@crack:~/nobackup/archive$ touch test
+gio@crack:~/nobackup/archive$ git annex add test
+add test
+git-annex: test: createLink: unsupported operation (Invalid cross-device link)
+failed
+git-annex: add: 1 failed
+gio@crack:~/nobackup/archive$ logout
+"""]]
+
+It seems to me that AFS doesn't support hard links between different
+directories.
+
+> [[done]] per comments --[[Joey]]
diff --git a/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_1_bc783e551fc0e8da87bc95bff5b8f73a._comment b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_1_bc783e551fc0e8da87bc95bff5b8f73a._comment
new file mode 100644
index 000000000..7a0d15842
--- /dev/null
+++ b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_1_bc783e551fc0e8da87bc95bff5b8f73a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~giomasce"
+ nickname="giomasce"
+ subject="Reference"
+ date="2013-08-12T11:39:44Z"
+ content="""
+https://lists.openafs.org/pipermail/openafs-info/2007-December/028158.html
+"""]]
diff --git a/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_2_faefcf69bd61c47566131cb31b78cc19._comment b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_2_faefcf69bd61c47566131cb31b78cc19._comment
new file mode 100644
index 000000000..a2301499c
--- /dev/null
+++ b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_2_faefcf69bd61c47566131cb31b78cc19._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-24T19:48:46Z"
+ content="""
+I'm confused by this bug report, because it seems to me I already fixed this same problem in commit a64106dcef5c5aad825662ef115cb2a1cc6985a8. There the problem was that encfs in paranoia mode doesn't support hard links. So I made it detect when createLink fails, and fall back to a code path that doesn't need hard links.
+
+Can you re-check the version you have, and perhaps try with a current daily build?
+"""]]
diff --git a/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_3_d5014c8b78437b9fddbb1e83d3679081._comment b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_3_d5014c8b78437b9fddbb1e83d3679081._comment
new file mode 100644
index 000000000..3d30cea41
--- /dev/null
+++ b/doc/bugs/git_annex_add_error_with_Andrew_File_System/comment_3_d5014c8b78437b9fddbb1e83d3679081._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~giomasce"
+ nickname="giomasce"
+ subject="comment 3"
+ date="2013-09-07T15:35:48Z"
+ content="""
+Apparently I wrote a wrong version number. The version actually running on the system I tested is much older. Probably I wrote the one of my own laptop instead.
+
+The bug can be closed, sorry for the noise.
+"""]]
diff --git a/doc/bugs/git_annex_copy_trying_to_connect_to_remotes_uninvolved.mdwn b/doc/bugs/git_annex_copy_trying_to_connect_to_remotes_uninvolved.mdwn
index a8131df4d..f41a80616 100644
--- a/doc/bugs/git_annex_copy_trying_to_connect_to_remotes_uninvolved.mdwn
+++ b/doc/bugs/git_annex_copy_trying_to_connect_to_remotes_uninvolved.mdwn
@@ -23,3 +23,5 @@ I'm running git-annex 4.20130627 as shipped with debian unstable.
Jason
P.S. 192.168.1.5 is set as the HostName for one of my other remotes in my ~/.ssh/config, so this isn't _totally_ out of the blue.
+
+> [[done]]; see comment's explanation. --[[Joey]]
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
new file mode 100644
index 000000000..7e26f63df
--- /dev/null
+++ 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
@@ -0,0 +1,42 @@
+### Please describe the problem.
+
+Creating two repos with the same name causes git annex dead to randomly choose one. This is reasonable except that it can choose to mark an already dead remote dead (as long as it shares the name), causing it to actually do nothing.
+
+I think preferring to mark live repos dead and printing a warning when multiple repos could have been chosen (or if the repo is already marked dead) would be a good solution.
+
+### What steps will reproduce the problem?
+
+[[!format sh """
+# Create a new repo /somecopy
+git clone /central /somecopy
+cd /somecopy
+git annex init somecopy
+git annex sync
+cd /
+
+# Now, git annex status shows somecopy as an existing repo.
+
+# Destroy the new repo
+rm -rf /somecopy
+cd /central
+git annex dead somecopy
+
+# git annex status correctly hides somecopy, and it is properly dead.
+
+# create it again with the same name, but new UUID
+git clone /central /somecopy
+cd /somecopy
+git annex init somecopy
+git annex sync
+cd /
+
+# Destroy the second repo
+rm -rf /somecopy
+cd /central
+"""]]
+
+Now, git annex dead somecopy will randomly (based on the order of the UUIDs?) choose to mark dead the already dead old repo or the new repo, in both cases showing success to the user.
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex 4.20131024 on linux. Also occurs on OSX.
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__/comment_1_7ee08a60e4b2516c010d3c2163049681._comment 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__/comment_1_7ee08a60e4b2516c010d3c2163049681._comment
new file mode 100644
index 000000000..3875affb7
--- /dev/null
+++ 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__/comment_1_7ee08a60e4b2516c010d3c2163049681._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-29T21:10:53Z"
+ content="""
+I don't think it's a good idea to give multiple repos the same description.
+
+You can use the uuid to refer to a repo unambiguously in this situation.
+
+I think it would add unncessary complication to make git-annex guess which repository you mean based on context
+(ie, choosing repositories that are not already dead). This would make commands that are currently idempotent not be.
+
+Perhaps git-annex should abort when multiple repositories match the given description? (Relevant code is Remote.nameToUUID's bydescription)
+"""]]
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__/comment_2_c29525bfda08717f68aaac83014e6b08._comment 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__/comment_2_c29525bfda08717f68aaac83014e6b08._comment
new file mode 100644
index 000000000..17191be04
--- /dev/null
+++ 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__/comment_2_c29525bfda08717f68aaac83014e6b08._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmGxww5ON3nilm7moGQCWJPnMEdRwNvb7U"
+ nickname="Chris"
+ subject="comment 2"
+ date="2013-10-29T22:01:04Z"
+ content="""
+I didn't think about idempotency. Erroring out seems like the best option now.
+"""]]
diff --git a/doc/bugs/git_annex_describe_can_break_uuid.log.mdwn b/doc/bugs/git_annex_describe_can_break_uuid.log.mdwn
new file mode 100644
index 000000000..16e6981f5
--- /dev/null
+++ b/doc/bugs/git_annex_describe_can_break_uuid.log.mdwn
@@ -0,0 +1,46 @@
+### Please describe the problem.
+
+`uuid.log` can end up in a state where `git annex describe` (and probably other things) stops working.
+
+### What steps will reproduce the problem?
+
+Run `git annex describe` against a remote that is not a an initialized git-annex repo.
+
+### What version of git-annex are you using? On what operating system?
+
+debian-packaged git-annex 4.20131106 on Linux Mint 13/Maya (Ubuntu Precise/12.04)
+
+### Please provide any additional information below.
+
+I will follow comments, but can also be found at [[https://microca.st/clacke]].
+
+Full transcript to reproduce:
+
+[[!format sh """
+$ git init a
+Initialized empty Git repository in /tmp/annex/a/.git/
+$ git init b
+Initialized empty Git repository in /tmp/annex/b/.git/
+$ cd a/
+$ git annex init
+init ok
+(Recording state in git...)
+$ git remote add -f b ../b
+Updating b
+$ git annex describe b b # this should not be ok
+describe b ok
+(Recording state in git...)
+$ git annex describe b b
+describe b git-annex: Prelude.last: empty list
+$ git cat-file blob git-annex:uuid.log
+ b timestamp=1383987654.900868s
+...
+
+# End of transcript.
+"""]]
+
+> Fixed the bug and made git breakage not crash git-annex. [[done]]
+> --[[Joey]]
+
+> > Update: Also made it automatically clean up the cruft this put in the
+> > log. --[[Joey]]
diff --git a/doc/bugs/git_annex_describe_can_break_uuid.log/comment_2_9ead36f13cbde6c822b231441de636ae._comment b/doc/bugs/git_annex_describe_can_break_uuid.log/comment_2_9ead36f13cbde6c822b231441de636ae._comment
new file mode 100644
index 000000000..a5616234e
--- /dev/null
+++ b/doc/bugs/git_annex_describe_can_break_uuid.log/comment_2_9ead36f13cbde6c822b231441de636ae._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 2"
+ date="2013-11-11T05:32:14Z"
+ content="""
+Great, thanks!
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_10_141819a6b67de2602673698f6f148106._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_10_141819a6b67de2602673698f6f148106._comment
new file mode 100644
index 000000000..db4d3e269
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_10_141819a6b67de2602673698f6f148106._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="calmyournerves"
+ ip="85.3.250.239"
+ subject="comment 10"
+ date="2013-10-24T20:47:19Z"
+ content="""
+I was able to successfully build git-annex on Mac OS X 10.9.
+
+See https://gist.github.com/calmyournerves/7144127 for instructions.
+I tried to document every step I made, but I'm not sure if I forgot to write down anything.
+
+Let me know if it works for you.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_11_8be96359fd2bd33ed2961e499dc2685e._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_11_8be96359fd2bd33ed2961e499dc2685e._comment
new file mode 100644
index 000000000..d166e8c67
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_11_8be96359fd2bd33ed2961e499dc2685e._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="warp"
+ ip="2001:4b98:dc0:45:216:3eff:fe83:3d9"
+ subject="comment 11"
+ date="2013-10-25T07:29:04Z"
+ content="""
+I was able to build git-annex on the work laptop with these steps:
+
+1. Make sure xcode is up-to-date.
+2. Download and install \"Command Line Tools (OS X Mavericks) for Xcode - Late October 2013\" from https://developer.apple.com/downloads/ after logging in as a developer.
+3. Follow the \"brew\" instructions at http://git-annex.branchable.com/install/OSX/
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_12_26950a37e86d4dd83dd59fb2564d0a2e._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_12_26950a37e86d4dd83dd59fb2564d0a2e._comment
new file mode 100644
index 000000000..b05d26c0b
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_12_26950a37e86d4dd83dd59fb2564d0a2e._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="imagejan"
+ ip="134.99.222.172"
+ subject="comment 12"
+ date="2013-10-25T13:37:13Z"
+ content="""
+I was able to build the git-annex.app OSX app using @calmyournerves instructions (see comment 10), but only after adding the 'async' dependency to the git-annex.cabal file.
+
+Command line works great now, but I wasn't able to run the git-annex-assistant :(
+
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_13_cbf8150dbe0da64bde7f6af8e041eda8._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_13_cbf8150dbe0da64bde7f6af8e041eda8._comment
new file mode 100644
index 000000000..94d962cd8
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_13_cbf8150dbe0da64bde7f6af8e041eda8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkQafKy7hNSEolLs6TvbgUnkklTctUY9LI"
+ nickname="Zellyn"
+ subject="Mac hardware"
+ date="2013-10-25T17:30:38Z"
+ content="""
+If someone had time to set up a campaign to buy you a Mac Mini, I'd chip in $20 :-)
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_14_0c203f90d911cf6869894dae89575a49._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_14_0c203f90d911cf6869894dae89575a49._comment
new file mode 100644
index 000000000..591123175
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_14_0c203f90d911cf6869894dae89575a49._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="calmyournerves"
+ ip="85.3.250.239"
+ subject="comment 14"
+ date="2013-10-25T18:43:01Z"
+ content="""
+@imagejan:
+What errors did you get before adding async to the cabal file?
+What's the problem with the assistant? Running git-annex webapp as well as simply opening git-annex.app both worked for me.
+
+@Zellyn:
+That's certainly a good idea and I would support it. But running multiple versions of OS X is tricky, Parallels allows this iirc (VM's).
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_15_68cbb7268bdad73357da2d11e05d73c4._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_15_68cbb7268bdad73357da2d11e05d73c4._comment
new file mode 100644
index 000000000..07e76fcb8
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_15_68cbb7268bdad73357da2d11e05d73c4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Remy"
+ ip="83.87.21.84"
+ subject="comment 15"
+ date="2013-10-25T18:51:32Z"
+ content="""
+I now got both the CLI and web app working but I had to switch to gcc-4.7 to work around a compiler preprocessing error and back to the default gcc to get fsevents to compile.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_16_816d552f871a1b06306f04d575adb2e5._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_16_816d552f871a1b06306f04d575adb2e5._comment
new file mode 100644
index 000000000..96f379dcf
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_16_816d552f871a1b06306f04d575adb2e5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkQafKy7hNSEolLs6TvbgUnkklTctUY9LI"
+ nickname="Zellyn"
+ subject="Earmarked donations?"
+ date="2013-10-25T21:51:19Z"
+ content="""
+Joeyh, is it possible to earmark donations? We could set up a wiki page to track progress, and try to buy you a Mac Mini...
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_17_7905b097a9c582452fb04cdc88ed4285._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_17_7905b097a9c582452fb04cdc88ed4285._comment
new file mode 100644
index 000000000..c67cc7add
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_17_7905b097a9c582452fb04cdc88ed4285._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 17"
+ date="2013-10-26T16:58:27Z"
+ content="""
+I'm glad that it's been gotten to build.
+
+Now all we need is for someone like @calmyournerves or @warp or @remy to put \"git pull; make osxapp\" in a cron job. I can provide a rsync account for publishing the DMG file, and help with setting up [gitbuilder](https://github.com/apenwarr/gitbuilder) which is one good way to automate it.
+
+Or, if someone else with a Mavericks desktop machine wants to install ssh and make me an account, I'm sure I can follow the instructions and set up an autobuilder on it.
+
+To be clear, I don't have time or interest in maintaining hardware to run the builds, even if I had the hardware. It's much better to let people who are passionate about it do it.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_18_bd5ac9bb2eaab66af6aa13b39172b49d._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_18_bd5ac9bb2eaab66af6aa13b39172b49d._comment
new file mode 100644
index 000000000..903a41364
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_18_bd5ac9bb2eaab66af6aa13b39172b49d._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://jspk.clavid.com/"
+ nickname="flabbergast"
+ subject="comment 18"
+ date="2013-10-27T19:29:01Z"
+ content="""
+I've also just upgraded and had to compile git-annex (following @calmyournerves' instructions). I've made a dmg, so if anyone out there doesn't feel like compiling, you can get 4.20131027-g9230b07 for Mavericks temporarily [here (7z for saving bandwidth)](https://freeshell.de/~teatime/git-annex-4.20131027-g9230b07.dmg.7z).
+(I've used my laptop, and I don't want to set it up for automatic building; I'll see if I can set up my work mac for that.)
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_19_9881db7bb6fef4e47c54cdc23e995f17._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_19_9881db7bb6fef4e47c54cdc23e995f17._comment
new file mode 100644
index 000000000..96356e047
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_19_9881db7bb6fef4e47c54cdc23e995f17._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnt7phVzBQ0xO5rCO6sfmEmxQItmFMyqls"
+ nickname="Kevin"
+ subject="comment 19"
+ date="2013-11-02T00:58:31Z"
+ content="""
+I tried @flabbergast's dmg. It seems to work fine (including the web app) on my Air, but the web app fails on my iMac with
+
+ $ git annex webapp
+ Launching web browser on file:///Users/kw/Desktop/annex/.git/annex/webapp.html
+ error: git-annex died of signal 4
+ $
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_20_41e2ea458669f59f96b5860825745910._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_20_41e2ea458669f59f96b5860825745910._comment
new file mode 100644
index 000000000..fca9ba58e
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_20_41e2ea458669f59f96b5860825745910._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnt7phVzBQ0xO5rCO6sfmEmxQItmFMyqls"
+ nickname="Kevin"
+ subject="comment 20"
+ date="2013-11-02T01:02:18Z"
+ content="""
+Also, to avoid hurt feelings etc., it might be best to make it clear on your home page and kickstarter that you do not intend to support OS X yourself.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_21_515039e321e0595f95430d8082bd54a5._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_21_515039e321e0595f95430d8082bd54a5._comment
new file mode 100644
index 000000000..a0a175d30
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_21_515039e321e0595f95430d8082bd54a5._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 21"
+ date="2013-11-08T19:22:17Z"
+ content="""
+Now that I can try running the 10.8 dmg on 10.9 myself, I get this failure:
+
+<pre>
+oberon:~ joeyh$ /Volumes/git-annex/git-annex.app/Contents/MacOS/git-annex
+dyld: Symbol not found: _objc_debug_taggedpointer_mask
+ Referenced from: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+ Expected in: /Volumes/git-annex/git-annex.app/Contents/MacOS/bundle/I
+ in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+</pre>
+
+This makes me think that that adding back the OSX frameworks might possibly yield a dmg that can work on both versions. Although that's probably more likely to work if it's built on 10.8 and used on 10.9 than the other way around. Might be worth a try to revert commit 900351ab8585c171486cef853eff4a95ec151e6f and commit 9b663c7f8cf82cee523b75be1a8786fa7d34b428 to try that.
+
+Oh well, I should have a native 10.9 dmg autobuild set up before too long. 10.8 autobuilder has built its last image unfortunately, due to being upgraded to 10.9.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_6_94144c0cbdbccc72c13e12daf7657a29._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_6_94144c0cbdbccc72c13e12daf7657a29._comment
new file mode 100644
index 000000000..fbb519bdd
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_6_94144c0cbdbccc72c13e12daf7657a29._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlYsjf5dcZnzs0b9EPxnjVddx1rnrpZASs"
+ nickname="Duarte"
+ subject="Any news?"
+ date="2013-08-31T15:48:39Z"
+ content="""
+Has anyone made any progress on this? Just wondering...
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_7_9eb064ffdc3fdb70e85572185e151a3f._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_7_9eb064ffdc3fdb70e85572185e151a3f._comment
new file mode 100644
index 000000000..db8e707cd
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_7_9eb064ffdc3fdb70e85572185e151a3f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmBcKrChzs1mdF5pxnenPuMOaJBKfbeRVY"
+ nickname="Raffael"
+ subject="bump"
+ date="2013-10-24T07:03:56Z"
+ content="""
+As Mavericks is now the current version of Mac OS X, it would be cool to have a working DMG for it. Any news here?
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_8_cde756e8a9b18fe2ca9cda25967bc7fb._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_8_cde756e8a9b18fe2ca9cda25967bc7fb._comment
new file mode 100644
index 000000000..708f21a79
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_8_cde756e8a9b18fe2ca9cda25967bc7fb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="67.223.1.203"
+ subject="comment 8"
+ date="2013-10-24T17:14:06Z"
+ content="""
+As I don't own any mac hardware, and don't plan to buy any, and I don't know of a way to just spin up a OSX VM in the cloud, I'm reliant on git-annex users for running builds for the various versions of OS X.
+
+I think there's a chance that one of the two people currently doing builds for older versions will upgrade their system. Although of course then we lose builds for that older version. Alternatively, I'm waiting for someone to either volenteer to set up a builder for 10.9, or give me ssh access to a machine were I can do it.
+"""]]
diff --git a/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_9_1fd6a4374a334bc03914c3e0df95ef95._comment b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_9_1fd6a4374a334bc03914c3e0df95ef95._comment
new file mode 100644
index 000000000..d70d0a872
--- /dev/null
+++ b/doc/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/comment_9_1fd6a4374a334bc03914c3e0df95ef95._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="67.223.1.203"
+ subject="comment 9"
+ date="2013-10-24T17:27:04Z"
+ content="""
+Anyone trying to compile git-annex on OSX 10.9 will need to be aware of and work around this problem:
+<http://justtesting.org/post/64947952690/the-glasgow-haskell-compiler-ghc-on-os-x-10-9>
+<http://www.haskell.org/pipermail/haskell-cafe/2013-September/110320.html>
+"""]]
diff --git a/doc/bugs/git_annex_import_destroys_a_fellow_git_annex_repository.mdwn b/doc/bugs/git_annex_import_destroys_a_fellow_git_annex_repository.mdwn
new file mode 100644
index 000000000..c8307ca6b
--- /dev/null
+++ b/doc/bugs/git_annex_import_destroys_a_fellow_git_annex_repository.mdwn
@@ -0,0 +1,130 @@
+### Please describe the problem.
+
+`git annex import` not only [[does not work with git annex repositories|bugs/`git annex import` does not work on other git annex repositories]], it even destroys the meta-data in that repository, because it moves the `.git/*` metadata out of the remote repository.
+
+### What steps will reproduce the problem?
+
+[[!format txt """
+git init foo
+cd foo
+git annex init
+dd if=/dev/urandom of=foo bs=1M count=1
+git annex add foo
+git commit -m'files'
+cd ../
+git init bar
+cd bar
+git annex init
+mkdir foo
+cd foo
+git annex import ../../foo
+cd ../../foo
+git status
+"""]]
+
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format txt """
+anarcat@angela:foo$ git annex version
+git-annex version: 4.20130921-g434dc22
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi
+"""]]
+
+### 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
+anarcat@angela:~$ cd /tmp
+anarcat@angela:/tmp$ mkdir test
+anarcat@angela:/tmp$ cd test
+anarcat@angela:test$ ls
+anarcat@angela:test$ git init foo
+Initialized empty Git repository in /tmp/test/foo/.git/
+anarcat@angela:test$ cd foo
+anarcat@angela:foo$ git annex init
+init ok
+(Recording state in git...)
+anarcat@angela:foo$ dd if=/dev/urandom of=foo bs=1M count=1
+1+0 enregistrements lus
+1+0 enregistrements écrits
+1048576 octets (1,0 MB) copiés, 0,410384 s, 2,6 MB/s
+anarcat@angela:foo$ git annex add foo
+add foo (checksum...) ok
+(Recording state in git...)
+anarcat@angela:foo$ git commit -m'files'
+[master (root-commit) 83daa0b] files
+ 1 file changed, 1 insertion(+)
+ create mode 120000 foo
+anarcat@angela:foo$ cd ../
+anarcat@angela:test$ git init bar
+Initialized empty Git repository in /tmp/test/bar/.git/
+anarcat@angela:test$ cd bar
+anarcat@angela:bar$ git annex init
+init ok
+(Recording state in git...)
+anarcat@angela:bar$ mkdir foo
+anarcat@angela:bar$ cd foo
+anarcat@angela:foo$ git annex import ../../foo
+import .git/COMMIT_EDITMSG (checksum...) ok
+import .git/description (checksum...) ok
+import .git/config (checksum...) ok
+import .git/index (checksum...) ok
+import .git/HEAD (checksum...) ok
+import .git/annex/journal.lck (checksum...) ok
+import .git/annex/index.lck (checksum...) ok
+import .git/annex/sentinal (checksum...) ok
+import .git/annex/sentinal.cache (checksum...) ok
+import .git/annex/index (checksum...) ok
+import .git/annex/objects/w2/Kz/SHA256E-s1048576--f957108785c8dc30cf792948b89d61af257c40e5ef0e1d20ff6cf6aadaf6f66b/SHA256E-s1048576--f957108785c8dc30cf792948b89d61af257c40e5ef0e1d20ff6cf6aadaf6f66b
+git-annex: ../../foo/.git/annex/objects/w2/Kz/SHA256E-s1048576--f957108785c8dc30cf792948b89d61af257c40e5ef0e1d20ff6cf6aadaf6f66b/SHA256E-s1048576--f957108785c8dc30cf792948b89d61af257c40e5ef0e1d20ff6cf6aadaf6f66b: rename: permission denied (Permission denied)
+failed
+import .git/objects/0e/6881452189b7fc34809f101f075da7cca9d9d8 (checksum...) ok
+import .git/objects/03/c0163611cd061af17b2dd58a93c95ffbb05040 (checksum...) ok
+import .git/objects/39/10912eab082d015bface04ed3a8ed658b94893 (checksum...) ok
+import .git/objects/21/05f6aaf523510f25516b04a0c07d5900df2b0b (checksum...) ok
+import .git/objects/83/daa0b1d8290191f53d1d3b5e39e03653a89ce2 (checksum...) ok
+import .git/objects/83/8fa78626a6cdc4399186172df9109d321ca0bf (checksum...) ok
+import .git/objects/dc/1e1b7b811079e1c5826d44958b736fc3a3a458 (checksum...) ok
+import .git/objects/7b/4d3d6a3ee2286b2da15c1aca39353d63c16fa2 (checksum...) ok
+import .git/objects/86/2b2a09ebc7a1eb298dccc57be75bad897a7c10 (checksum...) ok
+import .git/objects/e1/61ad2ad1843e39937caaf6add6f690fd361126 (checksum...) ok
+import .git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 (checksum...) ok
+import .git/objects/9b/47feee99b5f24e0dc96cf4a20fcb88c0ec007d (checksum...) ok
+import .git/objects/b0/8c838cfb09bafae40a05312092c37360c880b0 (checksum...) ok
+import .git/refs/heads/master (checksum...) ok
+import .git/refs/heads/git-annex (checksum...) ok
+import .git/logs/HEAD (checksum...) ok
+import .git/logs/refs/heads/master (checksum...) ok
+import .git/logs/refs/heads/git-annex (checksum...) ok
+import .git/info/exclude (checksum...) ok
+import .git/hooks/pre-applypatch.sample (checksum...) ok
+import .git/hooks/applypatch-msg.sample (checksum...) ok
+import .git/hooks/pre-rebase.sample (checksum...) ok
+import .git/hooks/update.sample (checksum...) ok
+import .git/hooks/commit-msg.sample (checksum...) ok
+import .git/hooks/pre-commit (checksum...) ok
+import .git/hooks/prepare-commit-msg.sample (checksum...) ok
+import .git/hooks/post-update.sample (checksum...) ok
+import .git/hooks/pre-commit.sample (checksum...) ok
+(Recording state in git...)
+error: Invalid path 'foo/.git/COMMIT_EDITMSG'
+error: unable to add foo/.git/COMMIT_EDITMSG to index
+fatal: adding files failed
+
+git-annex: user error (xargs ["-0","git","--git-dir=/tmp/test/bar/.git","--work-tree=/tmp/test/bar","add","--"] exited 123)
+failed
+git-annex: import: 2 failed
+anarcat@angela:foo$ cd ../../foo
+anarcat@angela:foo$ git status
+fatal: Not a git repository (or any of the parent directories): .git
+anarcat@angela:foo$
+# End of transcript or log.
+"""]]
+
+Thanks! --[[anarcat]]
+
+> Would have thought this was obviously something you shouldn't do
+> (sorta like running git-annex import on your home directory),
+> but ok, it can skip .git directories. [[done]] --[[Joey]]
diff --git a/doc/bugs/git_annex_importfeed_fails.mdwn b/doc/bugs/git_annex_importfeed_fails.mdwn
new file mode 100644
index 000000000..244ed769c
--- /dev/null
+++ b/doc/bugs/git_annex_importfeed_fails.mdwn
@@ -0,0 +1,64 @@
+### Please describe the problem.
+
+git annex importfeed fails
+
+### What steps will reproduce the problem?
+
+git annex importfeed http://www.tatw.co.uk/podcast.xml
+
+### On what operating system?
+
+Ubuntu 12.04, the prebuilt linux tarball
+
+[[!format sh """
+$ git annex version
+git-annex version: 4.20130922-g7dc188a
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP Feeds Quvi
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+
+### 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 importfeed http://www.tatw.co.uk/podcast.xml
+(checking known urls...)
+(Recording state in git...)
+importfeed http://www.tatw.co.uk/podcast.xml
+--2013-09-27 12:16:09-- http://www.tatw.co.uk/podcast.xml
+Résolution de www.tatw.co.uk (www.tatw.co.uk)... 88.190.26.130
+Connexion vers www.tatw.co.uk (www.tatw.co.uk)|88.190.26.130|:80... connecté.
+requête HTTP transmise, en attente de la réponse... 200 OK
+Longueur: 41267 (40K) [application/xml]
+Sauvegarde en : «/tmp/user/2166/feed10670»
+
+100%[==========================================================================>] 41 267 81,6K/s ds 0,5s
+
+2013-09-27 12:16:10 (81,6 KB/s) - «/tmp/user/2166/feed10670» sauvegardé [41267/41267]
+
+addurl Above___Beyond__Group_Therapy/_001_Group_Therapy_Radio_with_Above___Beyond (downloading ...)
+failed
+addurl Above___Beyond__Group_Therapy/_002_Group_Therapy_Radio_with_Above___Beyond (downloading ...)
+failed
+addurl Above___Beyond__Group_Therapy/_003_Group_Therapy_Radio_with_Above___Beyond (downloading ...)
+failed
+addurl Above___Beyond__Group_Therapy/_004_Group_Therapy_Radio_with_Above___Beyond (downloading ...)
+failed
+
+etc
+
+
+# End of transcript or log.
+"""]]
+
+> This is a bug in the feed library: <https://github.com/sof/feed/issues/7>
+> And already fixed upstream this morning, so if you need the fix
+> immediately, build with cabal. Otherwise fix will percolate out to
+> builds eventually.
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn b/doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn
new file mode 100644
index 000000000..34096d894
--- /dev/null
+++ b/doc/bugs/git_annex_indirect_can_fail_catastrophically.mdwn
@@ -0,0 +1,78 @@
+### Please describe the problem.
+
+I have a repo that I initialized in direct mode because i felt unconfortable with the "symlink forest" approach.
+
+Now that I prefer that, i want to switch back to indirect mode. The problem is, when I did that, I realized that some files in the repo were not writable by my user, and git annex indirect crashed, and didn't "indirect" all the files. Now the repo is in a "half-direct" state, and I seem to be unable to recover.
+
+### What steps will reproduce the problem?
+
+[[!format txt """
+git init
+git annex init
+git annex direct
+git annex add . # make sure some files are not writable by your user
+git annex indirect
+"""]]
+
+The `indirect` step will stop at the file that is not writable and will fail to move some files to `.git/annex`. And then the repo is in `indirect` mode yet some files are still not symlinks.
+
+Doing a `git annex direct` will try to commit all those nasty files into git, as it does a `git commit -a`.
+
+### What version of git-annex are you using? On what operating system?
+
+ git-annex version: 4.20130912-ga1faca3
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi
+
+Debian wheezy.
+
+### Please provide any additional information below.
+
+Ideally, there would be a way to just tell git annex it's really still in direct mode and migrate the remaining files.
+
+The workaround is, obviously, to make sure you own all those files before messing around:
+
+ chown -R you *
+ chmod -R u+w *
+
+A [[patch]], maybe, that allows you to flip cleanly between the two modes:
+
+[[!format diff """
+From a21dfc97da96883b2a088bb5f3f466296f08d858 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= <anarcat@koumbit.org>
+Date: Mon, 16 Sep 2013 13:58:29 -0400
+Subject: [PATCH] do not commit -a when going back to direct mode
+
+without this, if we switched to indirect mode but failed doing so
+(because of a permission problem, for example), going back to
+direct mode will commit all files to git, which we really want
+to avoid.
+
+---
+ Command/Direct.hs | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/Command/Direct.hs b/Command/Direct.hs
+index 7835988..ed8ea6c 100644
+--- a/Command/Direct.hs
++++ b/Command/Direct.hs
+@@ -33,7 +33,6 @@ perform = do
+ showOutput
+ _ <- inRepo $ Git.Command.runBool
+ [ Param "commit"
+- , Param "-a"
+ , Param "-m"
+ , Param "commit before switching to direct mode"
+ ]
+--
+1.7.10.4
+
+"""]]
+
+Any update on this? Why is `-a` used here? -- [[anarcat]]
+
+> -a is not really the problem. You certianly do usually want
+> to commit your changes before converting to direct mode.
+>
+> [[done]]; now when this happens it catches the exception and
+> leaves the file in direct mode, which is the same as it being
+> unlocked. --[[Joey]]
diff --git a/doc/bugs/git_annex_indirect_can_fail_catastrophically/comment_1_0b085e7e8c8e364f479574bc00c7c394._comment b/doc/bugs/git_annex_indirect_can_fail_catastrophically/comment_1_0b085e7e8c8e364f479574bc00c7c394._comment
new file mode 100644
index 000000000..68814881d
--- /dev/null
+++ b/doc/bugs/git_annex_indirect_can_fail_catastrophically/comment_1_0b085e7e8c8e364f479574bc00c7c394._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:57:25Z"
+ content="""
+Worse than being stuck partway converted, it fails in such a way that the file you can't write to is left stuck in .git/annex/objects/ without a symlink pointint to it.
+
+Here is how to recover:
+
+1. run `git annex direct`
+2. run `git annex indirect`
+3. run `git annex direct`
+4. run `git annex indirect`
+5. run `git revert HEAD`
+6. run `git annex direct`
+7. fix the permission of the file
+8. run `git annex indirect`
+
+Please don't ask me why this works, but it will..
+"""]]
diff --git a/doc/bugs/git_annex_migrate_leaves_old_backend_versions_around/comment_1_f3e418144e5a5a9b3eda459546fc2bb0._comment b/doc/bugs/git_annex_migrate_leaves_old_backend_versions_around/comment_1_f3e418144e5a5a9b3eda459546fc2bb0._comment
new file mode 100644
index 000000000..dac018cfa
--- /dev/null
+++ b/doc/bugs/git_annex_migrate_leaves_old_backend_versions_around/comment_1_f3e418144e5a5a9b3eda459546fc2bb0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://nicolas-schodet.myopenid.com/"
+ ip="2a01:e35:8ae6:f130:1e4b:d6ff:fe78:1ddb"
+ subject="Hardlink on remote repository?"
+ date="2013-08-15T06:58:16Z"
+ content="""
+Does the hardlink magic also work on the remote repository? If I understand correctly, the remote does not know that the new hash is the same file (and also, file needs to be transferred again) unless the migration is done on all remote before synchronizing. Is it right?
+"""]]
diff --git a/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated.mdwn b/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated.mdwn
new file mode 100644
index 000000000..e5960b62e
--- /dev/null
+++ b/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated.mdwn
@@ -0,0 +1,11 @@
+### Please describe the problem.
+I created a .gitignore file and added it to git annex. In the assistant webapp log, the error "The installed version of git is too old for .gitignores to be honored by git-annex." shows up. According to [[bugs/assistant_ignore_.gitignore/]] this bug should be fixed in a later git version.
+
+### What steps will reproduce the problem?
+Download the current prebuilt linux tarball from [[/install]], extract it, run "./runshell", then "git --version" returns "git version 1.7.10.4"
+
+### What version of git-annex are you using? On what operating system?
+git-annex-standalone-amd64.tar.gz 2013-09-22 09:56 (Linux Ubuntu Precise)
+
+> Updated to wheezy backport 1.8.4. [[done]] for now, obviously it will go
+> out of date again eventually.. --[[Joey]]
diff --git a/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated/comment_1_2a5a07498df9d38531d4570f7b463b9a._comment b/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated/comment_1_2a5a07498df9d38531d4570f7b463b9a._comment
new file mode 100644
index 000000000..5287ea935
--- /dev/null
+++ b/doc/bugs/git_version_in_prebuilt_linux_tarball_is_outdated/comment_1_2a5a07498df9d38531d4570f7b463b9a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:18:49Z"
+ content="""
+The tarballs are built on Debian stable in order to have an old enough libc to work most places. So I am limited to what is available in stable and backports. Once there is a backport available of git, I will use it.
+"""]]
diff --git a/doc/bugs/immediately_drops_files.mdwn b/doc/bugs/immediately_drops_files.mdwn
new file mode 100644
index 000000000..70f7faa46
--- /dev/null
+++ b/doc/bugs/immediately_drops_files.mdwn
@@ -0,0 +1,222 @@
+### Please describe the problem.
+When I `git annex get` files in a certain directory, they are got, then are dropped.
+When I do the same in a different directory, then the files there remains (as expected).
+
+`git annex fsck` also fails on these files, but after that the problem persists.
+
+I'm not really sure where to look to see why this is happening, especially why only on some directories.
+The filesystem (ext4) this is on has several GB free.
+
+Looking at the (broken) symlinks, they are strange:
+
+[[!format sh """
+git annex fsck IMG_4230.JPG > /dev/null
+ls -l IMG_4230.JPG
+lrwxrwxrwx 1 walter walter 207 Aug 13 12:14 IMG_4230.JPG -> ../../../.git/annex/objects/86/KF/SHA256E-s4209479--bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG/SHA256E-s4209479--bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG
+"""]]
+
+But then after getting it (and it being dropped somehow), the symlink is different (the number of ..s)
+
+[[!format sh """
+git annex get IMG_4230.JPG > /dev/null
+ls -l IMG_4230.JPG
+lrwxrwxrwx 1 walter walter 210 Aug 13 12:16 IMG_4230.JPG -> ../../../../.git/annex/objects/86/KF/SHA256E-s4209479--bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG/SHA256E-s4209479--bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG
+"""]]
+
+
+
+### What steps will reproduce the problem?
+
+I'm not really sure; I will test later whether this happens on other computers.
+
+### What version of git-annex are you using? On what operating system?
+ git-annex version: 4.20130812-gc590455
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+On ubuntu 12.10
+
+
+--Walter
+
+### Please provide any additional information below.
+
+*output of git annex fsck*
+[[!format sh """
+git annex fsck 2013/08/01/IMG_4230.JPG
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","ls-files","--cached","-z","--","2013/08/01/IMG_4230.JPG"]
+[2013-08-13 12:01:25 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","check-attr","-z","--stdin","annex.backend","annex.numcopies","--"]
+fsck 2013/08/01/IMG_4230.JPG [2013-08-13 12:01:25 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","cat-file","--batch"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..3afd101dade8be4e1ed7ac48fdf4173274d3ecd7","--oneline","-n1"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 12:01:25 NZST] read: git ["config","--null","--list"]
+ok
+[2013-08-13 12:01:25 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","hash-object","-w","--stdin-paths","--no-filters"]
+[2013-08-13 12:01:25 NZST] feed: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-index","-z","--index-info"]
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+(Recording state in git...)
+[2013-08-13 12:01:25 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","write-tree"]
+[2013-08-13 12:01:25 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","commit-tree","78aca82f86ffb91bc841a3978f410e55aa6e0efe","-p","refs/heads/git-annex"]
+[2013-08-13 12:01:25 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-ref","refs/heads/git-annex","14908fedbd44917815dd013125b69def1f7f8f7c"]
+
+"""]]
+
+*output of git annex get* (output taken from daemon.log, as output from command does not include the dropping part)
+[[!format sh """
+git annex get 2013/08/01/IMG_4230.JPG
+[2013-08-13 12:03:46 NZST] TransferWatcher: transfer starting: Download UUID "e6bb2ef2-b2b5-11e1-bd1b-3fd40e5e767d" 2013/08/01/IMG_4230.JPG Nothing
+[2013-08-13 12:03:46 NZST] TransferWatcher: transfer starting: Download UUID "e6bb2ef2-b2b5-11e1-bd1b-3fd40e5e767d" 2013/08/01/IMG_4230.JPG Nothing
+[2013-08-13 12:03:46 NZST] TransferWatcher: transfer finishing: Transfer {transferDirection = Download, transferUUID = UUID "e6bb2ef2-b2b5-11e1-bd1b-3fd40e5e767d", transferKey = Key {keyName = "bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG", keyBackendName = "SHA256E", keySize = Just 4209479, keyMtime = Nothing}}
+[2013-08-13 12:03:46 NZST] Watcher: add symlink 01/IMG_4230.JPG
+[2013-08-13 12:03:46 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","hash-object","-t","blob","-w","--stdin","--no-filters"]
+[2013-08-13 12:03:46 NZST] Committer: committing 1 changes
+[2013-08-13 12:03:46 NZST] Committer: Committing changes to git
+[2013-08-13 12:03:46 NZST] feed: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-index","-z","--index-info"]
+[2013-08-13 12:03:46 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","commit","--allow-empty-message","--no-edit","-m","","--quiet","--no-verify"]
+[2013-08-13 12:03:46 NZST] Pusher: Synok
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+drop 01/IMG_4230.JPG cing with Adata, b(checking cloud...) itbucket
+[2013-08-13 12:03:46 NZST] Committer: dropped 01/IMG_4230.JPG (from here) (copies now 4) : file renamed
+[2013-08-13 12:03:46 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","hash-object","-w","--stdin-paths","--no-filters"]
+[2013-08-13 12:03:46 NZST] feed: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-index","-z","--index-info"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","write-tree"]
+[2013-08-13 12:03:47 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","commit-tree","f288bfce8d133cc0ce00b65d48ca726809da34e6","-p","refs/heads/git-annex"]
+[2013-08-13 12:03:47 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-ref","refs/heads/git-annex","5a188246bda51207d12adf86c6d87568ca7076d7"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","symbolic-ref","HEAD"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","refs/heads/master"]
+[2013-08-13 12:03:47 NZST] Pusher: pushing to [Remote { name ="Adata" },Remote { name ="bitbucket" }]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 12:03:47 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","branch","-f","synced/master"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:03:47 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master:synced/master"]
+[2013-08-13 12:03:47 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","Adata","git-annex:synced/git-annex","master:synced/master"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..5a188246bda51207d12adf86c6d87568ca7076d7","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..3afd101dade8be4e1ed7ac48fdf4173274d3ecd7","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","ls-tree","-z","--","refs/heads/git-annex","uuid.log","remote.log","trust.log","group.log","preferred-content.log"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..5a188246bda51207d12adf86c6d87568ca7076d7","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..3afd101dade8be4e1ed7ac48fdf4173274d3ecd7","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 12:03:47 NZST] Watcher: add symlink 01/IMG_4230.JPG
+[2013-08-13 12:03:47 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","hash-object","-t","blob","-w","--stdin","--no-filters"]
+To /media/walter/327D522A6727FE79/Pictures
+ 3afd101..5a18824 git-annex -> synced/git-annex
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","Adata","git-annex:synced/git-annex","master"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..5a188246bda51207d12adf86c6d87568ca7076d7","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..3afd101dade8be4e1ed7ac48fdf4173274d3ecd7","--oneline","-n1"]
+[2013-08-13 12:03:48 NZST] Committer: committing 1 changes
+[2013-08-13 12:03:48 NZST] Committer: Committing changes to git
+[2013-08-13 12:03:48 NZST] feed: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-index","-z","--index-info"]
+[2013-08-13 12:03:48 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","commit","--allow-empty-message","--no-edit","-m","","--quiet","--no-verify"]
+To git@bitbucket.org:waltersom/Pictures.git
+ 3afd101..5a18824 git-annex -> synced/git-annex
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..5a188246bda51207d12adf86c6d87568ca7076d7","--oneline","-n1"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 12:03:52 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 12:03:58 NZST] Pusher: Syncing with Adata, bitbucket
+[2013-08-13 12:03:58 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","symbolic-ref","HEAD"]
+[2013-08-13 12:03:58 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","refs/heads/master"]
+[2013-08-13 12:03:58 NZST] Pusher: pushing to [Remote { name ="Adata" },Remote { name ="bitbucket" }]
+[2013-08-13 12:03:58 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","branch","-f","synced/master"]
+[2013-08-13 12:03:58 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","Adata","git-annex:synced/git-annex","master:synced/master"]
+[2013-08-13 12:03:58 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master:synced/master"]
+Everything up-to-date
+[2013-08-13 12:03:58 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","Adata","git-annex:synced/git-annex","master"]
+Everything up-to-date
+[2013-08-13 12:04:02 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master"]
+
+"""
+]]
+
+
+
+I tried removing the USB drive I had plugged in, and was able to get the file from S3, and it wasn't dropped.
+However, checking the logs, I see that it did try to drop the file, but was unable to verify numcopies, so gives up.
+Also odd, is that it doesn't suggest making the USB drive available, but `git annex whereis` knows that the drive does have it. Also, annex.numcopies is 1, and it got it from S3, so why can't it drop it on the computer?
+Or, why does it say that it needs two copies? `git config annex.numcopies` gives 1.
+
+[[!format sh """
+[2013-08-13 16:52:08 NZST] TransferWatcher: transfer starting: Download UUID "be992080-b1db-11e1-8f79-1b10bb4092ef" 01/IMG_4230.JPG Nothing
+[2013-08-13 16:54:06 NZST] TransferWatcher: transfer starting: Download UUID "be992080-b1db-11e1-8f79-1b10bb4092ef" 01/IMG_4230.JPG Just 65504
+[...]
+[2013-08-13 16:54:06 NZST] TransferWatcher: transfer starting: Download UUID "be992080-b1db-11e1-8f79-1b10bb4092ef" 01/IMG_4230.JPG Just 4192256
+[2013-08-13 16:54:06 NZST] TransferWatcher: transfer finishing: Transfer {transferDirection = Download, transferUUID = UUID "be992080-b1db-11e1-8f79-1b10bb4092ef", transferKey = Key {keyName = "bba2489f526ed1288d23157b2b985bfda99321c52d05d3f4ddb92144b301318e.JPG", keyBackendName = "SHA256E", keySize = Just 4209479, keyMtime = Nothing}}
+[2013-08-13 16:54:06 NZST] Watcher: add symlink 01/IMG_4230.JPG
+[2013-08-13 16:54:06 NZST] chat: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","hash-object","-t","blob","-w","--stdin","--no-filters"]
+[2013-08-13 16:54:06 NZST] Committer: committing 1 changes
+[2013-08-13 16:54:06 NZST] Committer: Committing changes to git
+[2013-08-13 16:54:06 NZST] feed: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","update-index","-z","--index-info"]
+[2013-08-13 16:54:06 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","commit","--allow-empty-message","--no-edit","-m","","--quiet","--no-verify"]
+[2013-08-13 16:54:06
+ Could only verify the existence of 1 out of 2 necessary copies
+
+ Try making some of these repositories available:
+ 416aa28e-b1d4-11e1-9539-c39b14a3f7d2 -- timeline laptop
+ f42d30a0-b1d2-11e1-8b32-3bdd169e3280 -- my desktop
+
+ (Use --force to override this check, or adjust annex.numcopies.)
+failed
+(Recording state in git...)
+(Recording state in git...)
+(Recording state in git...)
+drop 01/IMG_4230.JPG NZST] Pusher:(checking cloud...) Syncing with bitbucket
+(unsafe) [2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","symbolic-ref","HEAD"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","refs/heads/master"]
+[2013-08-13 16:54:07 NZST] Pusher: pushing to [Remote { name ="bitbucket" }]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 16:54:07 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","branch","-f","synced/master"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 16:54:07 NZST] call: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master:synced/master"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..7b6b1c6c479a13f9d4ece135bdf3ba31bc484b31","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..11a0c19d7c79f3e574b81295782ab2820caea232","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..5ebb3e46b8fc109c2966ceccdd716f469d94fcad","--oneline","-n1"]
+[2013-08-13 16:54:07 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","ls-tree","-z","--","refs/heads/git-annex","uuid.log","remote.log","trust.log","group.log","preferred-content.log"]
+To git@bitbucket.org:waltersom/Pictures.git
+ 5ebb3e4..7b6b1c6 git-annex -> synced/git-annex
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","git-annex"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","push","bitbucket","git-annex:synced/git-annex","master"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","show-ref","--hash","refs/heads/git-annex"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..7b6b1c6c479a13f9d4ece135bdf3ba31bc484b31","--oneline","-n1"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..9be78e75db197a26db6aaaffbcddf5057e30d23f","--oneline","-n1"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..2bae49a6e1ce85ad501b0fa85439da7cde8c8597","--oneline","-n1"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..b5858e25b7f7c45564ab463ecf3e74ecd8979609","--oneline","-n1"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..11a0c19d7c79f3e574b81295782ab2820caea232","--oneline","-n1"]
+[2013-08-13 16:54:12 NZST] read: git ["--git-dir=/home/walter/Photos/.git","--work-tree=/home/walter/Photos","log","refs/heads/git-annex..cad75ea77d513a24006ee0b56ff0aad12b7aa805","--oneline","-n1"]
+"""]]
diff --git a/doc/bugs/immediately_drops_files/comment_1_9ef6e694ef8a8eee7a42f88554475db7._comment b/doc/bugs/immediately_drops_files/comment_1_9ef6e694ef8a8eee7a42f88554475db7._comment
new file mode 100644
index 000000000..9d630e385
--- /dev/null
+++ b/doc/bugs/immediately_drops_files/comment_1_9ef6e694ef8a8eee7a42f88554475db7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T16:41:04Z"
+ content="""
+You are running the git annex assistant, which takes care of getting and dropping files as it's configured to do, and you are then going in and manually running `git annex get`. If the assistant sees a file's content has appeared, and that file is in a directory that it has been configured to not want the content of file in (the `archive` directory by default), it will immediately try to drop it.
+
+The only thing I don't understand is why the number of `..` in the symlink would change.
+"""]]
diff --git a/doc/bugs/immediately_drops_files/comment_2_76e4f8b73ab60b2540dd2a3e5379791d._comment b/doc/bugs/immediately_drops_files/comment_2_76e4f8b73ab60b2540dd2a3e5379791d._comment
new file mode 100644
index 000000000..274090c63
--- /dev/null
+++ b/doc/bugs/immediately_drops_files/comment_2_76e4f8b73ab60b2540dd2a3e5379791d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-24T16:41:47Z"
+ content="""
+BTW if you don't want the assistant to automatically get and drop files in your repository, you can edit the repository in the webapp and select \"manual mode\".
+"""]]
diff --git a/doc/bugs/immediately_drops_files/comment_3_788db083f5ba2e5589c3b952203ec954._comment b/doc/bugs/immediately_drops_files/comment_3_788db083f5ba2e5589c3b952203ec954._comment
new file mode 100644
index 000000000..9253caa1a
--- /dev/null
+++ b/doc/bugs/immediately_drops_files/comment_3_788db083f5ba2e5589c3b952203ec954._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 3"
+ date="2013-08-24T21:59:12Z"
+ content="""
+I have all of my repositories set to either manual (all the computers), or full backup (the usb drive and s3).
+So, this is happening in a manual repository.
+
+
+Also, I still don't understand why it would be confused over the annex.numcopies setting (why does it claim it needs 2 copies, when numcopies is 1?)
+
+I just tested between desktop and laptop. File is also present in s3.
+
+File on desktop. Copy to laptop --> desktop drops (why? both are set to manual, and both have the other set as manual as well)
+
+Get on desktop. Works, it gets it from laptop. But then, desktop makes laptop drop it (why? again, both are manual repositories)
+
+
+
+"""]]
diff --git a/doc/bugs/immediately_drops_files/comment_4_425b79865eb77d69d0b7a71a14639f81._comment b/doc/bugs/immediately_drops_files/comment_4_425b79865eb77d69d0b7a71a14639f81._comment
new file mode 100644
index 000000000..aacf2f2dc
--- /dev/null
+++ b/doc/bugs/immediately_drops_files/comment_4_425b79865eb77d69d0b7a71a14639f81._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 4"
+ date="2013-09-13T19:27:51Z"
+ content="""
+> both are set to manual, and both have the other set as manual as well
+
+I'm not sure what you mean by that. Do you mean that when you run git annex vicfg, it is in group manual?
+"""]]
diff --git a/doc/bugs/immediately_drops_files/comment_5_7c9f660b6bcec31827a44a650e9d4622._comment b/doc/bugs/immediately_drops_files/comment_5_7c9f660b6bcec31827a44a650e9d4622._comment
new file mode 100644
index 000000000..bb2569893
--- /dev/null
+++ b/doc/bugs/immediately_drops_files/comment_5_7c9f660b6bcec31827a44a650e9d4622._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 5"
+ date="2013-09-13T21:58:30Z"
+ content="""
+I had checked in the webapps, and they were all set to manual.
+
+Looking in `git annex vicfg`, the groups are set to manual, and the content is set to standard.
+"""]]
diff --git a/doc/bugs/importfeed_fails__44___bad_feed_content.mdwn b/doc/bugs/importfeed_fails__44___bad_feed_content.mdwn
new file mode 100644
index 000000000..4ee312be0
--- /dev/null
+++ b/doc/bugs/importfeed_fails__44___bad_feed_content.mdwn
@@ -0,0 +1,36 @@
+### Please describe the problem.
+
+I just added a new podcast to my feeds list and it is complaining of "bad feed content" when trying to import.
+
+### What steps will reproduce the problem?
+
+1. git-annex importfeed --fast http://redecentralize.org/podcast/feed.rss
+3. see the sad error "warning: bad feed content"
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 4.20130827
+
+### Please provide any additional information below.
+
+[[!format sh """
+greg@x200s:~/annex/Podcasts$ git-annex importfeed --fast http://redecentralize.org/podcast/feed.rss
+(checking known urls...)
+importfeed http://redecentralize.org/podcast/feed.rss
+--2013-09-09 15:05:17-- http://redecentralize.org/podcast/feed.rss
+Resolving redecentralize.org (redecentralize.org)... 204.232.175.78
+Connecting to redecentralize.org (redecentralize.org)|204.232.175.78|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 4331 (4.2K) [text/xml]
+Saving to: ‘/tmp/feed12649’
+
+100%[==============================================================>] 4,331 --.-K/s in 0.08s
+
+2013-09-09 15:05:17 (56.0 KB/s) - ‘/tmp/feed12649’ saved [4331/4331]
+
+
+ warning: bad feed content
+ok
+"""]]
+
+> upstream bug <https://github.com/sof/feed/issues/5> ; [[done]] --[[Joey]]
diff --git a/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast.mdwn b/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast.mdwn
new file mode 100644
index 000000000..0d6bcb05c
--- /dev/null
+++ b/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast.mdwn
@@ -0,0 +1,77 @@
+### Please describe the problem.
+
+importfeed responds with "failed" when using the option --lazy for specific podcast and no symbolic links get created. However when I don't use the --fast option the podcast enclosures do download and links get created as expected.
+
+### What steps will reproduce the problem?
+
+git-annex importfeed --fast http://schoolsucksproject.com/category/podcast/feed/
+
+### What version of git-annex are you using? On what operating system?
+
+ Ubuntu
+ git-annex version: 4.20130802-g1452ac3
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+### Please provide any additional information below.
+
+ git-annex importfeed --fast http://schoolsucksproject.com/category/podcast/feed/
+ (checking known urls...)
+ (Recording state in git...)
+ importfeed http://schoolsucksproject.com/category/podcast/feed/
+ --2013-09-28 00:27:25-- http://schoolsucksproject.com/category/podcast/feed/
+ Resolving schoolsucksproject.com (schoolsucksproject.com)... 108.162.199.17, 108.162.198.17
+ Connecting to schoolsucksproject.com (schoolsucksproject.com)|108.162.199.17|:80... connected.
+ HTTP request sent, awaiting response... 200 OK
+ Length: unspecified [text/xml]
+ Saving to: `/tmp/feed16555'
+
+ 2013-09-28 00:27:28 (217 KB/s) - `/tmp/feed16555' saved [423071]
+
+ addurl School_Sucks_Project___Podcasts/238f__Presence_and_Productivity__6___Tools_For_A_Freed_Mind_and_A_Voluntary_Life_mp3
+ unable to access url: http://schoolsucks.podomatic.com/enclosure/2013-09-21T08_21_33-07_00.mp3
+ failed
+ addurl School_Sucks_Project___Podcasts/238e__Presence_and_Productivity__5___Habit_Change_mp3
+ unable to access url: http://schoolsucks.podomatic.com/enclosure/2013-09-18T20_40_40-07_00.mp3
+ failed
+ addurl School_Sucks_Project___Podcasts/238d__Presence_and_Productivity__4___Next_Actions__Projects__and_Procrastination_mp3
+ unable to access url: http://schoolsucks.podomatic.com/enclosure/2013-09-16T10_10_06-07_00.mp3
+ failed
+ ...
+
+> (There is no --lazy option. You seem to mean --fast.)
+>
+> This fine web server rejects the User-Agent used by curl:
+
+<pre>
+joey@darkstar:~>curl http://schoolsucks.podomatic.com/enclosure/2013-09-18T20_40_40-07_00.mp3
+Forbidden
+joey@darkstar:~>wget http://schoolsucks.podomatic.com/enclosure/2013-09-18T20_40_40-07_00.mp3
+--2013-09-28 11:18:36-- http://schoolsucks.podomatic.com/enclosure/2013-09-18T20_40_40-07_00.mp3
+Resolving schoolsucks.podomatic.com (schoolsucks.podomatic.com)... 38.99.42.46, 38.110.155.212
+Connecting to schoolsucks.podomatic.com (schoolsucks.podomatic.com)|38.99.42.46|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+<pre>
+
+> git-annex always uses curl for checking file sizes. So the workaround
+> is to use `git annex addurl --relaxed` on this url, which will skip
+> the size check. However, if you only had curl installed, `git-annex get`
+> would again try to use curl to get the file, and would still fail.
+> It only happens to successfully download because git-annex chose
+> to use wget and this site has apparently forgotten to block that.
+>
+> I don't know if it makes sense for git-annex to vary the user-agent
+> to get around such (incredibly stupid) blocking. It could retry
+> with a random user-agent, but that could be construed as abusive
+> behavior; this site has asked us to go away. The only choices
+> that seem really defensible would be to add a --user-agent
+> switch, and/or to make git-annex set a default user agent header
+> of "git-annex", rather than relying on the curl/wget defaults.
+> --[[Joey]]
+
+> I've [[done]] what's discussed above, and verified it fixes
+> behavior for this specific server too.
+> --[[Joey]]
diff --git a/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast/comment_1_4ccfabbaf75e139b32f6fa6f7bc6a7fe._comment b/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast/comment_1_4ccfabbaf75e139b32f6fa6f7bc6a7fe._comment
new file mode 100644
index 000000000..26430ec91
--- /dev/null
+++ b/doc/bugs/importfeed_fails_when_using_the_option_--lazy_for_specific_podcast/comment_1_4ccfabbaf75e139b32f6fa6f7bc6a7fe._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Remy"
+ ip="82.94.186.146"
+ subject="Thank you very much"
+ date="2013-09-30T08:49:33Z"
+ content="""
+Thank you very much for looking into this! This issue was holding me back from using git-annex as my podcatcher. Hope it helps somebody else as well.
+"""]]
diff --git a/doc/bugs/importfeed_should_allow_pubdate_in_the_template.mdwn b/doc/bugs/importfeed_should_allow_pubdate_in_the_template.mdwn
new file mode 100644
index 000000000..44d25b02d
--- /dev/null
+++ b/doc/bugs/importfeed_should_allow_pubdate_in_the_template.mdwn
@@ -0,0 +1,5 @@
+importfeed is a great feature, but it doesn't allow templating the filename with the publish date.
+
+I would suggest adding pubdate option, which would fix this problem.
+
+> duplicate of [[todo/importfeed: allow ${itemdate} with --template]] [[done]] --[[Joey]]
diff --git a/doc/bugs/importfeed_uses___34____95__foo__34___as_extension.mdwn b/doc/bugs/importfeed_uses___34____95__foo__34___as_extension.mdwn
new file mode 100644
index 000000000..5f09e2636
--- /dev/null
+++ b/doc/bugs/importfeed_uses___34____95__foo__34___as_extension.mdwn
@@ -0,0 +1,17 @@
+### Please describe the problem.
+When running importfeed on gitminutes <http://feeds.gitminutes.com/gitminutes-podcast> git-annex interprets the extension as "_mp3" rather than ".mp3" which means that renaming is needed for various audio players to accept the files.
+
+### What steps will reproduce the problem?
+git annex importfeed http://feeds.gitminutes.com/gitminutes-podcast --fast
+
+### What version of git-annex are you using? On what operating system?
+git-annex version: 4.20130802
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+
+on Debian Sid
+
+> Already fixed in git. [[done]] --[[Joey]]
diff --git a/doc/bugs/inconsistent_use_of_SI_prefixes.mdwn b/doc/bugs/inconsistent_use_of_SI_prefixes.mdwn
new file mode 100644
index 000000000..df7fc5fb2
--- /dev/null
+++ b/doc/bugs/inconsistent_use_of_SI_prefixes.mdwn
@@ -0,0 +1,55 @@
+### Please describe the problem.
+
+`git annex status` inconsistently uses mebi (SI) and giga (informal) prefixes.
+
+### What steps will reproduce the problem?
+
+Example:
+
+[[!format txt """
+anarcat@marcos:mp3$ git annex status
+supported backends: SHA256E SHA1E SHA512E SHA224E SHA384E SHA256 SHA1 SHA512 SHA224 SHA384 WORM URL
+supported remote types: git S3 bup directory rsync web glacier hook
+repository mode: direct
+trusted repositories: 0
+semitrusted repositories: 2
+ 00000000-0000-0000-0000-000000000001 -- web
+ b7802161-c984-4c9f-8d05-787a29c41cfe -- here (anarcat@marcos:/srv/mp3)
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 31.93 gigabytes (+1 megabyte reserved)
+local annex keys: 19913
+local annex size: 111.08 gigabytes
+known annex keys: 20085
+known annex size: 111.38 gigabytes
+bloom filter size: 16 mebibytes (3.1% full)
+backend usage:
+ SHA256E: 39998
+"""]]
+
+Notice `mebibytes` and `gigabytes`. It is unclear whether those are gigabytes (1000^3) or gibibytes (1024^3).
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130802~bpo70+2, Debian wheezy.
+
+### Please provide any additional information below.
+
+nil. --[[anarcat]]
+
+> git-annex consistently uses the powers of ten units
+> for disk storage sizes. Its "gigabyte" is the SI gigabyte.
+>
+> It uses the absurdly named units for powers of 2 for memory sizes,
+> in the few places it deals with memory (probably only the above bloom
+> filter size number).
+>
+> AFAIK I am complying with all relevant standards and best practices.
+> Even though I consider them rather dumb, as is clear if you
+> [read the opionated source code I wrote to handle this]().
+>
+> If git-annex used "gibibyte", the numbers it reports for disk size
+> would not match the numbers disk vendors and most tools use.
+>
+> [[bug_is_in_world_not_in_git-annex|done]] --[[Joey]]
+
diff --git a/doc/bugs/internal_server_error:_hGetContents:_invalid_argument___40__invalid_byte_sequence__41__.mdwn b/doc/bugs/internal_server_error:_hGetContents:_invalid_argument___40__invalid_byte_sequence__41__.mdwn
new file mode 100644
index 000000000..8c9703ed2
--- /dev/null
+++ b/doc/bugs/internal_server_error:_hGetContents:_invalid_argument___40__invalid_byte_sequence__41__.mdwn
@@ -0,0 +1,29 @@
+### Please describe the problem.
+
+Some logs fail to be displayed, and instead of displaying parts of the log, no logs at all are displayed in the webapp.
+
+The problem character is, I believe, a latin-1 encoded filename (as opposed to UTF-8). --[[anarcat]]
+
+### What steps will reproduce the problem?
+
+1. download [this logfile](http://paste.anarc.at/daemon.log.1)
+2. install it in .git/annex/daemon.log
+3. load the webapp
+4. visit the logs page
+
+### What version of git-annex are you using? On what operating system?
+
+4.20131105-g8efdc1a
+
+### 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
+Internal Server Error
+/srv/video/.git/annex/daemon.log.1: hGetContents: invalid argument (invalid byte sequence)
+git-annex version 4.20131105-g8efdc1a
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/internal_server_error:_unknown_UUID_on_webapp.mdwn b/doc/bugs/internal_server_error:_unknown_UUID_on_webapp.mdwn
new file mode 100644
index 000000000..307eed308
--- /dev/null
+++ b/doc/bugs/internal_server_error:_unknown_UUID_on_webapp.mdwn
@@ -0,0 +1,147 @@
+### Please describe the problem.
+
+I am having trouble using the webapp with a setup I did on the commandline that was working fine.
+
+I have two machines: one, a server called `marcos`, is available on the internetz and I cloned a repo from there into `markov`, a workstation that is hidden behind a NAT connexion (so I can't add it as a remote).
+
+It seems that because the remote is not locally available as a git remote, the webapp is freaking out because it doesn't recognize `markov` as a proper remote.
+
+### What steps will reproduce the problem?
+
+1. setup git annex locally (on `marcos`) in a repository (probably `git annex init; git annex direct; git annex add .` i somewhat followed [[tips/Git_annex_and_Calibre/]])
+2. `git clone` that repo on a remote, unaccessible (NAT'd) server (`markov`)
+3. start doing some git annex get, get tired, run the web app on `markov`
+4. let that run over there, go back to `marcos`
+5. be curious about what is going on on `markov`, run the webapp and enter the path to the repository created in step one when prompted (it's the first time i run the webapp)
+6. it starts up fine, but doesn't seem to detect `markov`, marking transfers as going to the remote named `unknown`
+7. click on the `unknown` link, crash
+8. go back to the dashboard, crash
+
+From there on, the webapp is pretty much crashed, starting it from scratch asks me if i want to create a git annex repo.
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130921-gd4739c5 compiled and installed by hand on debian wheezy.
+
+### Please provide any additional information below.
+
+[[!format sh """
+# Here's everything that has been logged by the git-annex assistant, as well as by programs it has run.
+
+[2013-11-04 22:42:50 EST] main: starting assistant version 4.20130921-gd4739c5
+(merging synced/git-annex into git-annex...)
+(Recording state in git...)
+
+ No known network monitor available through dbus; falling back to polling
+Already up-to-date.
+
+(scanning...) [2013-11-04 22:42:50 EST] Watcher: Performing startup scan
+04/Nov/2013:22:42:51 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:42:52 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:42:52 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+(Recording state in git...)
+(Recording state in git...)
+(started...)
+
+ metadata.db still has writers, not adding
+[2013-11-04 22:42:59 EST] Committer: Adding cover.jpg Ars Techn..ibre.epub Cyberpres..ibre.epub cover.jpg cover.jpg Ars Techn..ibre.epub cover.jpg Democracy..ibre.epub cover.jpg and 11 other files
+add Calibre/Ars Technica [dim., 03 nov. 2013] (645)/cover.jpg (checksum...) ok
+add Calibre/Ars Technica [dim., 03 nov. 2013] (645)/Ars Technica [dim., 03 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Cyberpresse [lun., 04 nov. 2013] (647)/Cyberpresse [lun., 04 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Cyberpresse [lun., 04 nov. 2013] (647)/cover.jpg (checksum...) ok
+add Calibre/Ars Technica [sam., 02 nov. 2013] (642)/cover.jpg (checksum...) ok
+add Calibre/Ars Technica [sam., 02 nov. 2013] (642)/Ars Technica [sam., 02 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Democracy now! [lun., 04 nov. 2013] (649)/cover.jpg (checksum...) ok
+add Calibre/Democracy now! [lun., 04 nov. 2013] (649)/Democracy now! [lun., 04 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/xkcd [lun., 04 nov. 2013] (646)/cover.jpg (checksum...) ok
+add Calibre/xkcd [lun., 04 nov. 2013] (646)/xkcd [lun., 04 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Cyberpresse [dim., 03 nov. 2013] (644)/cover.jpg (checksum...) ok
+add Calibre/Cyberpresse [dim., 03 nov. 2013] (644)/Cyberpresse [dim., 03 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Le Devoir [sam., 02 nov., 2013] (640)/cover.jpg (checksum...) ok
+add Calibre/Le Devoir [sam., 02 nov., 2013] (640)/Le Devoir [sam., 02 nov., 2013] - Calibre.epub (checksum...) ok
+add Calibre/Le Devoir [lun., 04 nov., 2013] (648)/cover.jpg (checksum...) ok
+add Calibre/Le Devoir [lun., 04 nov., 2013] (648)/Le Devoir [lun., 04 nov., 2013] - Calibre.epub (checksum...) ok
+add Calibre/Cyberpresse [sam., 02 nov. 2013] (641)/cover.jpg (checksum...) ok
+add Calibre/Cyberpresse [sam., 02 nov. 2013] (641)/Cyberpresse [sam., 02 nov. 2013] - Calibre.epub (checksum...) ok
+add Calibre/Le Devoir [dim., 03 nov., 2013] (643)/cover.jpg (checksum...) ok
+add Calibre/Le Devoir [dim., 03 nov., 2013] (643)/Le Devoir [dim., 03 nov., 2013] - Calibre.epub (checksum...) [2013-11-04 22:43:01 EST] Committer: Committing changes to git
+ok
+(Recording state in git...)
+(Recording state in git...)
+04/Nov/2013:22:43:51 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:47:24 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:47:24 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:47:24 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:52:29 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:52:30 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:52:30 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:56:47 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+[2013-11-04 22:57:08 EST] Committer: Adding metadata.db-journal
+add metadata.db-journal (checksum...) [2013-11-04 22:57:08 EST] Committer: Committing changes to git
+[2013-11-04 22:57:09 EST] Committer: Adding metadata.db-journal metadata.db
+ok
+(Recording state in git...)
+(Recording state in git...)
+add metadata.db (checksum...) [2013-11-04 22:57:09 EST] Committer: Committing changes to git
+ok
+(Recording state in git...)
+(Recording state in git...)
+04/Nov/2013:22:57:12 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:57:15 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:57:18 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+04/Nov/2013:22:57:20 -0500 [Error#yesod-core] Unknown UUID @(yesod-core-1.2.4.2:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:485:5)
+"""]]
+
+> I wonder if this couldn't be related to [[cannot determine uuid for origin]], although in this case the remote is just not added to `.git/config`. --[[anarcat]]
+
+> This was fixed in commit 44e1524be53373ddbf28d643bedf5455433c2b2e
+> on Sep 29th. You should update. [[done]]
+>
+> (It also sounds like your repository on markov is for some reason not
+> able to push its git repository to marcos. You might need to fix
+> something in your setup to get syncing working) --[[Joey]]
+>
+> > Humm.. Weird. Upgrading fixes the crash, but `marcos` still sees only
+> > one repository. It sees some syncs going on from `unknown`, and when
+> > I click on that `unknown` link, I get to edit that repository, and
+> > it sees it as `here`. So I am not sure I understand what is going
+> > on here.
+> >
+> > (As for the repo on `markov`, it does sync properly:
+> >
+> > anarcat@desktop008:books$ git annex sync
+> > commit
+> > ok
+> > pull origin
+> > From anarc.at:/srv/books
+> > 3b4fa7b..c35b13e git-annex -> origin/git-annex
+> > ok
+> >
+> > Or rather - it doesn't fail. But it doesn't push!
+> >
+> > anarcat@desktop008:books$ git push
+> > Everything up-to-date
+> >
+> > Note that git on `marcos` is the 1.8.4 backport for some reason.
+> > I know that branch tracking changed with that release, maybe
+> > that's the problem? --[[anarcat]])
+> >
+> > > So yep, I confirm that even in 4.20131105-g8efdc1a, the webapp
+> > > doesn't find the `markov` remote properly, even though
+> > > `git annex status` can:
+> > >
+> > > $ git annex status
+> > > repository mode: direct
+> > > trusted repositories: 0
+> > > semitrusted repositories: 3
+> > > 00000000-0000-0000-0000-000000000001 -- web
+> > > a75cbbf7-e055-423e-b375-443e0552c9e2 -- here (anarcat@marcos:/srv/books)
+> > > aa500f29-42d9-4777-ae02-4a2c3d47db44 -- anarcat@markov:~/books
+> > >
+> > > I see transfers happening, but they go to "unknown". The link is:
+> > >
+> > > http://127.0.0.1:56577/config/repository/edit/UUID%20%22aa500f29-42d9-4777-ae02-4a2c3d47db44%22?auth=...
+> > >
+> > > -- [[anarcat]]
+> > >
+> > > > I have filed this as a separate bug to close the discussion properly here, sorry for the noise. :) see [[bugs/remote_not_showing_up_in_webapp]] --[[anarcat]]
diff --git a/doc/bugs/manpage_has_slight_indentation_error.mdwn b/doc/bugs/manpage_has_slight_indentation_error.mdwn
new file mode 100644
index 000000000..56d9d2266
--- /dev/null
+++ b/doc/bugs/manpage_has_slight_indentation_error.mdwn
@@ -0,0 +1,38 @@
+### Please describe the problem.
+
+The "import" section of the manpage has an indentation error.
+
+### What steps will reproduce the problem?
+
+man git-annex
+
+### What version of git-annex are you using? On what operating system?
+
+anything after 20130827, i believe.
+
+### Please provide any additional information below.
+
+silly patch:
+
+[[!format diff """
+# 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
+diff --git a/Build/mdwn2man b/Build/mdwn2man
+index ba5919b..b3ee404 100755
+--- a/Build/mdwn2man
++++ b/Build/mdwn2man
+@@ -25,7 +25,7 @@ while (<>) {
+ $inlist=1;
+ $spippara=0;
+ }
+- elsif (/.SH/) {
++ elsif (/^.SH/) {
+ $skippara=0;
+ $inlist=0;
+ }
+# End of transcript or log.
+"""]]
+
+-- [[anarcat]]
+
+> [[applied|done]] --[[Joey]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos.mdwn b/doc/bugs/merge_causes_out_of_memory_on_large_repos.mdwn
new file mode 100644
index 000000000..c081f9799
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos.mdwn
@@ -0,0 +1,26 @@
+### Please describe the problem.
+
+`git annex merge` goes out of memory on a large repo.
+
+
+### What steps will reproduce the problem?
+
+ $ git annex merge
+ merge git-annex git-annex: out of memory (requested 1048576 bytes)
+
+### What version of git-annex are you using? On what operating system?
+
+ git-annex version: 4.20130827
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS
+
+On debian wheezy i386
+
+### Please provide any additional information below.
+
+The repository contains a lot of files:
+
+ $ cd .git/objects
+ $ find . -type f | wc -l
+ 1091548
+
+[[!tag moreinfo]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_1_6d47485728ea65a9b555f8be7159dea5._comment b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_1_6d47485728ea65a9b555f8be7159dea5._comment
new file mode 100644
index 000000000..f87a9a84d
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_1_6d47485728ea65a9b555f8be7159dea5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnxlx1UrzVhdy6_gFjzmF42x6QXxBUxg00"
+ nickname="Jakukyo"
+ subject="pre-commit hook of git annex"
+ date="2013-09-11T00:58:09Z"
+ content="""
+The pre-commit hook of git annex throws an 'out of memory' error, too.
+
+As a workaround, I've deleted ~/.git/hooks/pre-commit, and use `git merge` manually.
+"""]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_2_06723d13ecdaf87de5ff2b209e3c5198._comment b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_2_06723d13ecdaf87de5ff2b209e3c5198._comment
new file mode 100644
index 000000000..76a0d2fd4
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_2_06723d13ecdaf87de5ff2b209e3c5198._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 2"
+ date="2013-09-13T18:38:11Z"
+ content="""
+Can you run this so I can get a better idea of the size of this repository:
+
+git ls-tree -r git-annex | wc -l
+"""]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_3_9f83ef190547b291a715cda55b7977d4._comment b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_3_9f83ef190547b291a715cda55b7977d4._comment
new file mode 100644
index 000000000..11f03b39d
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_3_9f83ef190547b291a715cda55b7977d4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 3"
+ date="2013-09-19T18:53:14Z"
+ content="""
+I just fixed a memory leak that occurred when large files were checked directly into git (perhaps by accident by committing files manually when using direct mode). However, I don't think it affected `git annex merge`.
+
+Still need information about how to reproduce this bug...
+"""]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_4_0e32ae0300472c56079cfbcd78a3e386._comment b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_4_0e32ae0300472c56079cfbcd78a3e386._comment
new file mode 100644
index 000000000..d1c447980
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_4_0e32ae0300472c56079cfbcd78a3e386._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnxlx1UrzVhdy6_gFjzmF42x6QXxBUxg00"
+ nickname="Jakukyo"
+ subject="size of repo"
+ date="2013-09-21T09:32:03Z"
+ content="""
+ $ git ls-tree -r git-annex | wc -l
+ 29273
+"""]]
diff --git a/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_5_e8998716107e7ae8d0e8d332812517ad._comment b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_5_e8998716107e7ae8d0e8d332812517ad._comment
new file mode 100644
index 000000000..272dc2fd2
--- /dev/null
+++ b/doc/bugs/merge_causes_out_of_memory_on_large_repos/comment_5_e8998716107e7ae8d0e8d332812517ad._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 5"
+ date="2013-09-25T18:36:39Z"
+ content="""
+That doesn't look very big, I merge one 3x that large on a 128 mb machine.
+
+I think you will need to either email me privately so I can get a copy of your repository to investigate with ... or you can try to investigate on your own.
+
+I think the first things I would try to debug this are to look over `git annex merge --debug` and see if I see anything unusual, and then I would probably `git checkout git-annex` in the repository, and wc -l on all the files and see if any file has a lot of lines, or is otherwise very large.
+
+If that found nothing, my next step would be to rebuild git-annex from source with memory profiling enabled, as explained in this book, and try to get a memory profiling graph that explained what was using up the memory. <http://book.realworldhaskell.org/read/profiling-and-optimization.html>
+"""]]
diff --git a/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build.mdwn b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build.mdwn
new file mode 100644
index 000000000..c10176463
--- /dev/null
+++ b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build.mdwn
@@ -0,0 +1,36 @@
+### Please describe the problem.
+
+1 thumb drive became corrupted when using as a server on raspberry pi, and 2 microSD cards when using as a client in my phone. Both happened during syncing largish repository. (corrupted = permanent input/output error)
+
+* Put git annex on my android phone with a 64GB (FAT) micro SD, fired up git annex, it got reported as corrupted half on hour later, reformatting worked but got reported as corrupted again.
+
+* Put git annex assistant on my raspberry pi, one of the thumbdrives in my LVM (ext4) got corrupted shortly after I began using the assistant. I replaced them with a cheap real SSD drive, and had no problem since.
+
+* Put git annex back on my android phone. Kept it going for an extended sync session, but it never started syncing. I kept it going for an hour or so, and my new 32GB microSD (FAT) got corrupted.
+
+The pattern is nothing like proof, but it seems to be too regular to be completely coincidental. The pattern seems to be: ARM + (SDcard|USBstick) + Assistant = drive corruption.
+
+My guess is that the ARM build might have some kind of unlucky write pattern or loop that causes increased wear, but I know very little of the interna.
+
+### What steps will reproduce the problem?
+
+* Get a raspberry pi and a USB stick, or an android phone and a microSD card
+* Get an [ARM build of the assistant](https://github.com/tradloff/git-annex-RPi)
+* Sync a largish (12GB) repository
+
+### What version of git-annex are you using? On what operating system?
+
+4.20131002 on the pi, 20131024 for the 32GB SD, and 20131015 for the 64GB SD.
+
+### 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
+
+Unfortunately, daemon.log was unrecoverable along with the other files on the SD card.
+
+I can try and autosync the daemon.log somewhere if I happen to come along a bunch of scrap flash storage (not impossible).
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_1_0527581ea60d28bb28504fa2a355ed87._comment b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_1_0527581ea60d28bb28504fa2a355ed87._comment
new file mode 100644
index 000000000..52324a5a8
--- /dev/null
+++ b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_1_0527581ea60d28bb28504fa2a355ed87._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="salvaged logs"
+ date="2013-10-31T10:00:40Z"
+ content="""
+The previously corrupt memory drive magically reappeared, so this might indicate a phone bug. In any case, I was able to salvage the logs from the phone.
+
+[Salvaged Logs](http://capocasa.name/android-4.2-lenovo-daemonlog.tar.gz)
+"""]]
diff --git a/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_2_926a87b60e20d286d49639c8dad13a1a._comment b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_2_926a87b60e20d286d49639c8dad13a1a._comment
new file mode 100644
index 000000000..878e8fd7d
--- /dev/null
+++ b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_2_926a87b60e20d286d49639c8dad13a1a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="correlation does not imply causation"
+ date="2013-11-01T16:37:31Z"
+ content="""
+I've been using git-annex on thumbdrives for years without problems. It seems more likely to me that you have a general problem with your hardware than that one program that does nothing special is somehow at fault.
+"""]]
diff --git a/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_3_c509fba1a9adacfd26a2bd12b4aea988._comment b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_3_c509fba1a9adacfd26a2bd12b4aea988._comment
new file mode 100644
index 000000000..01ab119d2
--- /dev/null
+++ b/doc/bugs/microsd__47__thumbdrives_seem_to_die_when_using_the_ARM_build/comment_3_c509fba1a9adacfd26a2bd12b4aea988._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 3"
+ date="2013-11-02T17:29:55Z"
+ content="""
+True, and good to know. Didn't necessarily want to trigger a big bug hunt here anyway, just some data/logs in case any more correlation comes up.
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange.mdwn b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange.mdwn
new file mode 100644
index 000000000..1dca84346
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange.mdwn
@@ -0,0 +1,40 @@
+### Please describe the problem.
+
+Changing a file in a repository from a symlink to a normal file causes annex to create an annexed file from that typechange regardless of weather or not it was an annexed file.
+
+
+### What steps will reproduce the problem?
+
+ git init newrepo
+ cd newrepo && git annex init
+ touch realfile
+ git add .
+ git commit -m "added realfile"
+ mkdir newdir && cd newdir
+ ln -s ../realfile newfile
+ git add .
+ git commit -m "Added placeholder until we get assets from designers"
+ rm newfile
+ dd bs=1024 count=10000 if=/dev/zero of=newfile
+ git add .
+ git commit -m "Finally got assets from designers"
+ ls -la newfile
+ # lrwxrwxrwx 1 user user <date> newfile -> ../.git/annex/objects/XX/XX/UUID/UUID
+
+### What version of git-annex are you using? On what operating system?
+
+git-annex version: 4.20130802
+
+Ubuntu 12.04 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
+
+
+# End of transcript or log.
+"""]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_1_6ac691645edb483797bee05043fd83b3._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_1_6ac691645edb483797bee05043fd83b3._comment
new file mode 100644
index 000000000..a3c162d61
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_1_6ac691645edb483797bee05043fd83b3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 1"
+ date="2013-08-12T20:19:37Z"
+ content="""
+It looks like all the \"add\" operations are missing from the log, which makes it a bit hard to follow...
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_2_5d67e3a60b7cc30c2b1857f50895d363._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_2_5d67e3a60b7cc30c2b1857f50895d363._comment
new file mode 100644
index 000000000..c122bd92f
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_2_5d67e3a60b7cc30c2b1857f50895d363._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://caust1c.myopenid.com/"
+ nickname="asbraithwaite"
+ subject="comment 2"
+ date="2013-08-12T20:41:34Z"
+ content="""
+Sorry about that. I forgot that -a doesn't add files.
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_3_78f1e081b92f418c20893d86a8715501._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_3_78f1e081b92f418c20893d86a8715501._comment
new file mode 100644
index 000000000..d00556c75
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_3_78f1e081b92f418c20893d86a8715501._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 3"
+ date="2013-08-12T20:48:42Z"
+ content="""
+There are still no git-annex actions in the log, except for the init. So the end result for ls -la is not possible with those commands. You may want to try to reproduce it again and write down the exact command sequence used ;)
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_4_1e2a59e0eec89ef1a57d1488ff40dcf0._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_4_1e2a59e0eec89ef1a57d1488ff40dcf0._comment
new file mode 100644
index 000000000..d68b3ea35
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_4_1e2a59e0eec89ef1a57d1488ff40dcf0._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://caust1c.myopenid.com/"
+ nickname="asbraithwaite"
+ subject="comment 4"
+ date="2013-08-12T21:07:45Z"
+ content="""
+@arand: That's precisely the problem! I think you'll find if you run those commands exactly, that's what you'll get.
+
+It's got something to do with the git annex pre-commit hook that runs and checks for typechanges.
+
+I shortened the output on the last command to be less verbose, but if the full output is needed, I'll add it.
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_5_5e74431048b07631e0dbeca90fdb365b._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_5_5e74431048b07631e0dbeca90fdb365b._comment
new file mode 100644
index 000000000..b2f525648
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_5_5e74431048b07631e0dbeca90fdb365b._comment
@@ -0,0 +1,47 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 5"
+ date="2013-08-12T21:50:47Z"
+ content="""
+Hmm, I think I see it now, you were missing a `rm` command in the log, and I had no idea the pre-commit hook existed :)
+
+This reproduces the issue, and it seems to indeed be a bug in the git-annex pre-commit handling, nice catch.
+
+<pre>
+$ git init temp
+Initialized empty Git repository in /home/arand/tmp/temp/.git/
+$ cd temp && git annex init
+init ok
+(Recording state in git...)
+$ ln -s broken link
+$ git add .
+$ git commit -m\"add broken link\"
+[master (root-commit) 8125488] add broken link
+ 1 file changed, 1 insertion(+)
+ create mode 120000 link
+$ rm link
+$ echo \"actual file\" >link
+$ git add .
+$ git commit -m\"replace link with real file\"
+add link (checksum...) ok
+ok
+(Recording state in git...)
+[master b58b068] replace link with real file
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+$ git diff HEAD~ | cat
+diff --git a/link b/link
+index 86a410d..4104f6e 120000
+--- a/link
++++ b/link
+@@ -1 +1 @@
+-broken
+\ No newline at end of file
++.git/annex/objects/v4/GQ/SHA256E-s12--ef29ded6f5ae80d89a838d37e01ed3efaade7a2994aff87d1100697554b7327b/SHA256E-s12--ef29ded6f5ae80d89a838d37e01ed3efaade7a2994aff87d1100697554b7327b
+\ No newline at end of file
+$
+</pre>
+
+
+
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_6_3724e1c1a5fc6d3589452478249792ec._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_6_3724e1c1a5fc6d3589452478249792ec._comment
new file mode 100644
index 000000000..9c558e05e
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_6_3724e1c1a5fc6d3589452478249792ec._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://caust1c.myopenid.com/"
+ nickname="asbraithwaite"
+ subject="comment 6"
+ date="2013-08-12T21:53:17Z"
+ content="""
+Ah, you're very right. Thank you.
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_7_7f841ea7bf7d44f3d810ca097ac9eb47._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_7_7f841ea7bf7d44f3d810ca097ac9eb47._comment
new file mode 100644
index 000000000..e781beae1
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_7_7f841ea7bf7d44f3d810ca097ac9eb47._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://caust1c.myopenid.com/"
+ nickname="asbraithwaite"
+ subject="comment 7"
+ date="2013-08-12T21:53:56Z"
+ content="""
+I updated the issue with the `rm` statement I forgot.
+"""]]
diff --git a/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_8_c53ce2274388711ffbde1595b64f932b._comment b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_8_c53ce2274388711ffbde1595b64f932b._comment
new file mode 100644
index 000000000..b4ef6b5c7
--- /dev/null
+++ b/doc/bugs/non-annexed_file_changed_to_annexed_on_typechange/comment_8_c53ce2274388711ffbde1595b64f932b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 8"
+ date="2013-08-22T17:25:48Z"
+ content="""
+Yay for the git-annex community for another fine bug testcase!
+
+The problem is simply that it assumes any typechanged link was an annexed file, and doesn't doublecheck. Fixing that now..
+"""]]
diff --git a/doc/bugs/remote_not_showing_up_in_webapp.mdwn b/doc/bugs/remote_not_showing_up_in_webapp.mdwn
new file mode 100644
index 000000000..f8b4da7b1
--- /dev/null
+++ b/doc/bugs/remote_not_showing_up_in_webapp.mdwn
@@ -0,0 +1,88 @@
+### Please describe the problem.
+
+This is a followup on [[bugs/internal_server_error:_unknown_UUID_on_webapp]]. In that issue, webapps previous to 20130929 would crash with `internal server error: unknown UUID`. This was fixed at that date, but some problems remain, namely that the remote that is recognized on the commandline doesn't show up in the webapp.
+
+`markov` is able to push to `marcos`, but not the reverse because `markov` is hidden behind a NAT. `git annex sync` seems to do the right thing accordingly on both ends (which is: `marcos` doesn't try to push to `markov` but `markov` pushes to `marcos`).
+
+### What steps will reproduce the problem?
+
+See [[bugs/internal_server_error:_unknown_UUID_on_webapp]]. I didn't do any further changes other than upgrade `git-annex` on both ends.
+
+### What version of git-annex are you using? On what operating system?
+
+`marcos` is now running `Version: 4.20131105-g8efdc1a Build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi TDFA CryptoHash`
+
+`markov` is now running the wheezy backport, `4.20131002~bpo70+1`.
+
+### Please provide any additional information below.
+
+#### On `marcos`
+
+Here's the output of `git annex status` on `marcos`:
+
+[[!format sh """
+anarcat@marcos:books$ git annex status
+repository mode: direct
+trusted repositories: 0
+semitrusted repositories: 3
+ 00000000-0000-0000-0000-000000000001 -- web
+ a75cbbf7-e055-423e-b375-443e0552c9e2 -- here (anarcat@marcos:/srv/books)
+ aa500f29-42d9-4777-ae02-4a2c3d47db44 -- anarcat@markov:~/books
+untrusted repositories: 0
+transfers in progress: none
+available local disk space: 7.04 gigabytes (+1 megabyte reserved)
+local annex keys: 736
+local annex size: 3.92 gigabytes
+annexed files in working tree: 721
+size of annexed files in working tree: 3.92 gigabytes
+bloom filter size: 16 mebibytes (0.1% full)
+backend usage:
+ SHA256E: 1457
+# End of transcript or log.
+"""]]
+
+Here's a screenshot of the idle webapp on marcos:
+
+<img src="http://i.imgur.com/3HFgj3w.png" />
+
+You can clearly see that the webapp doesn't see the `markov` remote.
+
+When `markov` transfers stuff, `marcos` sees the transfers happening, but marks it as going to the `unknown` remote:
+
+<img src="http://i.imgur.com/YOu9GbA.png" />
+
+Clicking on that link is what was previously triggering [[bugs/internal_server_error:_unknown_UUID_on_webapp]] but now yields a "Unknown remote" error.
+
+<img src="http://i.imgur.com/y7JxULi.png" />
+
+#### On `markov`:
+
+Here is a screenshot from `markov` that shows *it* knows about both repositories and seem to behave properly:
+
+<img src="http://i.imgur.com/fTMslVT.png" />
+
+And here's the output of `git annex status` on markov:
+
+[[!format sh """
+anarcat@desktop008:books$ git annex status
+repository mode: indirect
+trusted repositories: 0
+semitrusted repositories: 3
+ 00000000-0000-0000-0000-000000000001 -- web
+ a75cbbf7-e055-423e-b375-443e0552c9e2 -- origin (anarcat@marcos:/srv/books)
+ aa500f29-42d9-4777-ae02-4a2c3d47db44 -- here (anarcat@markov:~/books)
+untrusted repositories: 0
+transfers in progress:
+ downloading Patrick K. O'Brien/Philip's Atlas of World History, Concise Edition (115)/Philip's Atlas of World History, Concise Edition - Patrick K. O'Brien.pdf from origin
+available local disk space: 93.25 gigabytes (+1 megabyte reserved)
+temporary directory size: 50.07 megabytes (clean up with git-annex unused)
+local annex keys: 708
+local annex size: 3.81 gigabytes
+known annex keys: 721
+known annex size: 3.92 gigabytes
+bloom filter size: 16 mebibytes (0.1% full)
+backend usage:
+ SHA256E: 1429
+"""]]
+
+Finally, note that you sometimes see `desktop008` above: it turns out I am running `git annex` from my workstation, which NFS-mounts the `/home` directory of `markov` into `/srv/musique`. --[[anarcat]]
diff --git a/doc/bugs/remote_not_showing_up_in_webapp/comment_1_2a269732fd528f505777542d3556437a._comment b/doc/bugs/remote_not_showing_up_in_webapp/comment_1_2a269732fd528f505777542d3556437a._comment
new file mode 100644
index 000000000..ecf697d2c
--- /dev/null
+++ b/doc/bugs/remote_not_showing_up_in_webapp/comment_1_2a269732fd528f505777542d3556437a._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-06T16:38:47Z"
+ content="""
+marcov does not show up in the webapp because there is no configured git remote for it.
+
+This is a slightly confusing corner of the webapp. The webapp will show repositories that do not have a configured remote, but it only does it for special remotes. ssh repos, being regular git remotes, don't currently show up in the webapp unless that repository is actually set up as a remote.
+
+It should certianly not show it as \"unknown\"; it would be much better to use the full repo description here, since it does not have a remote name.
+(Unless the description is really long!)
+
+I think you'll also get the \"unknown uuid\" screen even for a special remote that is not configured in the local repository. So that needs to be fixed.
+
+Finally, it would probably be good for the webapp to show ssh repos that don't have remotes as existing, and let the user enter a ssh address to configure them. The problem with trying to do this is it actually has no idea that this is a ssh repo. It could just as easily be a local directory. The UI to configure it would be pretty elaborate.
+"""]]
diff --git a/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch.mdwn b/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch.mdwn
new file mode 100644
index 000000000..c315d4789
--- /dev/null
+++ b/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch.mdwn
@@ -0,0 +1,81 @@
+### Please describe the problem.
+
+On Mac OS X, I tried to switch a repository to direct mode, but there was a
+problem in the middle of the switch (permission denied) and the switch
+aborted, leaving the repository in a half switched state.
+
+I tried different manipulations, one of which was a checkout (oops), switch
+back to indirect, then direct again, and now I have the repository in direct
+mode except one file which caused the permission denied error.
+
+### What steps will reproduce the problem?
+
+Do not know exactly why this file is special. I still have the repository, and
+each time I try to get this file, it fails with the same error message.
+
+### What version of git-annex are you using? On what operating system?
+
+On Umba, git-annex version: 4.20130723, on Mac OS X 10.6.8.
+
+### Please provide any additional information below.
+
+Umba is the Mac OS X, camaar and riva are Debian machines.
+
+[[!format sh """
+Umba$ git annex version
+git-annex version: 4.20130723
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS
+Umba$
+
+Umba$ git annex get --from riva --not --in here
+get 2013-07-31/2013-07-31_180411.jpg (from riva...)
+Password:
+SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+ 2819887 100% 943.08kB/s 0:00:02 (xfer#1, to-check=0/1)
+
+sent 42 bytes received 2820397 bytes 433913.69 bytes/sec
+total size is 2819887 speedup is 1.00
+failed
+git-annex: get: 1 failed
+Umba$ find . -name SHA256-s2819887-\*
+./.git/annex/objects/wq/3j/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+./.git/annex/objects/wq/3j/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c.cache
+./.git/annex/objects/wq/3j/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c.map
+./.git/annex/transfer/failed/download/13fd5d5a-ed97-11e2-9178-574d3b1c0618/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+./.git/annex/transfer/failed/download/95443f2e-ed96-11e2-9d3f-8ffa5b1aae7a/SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+Umba$ git annex fsck
+fsck 2013-07-31/2013-07-31_180411.jpg ok
+(Recording state in git...)
+Umba$ git annex drop 2013-07-31/2013-07-31_180411.jpg
+Umba$ git annex get --from riva --not --in here
+get 2013-07-31/2013-07-31_180411.jpg (from riva...)
+Password:
+SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+ 2819887 100% 949.58kB/s 0:00:02 (xfer#1, to-check=0/1)
+
+sent 42 bytes received 2820397 bytes 512807.09 bytes/sec
+total size is 2819887 speedup is 1.00
+failed
+git-annex: get: 1 failed
+Umba$
+
+camaar% git annex copy --to umba --not --in umba
+copy 2013-07-31/2013-07-31_180411.jpg (checking umba...) (to umba...)
+SHA256-s2819887--987f9811d7b5c7a287a74b7adbb852be4d18eeda61c3507f4e08c534d2356f4c
+ 2819887 100% 4.19MB/s 0:00:00 (xfer#1, to-check=0/1)
+git-annex: //Users/nicolas/Pictures/Petites Boutes/.git/annex/tmp/2013-07-31_18041141700.jpg: rename: permission denied (Operation not permitted)
+git-annex-shell: recvkey: 1 failed
+
+sent 2820393 bytes received 42 bytes 1128174.00 bytes/sec
+total size is 2819887 speedup is 1.00
+rsync error: syntax or usage error (code 1) at main.c(1070) [sender=3.0.9]
+
+ rsync failed -- run git annex again to resume file transfer
+failed
+git-annex: copy: 1 failed
+camaar%
+"""]]
+
+> Put in a fix that works, although perhaps not ideal as I do not
+> understand how the repo got into the original problem state. [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch/comment_1_14cec6448831c67794b62926a03b2fc5._comment b/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch/comment_1_14cec6448831c67794b62926a03b2fc5._comment
new file mode 100644
index 000000000..1aef52076
--- /dev/null
+++ b/doc/bugs/rename:_permission_denied__44___after_direct_mode_switch/comment_1_14cec6448831c67794b62926a03b2fc5._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 1"
+ date="2013-09-30T16:47:42Z"
+ content="""
+I was able to cause a permission denied on `git annex direct` if I made the file in .git/annex/objects be owned by an different user than me. I do not know how that could happen in normal operation of git-annex.
+
+
+I have made `git annex direct` catch this exception and continue. So you will get a repository that is switched to direct mode, but with one file that is still a symlink to the content, and if you fix the permissions problem, `git annex fsck` will fix it.
+
+I am curious about any details of how your repository got into the original state..
+"""]]
diff --git a/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo.mdwn b/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo.mdwn
new file mode 100644
index 000000000..3aa3188af
--- /dev/null
+++ b/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo.mdwn
@@ -0,0 +1,44 @@
+### Please describe the problem.
+
+When I try to add remote ssh server repository it fails with an error:
+
+Internal Server Error
+ssh-keygen failed"
+
+
+### What steps will reproduce the problem?
+1. Select "Add another repository", then choose "Remote server", enter credentials.
+2. On the page "Ready to add remote server" click any choice ("Use a git repository on the server" or "Use an encrypted rsync repository on the server")
+3. Error is raised
+
+### What version of git-annex are you using? On what operating system?
+git-annex version 4.20130922-g7dc188a
+
+Fedora 18 x86_64
+
+### 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
+
+[2013-10-03 19:27:27 NOVT] main: starting assistant version 4.20130922-g7dc188a
+(scanning...) [2013-10-03 19:27:27 NOVT] Watcher: Performing startup scan
+(started...)
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+[2013-10-03 19:55:23 NOVT] call: ssh-keygen ["-P","","-f","/tmp/git-annex-keygen.0/key"]
+ssh-keygen: symbol lookup error: /lib64/libldap-2.4.so.2: undefined symbol: ber_sockbuf_io_udp
+
+
+# End of transcript or log.
+"""]]
+
+> Added ssh-keygen to bundle. [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo/comment_1_52180983b59c247389a55a9523ec435b._comment b/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo/comment_1_52180983b59c247389a55a9523ec435b._comment
new file mode 100644
index 000000000..f0f50151a
--- /dev/null
+++ b/doc/bugs/ssh-keygen_failed_when_adding_remote_server_repo/comment_1_52180983b59c247389a55a9523ec435b._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 1"
+ date="2013-11-08T18:28:37Z"
+ content="""
+Apologies for not following up on this bug sooner..
+
+It seems to me that your system has a broken ssh-keygen program. You didn't say how you installed git-annex, but based on the git rev in the version number, I'm guessing you either built it yourself, or you're using the standalone tarball I build.
+
+In the case of the latter, it didn't include ssh-keygen, so would try to use the one that comes with fedora. It seems likely that the problem comes from the libraries included in the bundle being used with a binary not in the bundle, that in turn is also using additional libraries.
+
+So, I think I should add ssh-keygen to the standalone bundle!
+"""]]
diff --git a/doc/bugs/submodule_path_problem/comment_6_cacc91afcb1739dfca3a60590bb70356._comment b/doc/bugs/submodule_path_problem/comment_6_cacc91afcb1739dfca3a60590bb70356._comment
new file mode 100644
index 000000000..1cae4ea98
--- /dev/null
+++ b/doc/bugs/submodule_path_problem/comment_6_cacc91afcb1739dfca3a60590bb70356._comment
@@ -0,0 +1,67 @@
+[[!comment format=mdwn
+ username="konubinix"
+ ip="82.243.233.186"
+ subject="Git annexed files symlink are wrong when submodule is not in the same path "
+ date="2013-08-08T06:36:10Z"
+ content="""
+Hi,
+
+First, thanks for the great tool that is git-annex!
+
+I have a problem with submodules when the git repository is not a submodule everywhere.
+
+ $ git-annex version
+ git-annex version: 4.20130802
+ ...
+
+ $ git --version
+ git version 1.8.3.2
+
+I try to have a repository has a submodule of another.
+
+ # creating the master repository
+ mkdir annex_master
+ cd annex_master/
+ git init
+ # hack: adding a file to create the master branch
+ touch start
+ git add start
+ git commit -m \"start\"
+ cd ..
+ # create another repository
+ mkdir annex_sub
+ cd annex_sub/
+ git init
+ # hack: adding a file to create the master branch
+ touch start
+ git add start
+ git commit -m \"start\"
+ # it is a annexed repository
+ git annex init sub
+ # add the other repository as submodule of the master one
+ cd ../annex_master/
+ git submodule add ../annex_sub/ module
+ cd module/
+ git annex init sub_module
+ git annex sync origin
+ # add an annexed file
+ echo test > test
+ git annex add
+ git annex sync
+ # go back to the origin repository
+ cd ../../annex_sub/
+ git annex sync
+ ls -l
+
+This returns
+test -> ../.git/modules/module/annex/objects/w8/pv/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
+
+Actually, the file committed is correct. But the fact it points to '../.git/modules/module/...' makes the link work only if the repository is also a submodule and if this submodule is also located in the modules folder in the parent git repository.
+
+I would expect, since this repository is not an annex:
+test -> .git/annex/objects/w8/pv/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2/SHA256E-s5--f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
+
+Do you think that is possible?
+
+Thanks.
+"""]]
diff --git a/doc/bugs/test_suite_failure_on_samba_mount.mdwn b/doc/bugs/test_suite_failure_on_samba_mount.mdwn
new file mode 100644
index 000000000..ab3990c32
--- /dev/null
+++ b/doc/bugs/test_suite_failure_on_samba_mount.mdwn
@@ -0,0 +1,278 @@
+### Please describe the problem.
+
+`git annex test` show multiple failures on a samba mounted partition.
+
+### What steps will reproduce the problem?
+
+just run `git annex test` (in the mounted dir)
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130521, built for architecture `armhf` by the Raspbian maintainers ("jessie" suite at the time of writing)
+
+### Please provide any additional information below.
+
+Here are the last lines of `git annex test` output; AFAICT they are the only lines mentioning failures. Before them the output mentions `+++ OK, passed 100 tests.`.
+
+[[!format text """
+# 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
+
+Cases: 1 Tried: 0 Errors: 0 Failures: 0----------------------------------------------------------------------
+Now, some broader checks ...
+ (Do not be alarmed by odd output here; it's normal.
+ wait for the last line to see how it went.)
+----------------------------------------------------------------------
+init
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ Cases: 1 Tried: 1 Errors: 0 Failures: 0
+Cases: 3 Tried: 0 Errors: 0 Failures: 0Cases: 3 Tried: 1 Errors: 0 Failures: 0----------------------------------------------------------------------
+add
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+Cases: 3 Tried: 2 Errors: 0 Failures: 0 Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+error: unable to create temporary sha1 filename : No such file or directory
+
+git-annex: user error (git ["--git-dir=/media/freebox/.t/tmprepo0/.git","--work-tree=/media/freebox/.t/tmprepo0","commit-tree","4b825dc642cb6eb9a060e54bf8d69288fbee4904"] exited 1)
+ ### Failure in: git-annex add:2
+git annex init failed
+Cases: 3 Tried: 3 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0----------------------------------------------------------------------
+reinject
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ Detected a crippled filesystem.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ Cases: 1 Tried: 1 Errors: 0 Failures: 0
+Cases: 2 Tried: 0 Errors: 0 Failures: 0not supported in direct mode; skipping
+----------------------------------------------------------------------
+unannex
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+error: unable to create temporary sha1 filename : No such file or directory
+
+git-annex: user error (git ["--git-dir=/media/freebox/.t/tmprepo1/.git","--work-tree=/media/freebox/.t/tmprepo1","commit-tree","4b825dc642cb6eb9a060e54bf8d69288fbee4904"] exited 1)
+ ### Failure in: git-annex unannex:0:no content
+git annex init failed
+Cases: 2 Tried: 1 Errors: 0 Failures: 1 Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ Detected a crippled filesystem.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ Cases: 2 Tried: 2 Errors: 0 Failures: 1
+Cases: 3 Tried: 0 Errors: 0 Failures: 0not supported in direct mode; skipping
+----------------------------------------------------------------------
+drop
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+error: unable to create temporary sha1 filename : No such file or directory
+
+git-annex: user error (git ["--git-dir=/media/freebox/.t/tmprepo2/.git","--work-tree=/media/freebox/.t/tmprepo2","commit-tree","4b825dc642cb6eb9a060e54bf8d69288fbee4904"] exited 1)
+ ### Failure in: git-annex drop:0:no remotes
+git annex init failed
+Cases: 3 Tried: 1 Errors: 0 Failures: 1 Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+Cases: 3 Tried: 2 Errors: 0 Failures: 1/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex drop:2:untrusted remote
+git clone failed
+Cases: 3 Tried: 3 Errors: 0 Failures: 2
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex get
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex move
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex copy
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex unlock/lock
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 2 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex edit/commit:0
+git clone failed
+Cases: 2 Tried: 1 Errors: 0 Failures: 1/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex edit/commit:1
+git clone failed
+Cases: 2 Tried: 2 Errors: 0 Failures: 2
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex fix
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex trust/untrust/semitrust/dead
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 4 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex fsck:0
+git clone failed
+Cases: 4 Tried: 1 Errors: 0 Failures: 1/media/freebox/.t/tmprepo3/refs: No such file or directory
+ ### Failure in: git-annex fsck:1
+git clone failed
+Cases: 4 Tried: 2 Errors: 0 Failures: 2/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex fsck:2
+git clone failed
+Cases: 4 Tried: 3 Errors: 0 Failures: 3/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex fsck:3
+git clone failed
+Cases: 4 Tried: 4 Errors: 0 Failures: 4
+Cases: 2 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex migrate:0
+git clone failed
+Cases: 2 Tried: 1 Errors: 0 Failures: 1/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex migrate:1
+git clone failed
+Cases: 2 Tried: 2 Errors: 0 Failures: 2
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex unused/dropunused
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex describe
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex find
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex merge
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex status
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex version
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex sync
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: union merge regression
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: automatic conflict resolution
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex map
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex uninit
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex upgrade
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex whereis
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex hook remote
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex directory remote
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex rsync remote
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex bup remote
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+Cases: 1 Tried: 0 Errors: 0 Failures: 0/media/freebox/.t/tmprepo3/.git: No such file or directory
+ ### Failure in: git-annex crypto
+git clone failed
+Cases: 1 Tried: 1 Errors: 0 Failures: 1
+----------------------------------------------------------------------
+get
+----------------------------------------------------------------------
+move
+----------------------------------------------------------------------
+copy
+----------------------------------------------------------------------
+lock
+----------------------------------------------------------------------
+edit
+----------------------------------------------------------------------
+fix
+----------------------------------------------------------------------
+trust
+----------------------------------------------------------------------
+fsck
+----------------------------------------------------------------------
+migrate
+----------------------------------------------------------------------
+ unused
+----------------------------------------------------------------------
+describe
+----------------------------------------------------------------------
+find
+----------------------------------------------------------------------
+merge
+----------------------------------------------------------------------
+status
+----------------------------------------------------------------------
+version
+----------------------------------------------------------------------
+sync
+----------------------------------------------------------------------
+union merge regression
+----------------------------------------------------------------------
+conflict resolution
+----------------------------------------------------------------------
+map
+----------------------------------------------------------------------
+uninit
+----------------------------------------------------------------------
+upgrade
+----------------------------------------------------------------------
+whereis
+----------------------------------------------------------------------
+hook remote
+----------------------------------------------------------------------
+directory remote
+----------------------------------------------------------------------
+rsync remote
+----------------------------------------------------------------------
+bup remote
+----------------------------------------------------------------------
+crypto
+git-annex: .t/repo/.git/annex: removeDirectory: unsatisified constraints (Directory not empty)
+
+# End of transcript or log.
+"""]]
diff --git a/doc/bugs/test_suite_failure_on_samba_mount/comment_1_e074b20801b921ee2661025a050a8af2._comment b/doc/bugs/test_suite_failure_on_samba_mount/comment_1_e074b20801b921ee2661025a050a8af2._comment
new file mode 100644
index 000000000..623028c80
--- /dev/null
+++ b/doc/bugs/test_suite_failure_on_samba_mount/comment_1_e074b20801b921ee2661025a050a8af2._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="seems like a general git problem"
+ date="2013-08-24T19:55:56Z"
+ content="""
+\"unable to create temporary sha1 filename\" is a git error message. I don't actually see any git-annex failure here, just a git failure that seems to lead to a cascade of other failures.
+
+I'm not sure if the \"/media/freebox/.t/tmprepo3/.git: No such file or directory\" is because git clone has failed due to the other errors, or if git clone somehow failed to set up the .git directory.
+
+It would probably be helpful to have a play around with git on this filesystem and see what breaks. Alternatively, you can use git-annex with `--debug` to see the git commands it's running that fail, and try them yourself and perhaps strace or gdb them or something to see where they go wrong.
+"""]]
diff --git a/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build.mdwn b/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build.mdwn
new file mode 100644
index 000000000..25db6d829
--- /dev/null
+++ b/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build.mdwn
@@ -0,0 +1,9 @@
+As told in http://git-annex.branchable.com/bugs/OSX_app_issues/#comment-2a69d531bd3bb593c1a49dc8cdb34b1e the Mac OS 10.7.5 (Lion) build fails to run.
+
+ $ /Applications/git-annex.app/Contents/MacOS/git-annex
+
+ /Applications/git-annex.app/Contents/MacOS/runshell: line 25: syntax error near unexpected token `&'
+
+Manually editing /Applications/git-annex.app/Contents/MacOS/runshell as told in http://git-annex.branchable.com/bugs/OSX_app_issues/#comment-5579c2150ad4d2ccc207a253fe57612a fixes the issue.
+
+Furthermore, this build is quite outdated...
diff --git a/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build/comment_1_e8df4b36a89b37edd94f3a318ae93a32._comment b/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build/comment_1_e8df4b36a89b37edd94f3a318ae93a32._comment
new file mode 100644
index 000000000..d67330a22
--- /dev/null
+++ b/doc/bugs/typo_on_the_Mac_OS_10.7.5_Lion_build/comment_1_e8df4b36a89b37edd94f3a318ae93a32._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-14T15:26:01Z"
+ content="""
+This is unfortunate.. The Lion autobuilder is running, but has been failing for various reasons for some time, and I have not managed to get ahold of Jimmy to fix them. Also, that machine may be upgraded from Lion before too long.
+"""]]
diff --git a/doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn b/doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn
index 509e12aeb..c31205ede 100644
--- a/doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn
+++ b/doc/bugs/unannex_and_uninit_do_not_work_when_git_index_is_broken.mdwn
@@ -12,3 +12,6 @@ git's index broke and I was unable to restore it. While this is not git-annex' p
%
Ttbomk, the softlinks and objects are enough to un-annex the files; side-stepping git's index if necessary.
+
+> `git annex repair` can now repair broken index files and other
+> git repository corruption. [[done]] --[[Joey]]
diff --git a/doc/bugs/unfinished_repos_in_webapp.mdwn b/doc/bugs/unfinished_repos_in_webapp.mdwn
new file mode 100644
index 000000000..b3e667c61
--- /dev/null
+++ b/doc/bugs/unfinished_repos_in_webapp.mdwn
@@ -0,0 +1,31 @@
+### Please describe the problem.
+
+Hi, all excited that the new release fixes the unknown UUID issue in the Webapp I hurridly installed the latest versions.
+
+Some progress in that the webapp now reports my missing/non-existent repo as an "unfinished repository" in the process of being setup. I see a check status box that when clicked says "in progress please be patient". Also I see the ssh config has changed to use IdentitiesOnly option.
+
+I had a go a deleting details via git-annex vicfg and directly editing the git-annex branch log files as detailed [here](http://git-annex.branchable.com/forum/Reappearing_repos_in_webapp_and_vicfg/). But still no joy.
+
+Any hints on what to do? Nothing in the log seems to help...
+
+### What steps will reproduce the problem?
+
+Not sure anymore.
+
+### What version of git-annex are you using? On what operating system?
+
+Latest.
+
+### 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.
+"""]]
+
+> This seems to be [[done]], at least the bug reporter didn't feel the need
+> to follow up with the info I asked for and says the problem does not
+> affect him. --[[Joey]]
diff --git a/doc/bugs/unfinished_repos_in_webapp/comment_1_9628b100e39489be9f28ef75276a7341._comment b/doc/bugs/unfinished_repos_in_webapp/comment_1_9628b100e39489be9f28ef75276a7341._comment
new file mode 100644
index 000000000..e17c1b899
--- /dev/null
+++ b/doc/bugs/unfinished_repos_in_webapp/comment_1_9628b100e39489be9f28ef75276a7341._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:07:56Z"
+ content="""
+It seems to me that it has already finished applying the workaround. That IdentitiesOnly change could only be made
+if you clicked on a Retry button once it detected a problem.
+
+You may be experiencing a different problem that it cannot recover from. Paste your .git/config file.
+"""]]
diff --git a/doc/bugs/unfinished_repos_in_webapp/comment_2_ba0fbff536b1d067c4098db401dc49f2._comment b/doc/bugs/unfinished_repos_in_webapp/comment_2_ba0fbff536b1d067c4098db401dc49f2._comment
new file mode 100644
index 000000000..8170a0175
--- /dev/null
+++ b/doc/bugs/unfinished_repos_in_webapp/comment_2_ba0fbff536b1d067c4098db401dc49f2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnXybLxkPMYpP3yw4b_I6IdC3cKTD-xEdU"
+ nickname="Matt"
+ subject="comment 2"
+ date="2013-08-08T08:33:32Z"
+ content="""
+Hi, I've sorted this now. The IP address of my laptop had changed on the local network. Fixing it then let the new fix fully work and the in-progress status of the bad repo went away.
+
+Is it right that in the UI I don't see the local LAN configured branch (which I setup for speed) - it all seems to come under the jabber account now and makes an appropriate choice?
+"""]]
diff --git a/doc/bugs/unfinished_repos_in_webapp/comment_3_fd554aa7d93117177784a29270ccf790._comment b/doc/bugs/unfinished_repos_in_webapp/comment_3_fd554aa7d93117177784a29270ccf790._comment
new file mode 100644
index 000000000..cd21af092
--- /dev/null
+++ b/doc/bugs/unfinished_repos_in_webapp/comment_3_fd554aa7d93117177784a29270ccf790._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawniayrgSdVLUc3c6bf93VbO-_HT4hzxmyo"
+ nickname="Tobias"
+ subject="comment 3"
+ date="2013-08-08T12:22:28Z"
+ content="""
+I also see `unfinished repository` in the assistant, but only at git remotes which don't have git-annex installed (f.e. gitlab). annex-ignore is set to true: `git config remote.gitlab.annex-ignore true`.
+
+Clicking on `check status` says `Setting up this repository seems to have stalled! Make sure the remote system is available and retry`
+
+git-annex version: 4.20130802-g1452ac3
+"""]]
diff --git a/doc/bugs/unfinished_repository_when_using_annex-ignore_true_.mdwn b/doc/bugs/unfinished_repository_when_using_annex-ignore_true_.mdwn
new file mode 100644
index 000000000..848f1b30b
--- /dev/null
+++ b/doc/bugs/unfinished_repository_when_using_annex-ignore_true_.mdwn
@@ -0,0 +1,25 @@
+### Please describe the problem.
+
+When using a git remote which doesn't support git-annex (f.e. gitlab) and is configured with `annex-ignore true` the remote is shown as `unfinished repository` in the webapp.
+
+It would be nice if the webapp would recognize this and show the remote as git-only remote including sync-state and remote name (or even better: the remote details, like the URL to the remote)
+
+### What steps will reproduce the problem?
+
+Add a normal git remote and configure `git config remote.<name>.annex-ignore true`.
+Start the webapp.
+
+### What version of git-annex are you using? On what operating system?
+
+ git-annex version: 4.20131101-gf59a6d1
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV 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 webdav glacier hook
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+Kubuntu 13.10 x86_64
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/utf8.mdwn b/doc/bugs/utf8.mdwn
index 61640ec5f..73b9bd9a9 100644
--- a/doc/bugs/utf8.mdwn
+++ b/doc/bugs/utf8.mdwn
@@ -185,3 +185,8 @@ ok
# End of transcript or log.
"""]]
+
+> We seem to have reached a point of confusion, lack of information,
+> and/or diminishing returns with this bug report. I have fixed
+> it as best I can. If you have any problems, please file a new bug report
+> with as complete information as possible. [[done]] --[[Joey]]
diff --git a/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working.mdwn b/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working.mdwn
new file mode 100644
index 000000000..64e83526f
--- /dev/null
+++ b/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working.mdwn
@@ -0,0 +1,28 @@
+### Please describe the problem.
+on [[tips/downloading_podcasts/]] it says to look for "Feeds" in the output of version to see if you have the importfeeds support. I have importfeeds support but "Feeds" is not listed when doing version.
+
+### What steps will reproduce the problem?
+# git-annex version
+# git-annex importfeed <someurl>
+
+### What version of git-annex are you using? On what operating system?
+4.20130802 on Debian unstable
+
+### Please provide any additional information below.
+
+[[!format sh """
+greg@x200s:~/annextest$ git-annex version
+git-annex version: 4.20130802
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+
+greg@x200s:~/annextest$ git-annex importfeed http://feeds.feedburner.com/OpenMetalcast/ogg
+(checking known urls...)
+importfeed http://feeds.feedburner.com/OpenMetalcast/ogg
+....<downloads the episodes etc>
+"""]]
+
+> Forgot I had to manually add that. [[done]] (really this time!) --[[Joey]]
diff --git a/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working/comment_1_ce06ba4f65f322362b23797f6190c7c3._comment b/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working/comment_1_ce06ba4f65f322362b23797f6190c7c3._comment
new file mode 100644
index 000000000..8b156f822
--- /dev/null
+++ b/doc/bugs/version_doesn__39__t_show___34__Feeds__34___but_podcasting_feature_working/comment_1_ce06ba4f65f322362b23797f6190c7c3._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="203.45.2.230"
+ subject="comment 1"
+ date="2013-09-04T01:36:46Z"
+ content="""
+This still is not fixed. :-(
+
+ $ git annex version
+ git-annex version: 4.20130827
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS
+
+
+...but the ```importfeed``` functionality works.
+
+I know this isn't a particularly high priority bug...
+"""]]
diff --git a/doc/bugs/web_app_loops_over_a_non-addable_file.mdwn b/doc/bugs/web_app_loops_over_a_non-addable_file.mdwn
new file mode 100644
index 000000000..a1f490061
--- /dev/null
+++ b/doc/bugs/web_app_loops_over_a_non-addable_file.mdwn
@@ -0,0 +1,56 @@
+### Please describe the problem.
+
+I started the webapp on a pre-existing repo today, and it started adding all sorts of files which I didn't manually add, which is a little bit surprising, but "okay".
+
+The problem is that it would loop over this one file over and over again. Adding it on the commandline yields a proper error, but this doesn't seem to properly propagate to the frontend.
+
+### What steps will reproduce the problem?
+
+Unclear.
+
+### What version of git-annex are you using? On what operating system?
+
+4.20131105-g8efdc1a
+
+### Please provide any additional information below.
+
+Here's the daemon.log:
+
+[[!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
+
+add clips/A31-05-12_21.22.amr (checksum...) [2013-11-06 10:21:10 EST] Committer: Committing changes to git
+[2013-11-06 10:21:11 EST] Committer: Adding A31-05-12_21.22.amr
+(Recording state in git...)
+(Recording state in git...)
+add clips/A31-05-12_21.22.amr (checksum...) [2013-11-06 10:21:11 EST] Committer: Committing changes to git
+[2013-11-06 10:21:12 EST] Committer: Adding A31-05-12_21.22.amr
+(Recording state in git...)
+(Recording state in git...)
+add clips/A31-05-12_21.22.amr (checksum...) [2013-11-06 10:21:12 EST] Committer: Committing changes to git
+[2013-11-06 10:21:13 EST] Committer: Adding A31-05-12_21.22.amr
+(Recording state in git...)
+add clips/A31-05-12_21.22.amr (checksum...) [2013-11-06 10:21:13 EST] Committer: Committing changes to git
+[2013-11-06 10:21:14 EST] Committer: Adding A31-05-12_21.22.amr
+(Recording state in git...)
+(Recording state in git...)
+add clips/A31-05-12_21.22.amr (checksum...) [2013-11-06 10:21:14 EST] Committer: Committing changes to git
+# End of transcript or log.
+"""]]
+
+And here's the attempt on the commandline, which is way more informative:
+
+[[!format sh """
+anarcat@marcos:video$ git annex add .
+add clips/96_257.mp3 ok
+add clips/A31-05-12_21.22.amr (checksum...)
+git-annex: /srv/video/.git/annex/objects/z3/96/SHA256E-s260070--46f0d657cdd79032d431e2aebb04b63685ab26e7d00963036e0b64c9f86998f8.22.amr/SHA256E-s260070--46f0d657cdd79032d431e2aebb04b63685ab26e7d00963036e0b64c9f86998f8.22.amr: setFileMode: permission denied (Operation not permitted)
+failed
+"""]]
+
+Turns out that file is owned by root, so it's an expected failure. But the webapp should simply skip this file, not loop over it.
+
+The workaround is obviously to give this file to the proper user. --[[anarcat]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/webapp:_difficult_to_abort_adding_a_repository.mdwn b/doc/bugs/webapp:_difficult_to_abort_adding_a_repository.mdwn
new file mode 100644
index 000000000..41007dbb4
--- /dev/null
+++ b/doc/bugs/webapp:_difficult_to_abort_adding_a_repository.mdwn
@@ -0,0 +1,24 @@
+### Please describe the problem.
+I could not find a way to abort the addition of a new remote repository.
+
+### What steps will reproduce the problem?
+- start adding a remote repository (unencrypted, with git-annex installed);
+- forget to create the folder on the remote host;
+- navigate away from the repository page;
+- the dashboard says the repository is partially set-up, and the only thing one can do is look at the log (which says the folder is missing).
+
+I was able to solve it by creating another repository with the exact same data.
+
+### What version of git-annex are you using? On what operating system?
+
+Version: 4.20131002-gf25991c on OS X 10.8.5
+
+### 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.
+"""]]
diff --git a/doc/bugs/webapp_usability:_put_the_notices_on_the_right.mdwn b/doc/bugs/webapp_usability:_put_the_notices_on_the_right.mdwn
new file mode 100644
index 000000000..54f6c3a4f
--- /dev/null
+++ b/doc/bugs/webapp_usability:_put_the_notices_on_the_right.mdwn
@@ -0,0 +1,18 @@
+### Please describe the problem.
+
+The colored notices on the left of the screen are a little off. When they disappear, it also leaves a huge gap on the left side.
+
+### What steps will reproduce the problem?
+
+Click the `X` on all the messages on the left.
+
+### What version of git-annex are you using? On what operating system?
+
+4.20130815~bpo70+1 on Debian Wheezy, with Chromium Version 29.0.1547.57 Debian 7.1 (217859)
+
+### Please provide any additional information below.
+
+This is admittedly a very mild problem, but from a usability perspective, it would be less confusing to show those on the right. When they were gone, I thought git-annex was broken somewhat... -- [[anarcat]]
+
+> [[done]], although I'm not sure I'm sold on their being on the right
+> being better. --[[Joey]]
diff --git a/doc/bugs/webapp_usability:_put_the_notices_on_the_right/comment_1_ec7a444e09a028b5225bd41fb83442e8._comment b/doc/bugs/webapp_usability:_put_the_notices_on_the_right/comment_1_ec7a444e09a028b5225bd41fb83442e8._comment
new file mode 100644
index 000000000..a494c5326
--- /dev/null
+++ b/doc/bugs/webapp_usability:_put_the_notices_on_the_right/comment_1_ec7a444e09a028b5225bd41fb83442e8._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T04:36:12Z"
+ content="""
+They're on the left hand side because that's where Bootstrap puts its sidebar.
+If someone knows how to make it put its sidebar on the right I'll happily do so.
+"""]]
diff --git a/doc/bugs/windows_fails_test___34__recoverEncode__34__.mdwn b/doc/bugs/windows_fails_test___34__recoverEncode__34__.mdwn
new file mode 100644
index 000000000..0413bb55d
--- /dev/null
+++ b/doc/bugs/windows_fails_test___34__recoverEncode__34__.mdwn
@@ -0,0 +1,39 @@
+### Please describe the problem.
+
+My windows install (2013-09-09) fails "quick checks" when running "git annex test". See below the errors from two seperate runs of the test in two fresh empty directories:
+
+*** Failed! Exception: 'recoverEncode: invalid argument (invalid character)' (after 13 tests):
+Key {keyName = "\140\DEL\159/\RS'", keyBackendName = "WQACSWJDVY", keySize = Just 6, keyMtime = Just 3}
+prop_idempotent_configEscape
+
+*** Failed! Exception: 'recoverEncode: invalid argument (invalid character)' (after 4 tests):
+Key {keyName = "\130", keyBackendName = "Y", keySize = Nothing, keyMtime = Nothing}
+prop_idempotent_configEscape
+
+### What steps will reproduce the problem?
+
+create a directory
+cd to it in cmd or Git Bash
+run "git annex test"
+
+
+### What version of git-annex are you using? On what operating system?
+
+OS Name: Microsoft Windows 7 Professional (64bit)
+OS Version: 6.1.7601 Service Pack 1 Build 7601
+
+Install Git-1.8.3-preview20130601 (third option to add git and tools to path)
+Install git-annex-installer (2013-09-09)
+
+### 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.
+"""]]
+
+> I've released a fix for this problem. Thanks for reporting! [[done]]
+> --[[Joey]]
diff --git a/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_1_424b3536e21e02f192f7f2b8e833ed18._comment b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_1_424b3536e21e02f192f7f2b8e833ed18._comment
new file mode 100644
index 000000000..e94608921
--- /dev/null
+++ b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_1_424b3536e21e02f192f7f2b8e833ed18._comment
@@ -0,0 +1,67 @@
+[[!comment format=mdwn
+ username="gary"
+ ip="82.112.140.250"
+ subject="Thanks for the fix"
+ date="2013-09-12T07:20:12Z"
+ content="""
+Hi the fix works fine, all the tests pass now. However I am having issues when trying to sync two directories. I have had this working in direct mode in fedora but not in the previously mentioned windows install
+
+2 directories d1 and d2.
+
+SETUP:
+
+cd d1
+
+mkdir annex
+
+cd annex
+
+cp someFile . (as get branch issue if empty)
+
+git init
+
+git annex init d1
+
+cp someFile . (as get branch issue if empty)
+
+git annex add .
+
+git annex sync
+
+cd ..\..\d2
+
+git clone ..\..\d1\annex
+
+cd annex
+
+git annex init d2
+
+git remote add d1 ..\..\d1\annex
+
+cd ..\..\d1\annex
+
+git remote add d2 ..\..\d2\annex
+
+
+SYNCING
+
+cd d1\annex
+
+cp someFiles .
+
+git annex add .
+
+git annex sync
+
+cd ..\..\d2\annex
+
+git annex sync
+
+git annex mirror --from d1
+
+It looks like the files copy across but when I look at them in explorer they are still just the place holders.
+
+any ideas on what may be going on. Does the work flow look correct?
+
+(ps typo on all slashes but
+"""]]
diff --git a/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_2_78db183aa401e2023d7faec5f7a4a573._comment b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_2_78db183aa401e2023d7faec5f7a4a573._comment
new file mode 100644
index 000000000..f186a0d81
--- /dev/null
+++ b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_2_78db183aa401e2023d7faec5f7a4a573._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 2"
+ date="2013-09-13T17:04:26Z"
+ content="""
+That is an unrelated bug. You got very lucky that I saw your followup comment.
+
+I was able to reproduce it, and found bug in git annex fsck that prevented it from finding and fixing this problem on Windows. Am still investigating why the problem occurs in the first place..
+"""]]
diff --git a/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_3_ed2da19eaf0bd0864f6b28816a79bc23._comment b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_3_ed2da19eaf0bd0864f6b28816a79bc23._comment
new file mode 100644
index 000000000..a8f7c0a02
--- /dev/null
+++ b/doc/bugs/windows_fails_test___34__recoverEncode__34__/comment_3_ed2da19eaf0bd0864f6b28816a79bc23._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 3"
+ date="2013-09-13T17:44:04Z"
+ content="""
+I have now diagnosed and fixed the underlying problem on Windows.
+"""]]
diff --git a/doc/bugs/youtube_support_suddenly_stopped_working.mdwn b/doc/bugs/youtube_support_suddenly_stopped_working.mdwn
new file mode 100644
index 000000000..bedda7674
--- /dev/null
+++ b/doc/bugs/youtube_support_suddenly_stopped_working.mdwn
@@ -0,0 +1,62 @@
+### Please describe the problem.
+
+[[This|design/assistant/blog/day_314__quvi/]] says that I can download youtube videos with git-annex, but I can't - it downloads the HTML of the page instead!
+
+### What steps will reproduce the problem?
+
+ git annex addurl http://www.youtube.com/watch?v=BTzNLhxPzjo
+
+Should have downloaded a Bill Hicks video, instead it downloads the HTML.
+
+### What version of git-annex are you using? On what operating system?
+
+[[!format txt """
+git-annex version: 4.20130912-ga1faca3
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi
+local repository version: 3
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2
+"""]]
+
+Note that quvi is still capable of fetching that video, no problem there.
+
+### 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
+anarcat@marcos:clips$ git annex addurl http://www.youtube.com/watch?v=BTzNLhxPzjo
+addurl www.youtube.com_watch_v=BTzNLhxPzjo ok
+anarcat@marcos:clips$ file www.youtube.com_watch_v\=BTzNLhxPzjo
+www.youtube.com_watch_v=BTzNLhxPzjo: broken symbolic link to `.git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b'
+anarcat@marcos:clips$ file www.youtube.com_watch_v\=BTzNLhxPzjo ^C
+anarcat@marcos:clips$ file .git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b
+.git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b: ERROR: cannot open `.git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b' (No such file or directory)
+anarcat@marcos:clips$ git annex get www.youtube.com_watch_v\=BTzNLhxPzjo
+get www.youtube.com_watch_v=BTzNLhxPzjo (from web...)
+--2013-09-14 17:24:23-- http://www.youtube.com/watch?v=BTzNLhxPzjo
+Résolution de www.youtube.com (www.youtube.com)... 173.194.43.96, 173.194.43.97, 173.194.43.98, ...
+Connexion vers www.youtube.com (www.youtube.com)|173.194.43.96|:80...connecté.
+requête HTTP transmise, en attente de la réponse...200 OK
+Longueur: non spécifié [text/html]
+Sauvegarde en : «/srv/video/clips/.git/annex/tmp/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b»
+
+ [ <=> ] 123 245 346K/s ds 0,3s
+
+2013-09-14 17:24:23 (346 KB/s) - «/srv/video/clips/.git/annex/tmp/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b» sauvegardé [123245]
+
+ok
+(Recording state in git...)
+anarcat@marcos:clips$ file www.youtube.com_watch_v\=BTzNLhxPzjo
+www.youtube.com_watch_v=BTzNLhxPzjo: symbolic link to `.git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b'
+anarcat@marcos:clips$ file .git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b
+.git/annex/objects/qZ/q1/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b/SHA256E-s123162--96fe8634aaf035373077473ac2b166c5ad22bfe099112c414eee9fe753f4ce2b: HTML document, UTF-8 Unicode text, with very long lines
+# End of transcript or log.
+"""]]
+
+### Workaround
+
+Use the `quvi` prefix.
+
+> Typo introduced in last release. [[fixed|done]] --[[Joey]]
diff --git a/doc/builds.mdwn b/doc/builds.mdwn
new file mode 100644
index 000000000..b6ada2bc2
--- /dev/null
+++ b/doc/builds.mdwn
@@ -0,0 +1,20 @@
+[[!meta title="git-annex autobuild overview"]]
+
+<h2>Linux i386</h2>
+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/i386/">
+</iframe>
+<h2>Linux amd64</h2>
+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/amd64/">
+</iframe>
+<h2>Android</h2>
+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/android/">
+</iframe>
+<h2>OSX Mountain Lion</h2>
+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mountain-lion/">
+</iframe>
+<h2>OSX Lion</h2>
+<iframe width=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/">
+</iframe>
+<h2>Windows</h2>
+<iframe width=1024 height=1024 scrolling=no frameborder=0 marginheight=0 marginwidth=0 src="https://qa.nest-initiative.org/view/msysGit/job/msysgit-git-annex-assistant-test/">
+</iframe>
diff --git a/doc/contact/comment_1_12d60f767d90bea94974e1ff6b206d31._comment b/doc/contact/comment_1_12d60f767d90bea94974e1ff6b206d31._comment
new file mode 100644
index 000000000..f72f3fbe5
--- /dev/null
+++ b/doc/contact/comment_1_12d60f767d90bea94974e1ff6b206d31._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlZQcpoRmyZBlsFQ7TMMYlZZdmBG1TxMzA"
+ nickname="Felipe"
+ subject="translation"
+ date="2013-09-10T20:19:53Z"
+ content="""
+I would like to translate this content of site, the tutorials, pages, etc, to portuguese. I think that can help many users in my country. How can I build a new pages here with git-annex content in portuguese?
+"""]]
diff --git a/doc/contact/comment_2_95b6d868b913418de50ba121d71d2390._comment b/doc/contact/comment_2_95b6d868b913418de50ba121d71d2390._comment
new file mode 100644
index 000000000..6f451d9ae
--- /dev/null
+++ b/doc/contact/comment_2_95b6d868b913418de50ba121d71d2390._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 2"
+ date="2013-09-12T21:08:16Z"
+ content="""
+I welcome translations in theory, but I do not have any infrastructure in place to support it, so that would have to be the first step.
+
+(Also, this page is not a general-purpose discussion forum.)
+"""]]
diff --git a/doc/contact/comment_3_2cf43bd406673294e6cdbd785c4a0d0c._comment b/doc/contact/comment_3_2cf43bd406673294e6cdbd785c4a0d0c._comment
new file mode 100644
index 000000000..32fbc7f65
--- /dev/null
+++ b/doc/contact/comment_3_2cf43bd406673294e6cdbd785c4a0d0c._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlkA6XinbeOdnEDxEGQUWyjqPGh0kdMXr4"
+ nickname="Blake"
+ subject="Starting git-annex assistant"
+ date="2013-10-02T23:57:48Z"
+ content="""
+Hi Joey,
+
+I am one of your original funders for git-annex. I think you have done a great job and I am proud to say I helped fund your endeavor.
+
+How do I start the git-annex assistant webapp via command line? I installed the program on my Fedora 19 computer via YUM and it does not come packaged with a desktop icon as you show in your demonstration video. I try running `$ git annex assistant` but I cannot access `http://127.0.0.1:34795/` as you do in the video. Also, the quickstart page (http://git-annex.branchable.com/assistant/quickstart/) seems to have outdated information as it states you can start the webapp via `$ git annex webapp`, however when I try to run this I get the following error: `git-annex: unknown command webapp`.
+
+Regards,
+Blake
+
+"""]]
diff --git a/doc/contact/comment_4_586a506e27379d74fbc0f4b654e89c7d._comment b/doc/contact/comment_4_586a506e27379d74fbc0f4b654e89c7d._comment
new file mode 100644
index 000000000..1cf9c3acc
--- /dev/null
+++ b/doc/contact/comment_4_586a506e27379d74fbc0f4b654e89c7d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 4"
+ date="2013-10-03T00:06:11Z"
+ content="""
+Your fedora build apparently does not include the webapp, since `git annex webapp` is the right command. Install the [[install/Linux_standalone]] build instead.
+
+(Again this page is not a discussion forum. Next person to post here will waste my time since I will have to go configure the site to block comments here..)
+"""]]
diff --git a/doc/copies/comment_1_af9bee33777fb8a187b714fc8c5fb11d._comment b/doc/copies/comment_1_af9bee33777fb8a187b714fc8c5fb11d._comment
new file mode 100644
index 000000000..45e572260
--- /dev/null
+++ b/doc/copies/comment_1_af9bee33777fb8a187b714fc8c5fb11d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="See also section on backups in walthroug"
+ date="2013-08-25T05:37:04Z"
+ content="""
+See also [walthrough/backups](/walkthrough/backups/) for some details about copies.
+"""]]
diff --git a/doc/design.mdwn b/doc/design.mdwn
index 6e45df573..9a03e7554 100644
--- a/doc/design.mdwn
+++ b/doc/design.mdwn
@@ -3,4 +3,6 @@ stores in git, and alongside git. See [[internals]] for details.
See [[encryption]] for design of encryption elements.
+See [[roadmap]] for planning and scheduling of new stuff.
+
See [[assistant]] for the design site for the git-annex [[/assistant]].
diff --git a/doc/design/assistant.mdwn b/doc/design/assistant.mdwn
index affe7d63f..daf6fce0b 100644
--- a/doc/design/assistant.mdwn
+++ b/doc/design/assistant.mdwn
@@ -1,11 +1,11 @@
-This is the design site for the git-annex [[/assistant]].
+These are the design pages for the git-annex [[/assistant]].
Parts of the design is still being fleshed out, still many ideas
and use cases to add. Feel free to chip in with comments! --[[Joey]]
-## roadmap
+See [[roadmap]] for current plans.
-kickstarter year
+## initial development kickstarter year overview (2012-2013)
* Month 1 "like dropbox": [[!traillink inotify]] [[!traillink syncing]]
* Month 2 "shiny webapp": [[!traillink webapp]] [[!traillink progressbars]]
@@ -21,22 +21,6 @@ kickstarter year
* Month 11: [[!traillink Windows]] porting, finishing touches
* Month 12: [presentation at SELF2013](http://www.southeastlinuxfest.org/), finishing touches
-[sustaining git-annex development](https://campaign.joeyh.name/) year
-(starts September 2013).
-
-* Month 1 [[!traillink encrypted_git_remotes]]
-* Month 2 [[!traillink disaster_recovery]]
-* Month 3 user-driven features and polishing
-* Month 4 improve special remote interface & git-annex enhancement contest
-* Month 5 [[!traillink xmpp_security]]
-* Month 6 Windows assistant and webapp
-* Month 7 user-driven features and polishing
-* Month 8 [[!traillink gpgkeys]] [[!traillink sshpassword]]
-* Month 9 get [[Android]] out of beta
-* Month 10 user-driven features and polishing
-* Month 11 [[!traillink chunks]] [[!traillink deltas]]
-* Month 12 user-driven features and polishing
-
## porting
* [[OSX]] port is in fairly good shape, but still has some room for improvement
@@ -57,5 +41,5 @@ I post [[polls]] occasionally to make decisions. You can vote!
## blog
-I'm blogging about my progress in the [[blog]] on a semi-daily basis.
+I'm blogging about my progress in the [[devblog]] on a semi-daily basis.
Follow along!
diff --git a/doc/design/assistant/blog.mdwn b/doc/design/assistant/blog.mdwn
index ea21a726b..561173d27 100644
--- a/doc/design/assistant/blog.mdwn
+++ b/doc/design/assistant/blog.mdwn
@@ -1,10 +1,11 @@
-Work on the git-annex assistant is [crowdfunded](https://campaign.joeyh.name/).
-I'll be blogging about my progress here on a semi-daily basis.
+This blog was updated on a semi-daily basis by Joey during the year of work
+concentrating on the git-annex assistant that was funded by his kickstarter
+campaign.
-[[!sidebar content="""
-[[!calendar type="month" pages="page(design/assistant/blog/*)"]]
-[[!calendar type="month" month="-1" pages="page(design/assistant/blog/*)"]]
-[[!calendar type="month" month="-2" pages="page(design/assistant/blog/*)"]]
-"""]]
+Post-kickstarter work will instead appear on the [[devblog]]. However,
+this page's RSS feed will continue to work, so you don't have to migrate
+your RSS reader.
-[[!inline pages="page(design/assistant/blog/*)" show=0]]
+[[!inline pages="page(devblog/*)" show=-1 feedshow=7]]
+
+[[!inline pages="page(design/assistant/blog/*)" show=0 feeds=no]]
diff --git a/doc/design/assistant/blog/day_18__merging/comment_1_7a553ad559519f3b3e3cd20115b4c44e._comment b/doc/design/assistant/blog/day_18__merging/comment_1_7a553ad559519f3b3e3cd20115b4c44e._comment
new file mode 100644
index 000000000..94261f81e
--- /dev/null
+++ b/doc/design/assistant/blog/day_18__merging/comment_1_7a553ad559519f3b3e3cd20115b4c44e._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://droggl.myopenid.com/"
+ ip="2001:638:602:1181:a6ba:dbff:fedd:8041"
+ subject="comment 1"
+ date="2013-09-11T11:55:27Z"
+ content="""
+Nice!
+However I didnt find any documentation yet on how to actually resolve the situation as a user (sorry if I'm being blind).
+To be more specific: Say a conflict occurs on foo.txt and i now have two files foo.variant-dead.txt and foo.variant-beef.txt.
+Now what? Say I used my favorite merge diffmerge tool to create a merged version foo-merged.txt, should I rename that to foo.txt?
+Should I delete the variant files? Or drop them? Or would that lead to another merge for systems that still have the old foo.txt?
+(You see I'm kind of confused of what happens here ;))
+
+TIA for any helpers
+"""]]
diff --git a/doc/design/assistant/blog/day_224__annex.largefiles/comment_2_b24d1da2bc4307ded0216daffb8f9336._comment b/doc/design/assistant/blog/day_224__annex.largefiles/comment_2_b24d1da2bc4307ded0216daffb8f9336._comment
new file mode 100644
index 000000000..14fdfed5c
--- /dev/null
+++ b/doc/design/assistant/blog/day_224__annex.largefiles/comment_2_b24d1da2bc4307ded0216daffb8f9336._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWBvsZvSsAL8P2ye3F0OBStjFCVnOImzM"
+ nickname="Jarno"
+ subject="Making &quot;git-annex add&quot; commit largefiles, too?"
+ date="2013-10-31T00:26:21Z"
+ content="""
+Is it possible to make `git annex add` also *not* skip largefiles but do an automatic `git add` instead? I'd like to keep .txt, .sh and the like in git directly (for easier diffing) but having to add them separately sounds like trouble.
+"""]]
diff --git a/doc/design/assistant/blog/day_311__Windows_porting.mdwn b/doc/design/assistant/blog/day_311__Windows_porting.mdwn
new file mode 100644
index 000000000..fe14a6e4b
--- /dev/null
+++ b/doc/design/assistant/blog/day_311__Windows_porting.mdwn
@@ -0,0 +1,10 @@
+Made two big improvements to the Windows port, in just a few hours.
+First, got gpg working, and encrypted special remotes work on Windows.
+Next, fixed a permissions problem that was breaking removing files
+from directory special remotes on Windows.
+(Also cleaned up a lot of compiler warnings on Windows.)
+
+I think I'm almost ready to move the Windows port from alpha to beta
+status. The only really bad problem that I know of with using it is that
+due to a lack of locking, it's not safe to run multiple git-annex
+commands at the same time in Windows.
diff --git a/doc/design/assistant/blog/day_311__Windows_porting/comment_1_8e738f54a72557bee1e19970472b925c._comment b/doc/design/assistant/blog/day_311__Windows_porting/comment_1_8e738f54a72557bee1e19970472b925c._comment
new file mode 100644
index 000000000..9f4bf2284
--- /dev/null
+++ b/doc/design/assistant/blog/day_311__Windows_porting/comment_1_8e738f54a72557bee1e19970472b925c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlpSOjMH7Iaz56v6Pr9KCFSpbvMXvg-y9o"
+ nickname="Dominik"
+ subject="That's amazing..."
+ date="2013-08-17T11:18:05Z"
+ content="""
+...so pretty soon my bi-directional Mac <-> Win Git-Annex-Assitant sync via rsync.net will work without a VM on Windows :-)
+"""]]
diff --git a/doc/design/assistant/blog/day_312__DebConf_midpoint.mdwn b/doc/design/assistant/blog/day_312__DebConf_midpoint.mdwn
new file mode 100644
index 000000000..8e0758432
--- /dev/null
+++ b/doc/design/assistant/blog/day_312__DebConf_midpoint.mdwn
@@ -0,0 +1,30 @@
+Wow, 11 days off! I was busy with first dentistry and then DebConf.
+
+Yesterday I [visited CERN](http://joeyh.name/blog/entry/words_fail_me/) and
+got to talk with some of their IT guys about how they manage their tens of
+petabytes of data. Interested to hear they also have the equivilant of a
+per-subdirectory annex.numcopies setting. OTOH, they have half a billion
+more files than git's index file is likely to be able to scale to support. ;)
+
+Pushed a release out today despite not having many queued changes.
+Also, I got git-annex migrated to Debian testing, and so was also
+able to update the wheezy backport to a just 2 week old version.
+
+Today is also the last day of the [campaign](https://campaign.joeyh.name/)!
+
+----
+
+There has been a ton of discussion about git-annex here at DebConf,
+including 3 BoF sessions that mostly focused on it, amoung other git stuff.
+Also, RichiH will be presenting his
+"[Gitify Your Life](http://penta.debconf.org/dc13_schedule/events/1025.en.html)"
+talk on Friday; you can catch it on the [live stream](http://blog.debconf.org/blog/2013/08/14#hl_dc13_recordings).
+
+I've also had a continual stream of in-person bug and feature requests.
+(Mostly features.)
+These have been added to the wiki and I look forward to working on that
+backlog when I get home.
+
+As for coding, I am doing little here, but I do have a branch cooking that
+adds some options to `git annex import` to control handling of duplicate
+files.
diff --git a/doc/design/assistant/blog/day_313__back.mdwn b/doc/design/assistant/blog/day_313__back.mdwn
new file mode 100644
index 000000000..28c7f971d
--- /dev/null
+++ b/doc/design/assistant/blog/day_313__back.mdwn
@@ -0,0 +1,34 @@
+Back home. I have some 170 messages of backlog to attend to. Rather than
+digging into that on my first day back, I spent some time implementing some
+new features.
+
+`git annex import` has grown three options that help managing importing of
+duplicate files in different ways. I started work on that last week, but
+didn't have time to find a way to avoid the `--deduplicate` option
+checksumming each imported file twice. Unfortunately, I have still not
+found a way I'm happy with, so it works but is not as efficient as it could
+be.
+
+`git annex mirror` is a new command suggested to me by someone at DebConf
+(they don't seem to have filed the requested todo). It arranges for two
+repositories to contain the same set of files, as much as possible (when
+numcopies allows). So for example, `git annex mirror --to otherdrive`
+will make the otherdrive remote have the same files present and not present
+as the local repository.
+
+I am thinking about expanding `git annex sync` with an option to also sync
+data. I know some find it confusing that it only syncs the git metadata
+and not the file contents. That still seems to me to be the best and most
+flexible behavior, and not one I want to change in any case since
+it would be most unexpected if `git annex sync` downloaded a lot of stuff
+you don't want. But I can see making `git annex sync --data` download
+all the file contents it can, as well as uploading all available file
+contents to each remote it syncs with. And `git annex sync --data --auto`
+limit that to only the preferred content. Although perhaps
+these command lines are too long to be usable?
+
+----
+
+With the campaign more or less over, I only have a little over a week
+before it's time to dive into the first big item on the roadmap. Hope
+to be through the backlog by then.
diff --git a/doc/design/assistant/blog/day_313__back/comment_1_fbf3fdf9688c18156753d446facd942d._comment b/doc/design/assistant/blog/day_313__back/comment_1_fbf3fdf9688c18156753d446facd942d._comment
new file mode 100644
index 000000000..7230a1568
--- /dev/null
+++ b/doc/design/assistant/blog/day_313__back/comment_1_fbf3fdf9688c18156753d446facd942d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="GLITTAH"
+ ip="77.247.181.162"
+ subject="comment 1"
+ date="2013-08-20T22:42:46Z"
+ content="""
+I wouldn't worry about the commands being too long. If they're used often enough, they'll get aliased.
+
+alias GASDA='git annex sync --data --auto'
+"""]]
diff --git a/doc/design/assistant/blog/day_314__quvi.mdwn b/doc/design/assistant/blog/day_314__quvi.mdwn
new file mode 100644
index 000000000..3c38e427d
--- /dev/null
+++ b/doc/design/assistant/blog/day_314__quvi.mdwn
@@ -0,0 +1,27 @@
+Made some good progress on the backlog today. Fixed some bugs, applied some
+patches. Noticing that without me around, things still get followed up
+on, to a point, for example incomplete test cases for bugs get corrected so
+they work. This is a very good thing. Community!
+
+I had to stop going through the backlog when I got to one message from
+Anarcat mentioning [quvi](http://quvi.sourceforge.net/). That turns
+out to be just what is needed to implement the often-requested feature
+of `git-annex addurl` supporting YouTube and other similar sites. So I
+spent the rest of the day making that work. For example:
+
+<pre>
+% git annex addurl --fast 'http://www.youtube.com/watch?v=1mxPFHBCfuU&list=PL4F80C7D2DC8D9B6C&index=1'
+addurl Star_Wars_X_Wing__Seth_Green__Clare_Grant__and_Mike_Lamond_Join_Wil_on_TableTop_SE2E09.webm ok
+</pre>
+
+Yes, that got the video title and used it as the filename, and yes,
+I can commit this file and run `git annex get` later, and it will be
+able to go download the video! I can even use `git annex fsck --fast`
+to make sure YouTube still has my videos. Awesome.
+
+The great thing about quvi is it takes the url to a video webpage, and
+returns an url that can be used to download the actual video file. So it
+simplifies ugly flash videos as far out of existence as is possible.
+However, since the direct url to the video file may not keep working for long.
+addurl actually records the page's url, with an added indication that quvi
+should be used to get it.
diff --git a/doc/design/assistant/blog/day_314__quvi/comment_1_3fdfb0742cb5422530ddd97b904f2a42._comment b/doc/design/assistant/blog/day_314__quvi/comment_1_3fdfb0742cb5422530ddd97b904f2a42._comment
new file mode 100644
index 000000000..797d25101
--- /dev/null
+++ b/doc/design/assistant/blog/day_314__quvi/comment_1_3fdfb0742cb5422530ddd97b904f2a42._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="New YouTube problems"
+ date="2013-09-05T03:45:16Z"
+ content="""
+Joey, you may notice eventually that YouTube is moving some videos, especially long ones, to a new format called DASH, which splits them up into smaller parts; unfortunately, it also delivers the audio as a separate file, requiring something like ffmpeg to merge it with the video. I don't know anything about quvi, but youtube-dl recently added support for DASH. It's a Python program that's packaged in Debian, but it can also update itself if you install it locally, which is helpful if Debian is frozen... Anyway, if you need it in the future, youtube-dl might be helpful.
+"""]]
diff --git a/doc/design/assistant/blog/day_315__backlog.mdwn b/doc/design/assistant/blog/day_315__backlog.mdwn
new file mode 100644
index 000000000..ec0ee33be
--- /dev/null
+++ b/doc/design/assistant/blog/day_315__backlog.mdwn
@@ -0,0 +1,12 @@
+After a couple days plowing through it, my backlog is down to 30 messages
+from 150. And most of what's left is legitimate bugs and todo items.
+
+Spent a while today on an ugly file descriptor leak in the assistant's
+local pairing listener. This was an upstream bug in the network-multicast
+library, so while I've written a patch to fix it, the fix isn't quite
+deployed yet. The file descriptor leak happens when the assistant is
+running and there is no network interface that supports multicast.
+I was able to reproduce it by just disconnecting from wifi.
+
+Meanwhile, guilhem has been working on patches that promise to massively
+speed up `git annex unused`! I will be reviewing them tonight.
diff --git a/doc/design/assistant/blog/day_316__day_off.mdwn b/doc/design/assistant/blog/day_316__day_off.mdwn
new file mode 100644
index 000000000..b26118b17
--- /dev/null
+++ b/doc/design/assistant/blog/day_316__day_off.mdwn
@@ -0,0 +1,6 @@
+Today was a day off, really. However, I have a job running to try to
+build get a version of ghc-android that works on newer Android releases.
+
+Also, guilhem's `git annex unused` speedup patch landed. The results are
+extrordinary -- speedups on the order of 50 to 100 times faster should
+not be uncommon. Best of all (for me), it still runs in constant memory!
diff --git a/doc/design/assistant/blog/day_317__misc.mdwn b/doc/design/assistant/blog/day_317__misc.mdwn
new file mode 100644
index 000000000..e2acf2168
--- /dev/null
+++ b/doc/design/assistant/blog/day_317__misc.mdwn
@@ -0,0 +1,17 @@
+Spent a while tracking down a bug that causes a crash on OSX when setting
+up an XMPP account. I managed to find a small test case that reliably
+crashes, and sent it off to the author of the haskell-gnutls bindings,
+which had one similar segfault bug fixed before with a similar test case.
+Fingers crossed..
+
+Just finished tracking down a bug in the Android app that caused its
+terminal to spin and consume most CPU (and presumably a lot of battery).
+I introduced this bug when adding the code to open urls written to a fifo,
+due to misunderstanding how java objects are created, basically. This bug
+is bad enough to do a semi-immediate release for; luckily it's just about
+time for a release anyway with other improvements, so in the next few
+days..
+
+Have not managed to get a recent ghc-android to build so far.
+
+Guilhem fixed some bugs in `git annex unused`.
diff --git a/doc/design/assistant/disaster_recovery.mdwn b/doc/design/assistant/disaster_recovery.mdwn
index 28dd41c5a..6fcf95519 100644
--- a/doc/design/assistant/disaster_recovery.mdwn
+++ b/doc/design/assistant/disaster_recovery.mdwn
@@ -1,39 +1,105 @@
The assistant should help the user recover their repository when things go
wrong.
+[[!toc ]]
+
## dangling lock files
There are a few ways a git repository can get broken that are easily fixed.
One is left over index.lck files. When a commit to a repository fails,
check that nothing else is using it, fix the problem, and redo the commit.
-This should be done on both the current repository and any local
-repositories. Maybe also make git-annex-shell be able to do it remotely?
+* **done** for .git/annex/index.lock, can be handled safely and automatically.
+* **done** for .git/index.lock, only when the assistant is starting up.
+* What about local remotes, eg removable drives? git-annex does attempt
+ to commit to the git-annex branch of those. It will use the automatic
+ fix if any are dangling. It does not commit to the master branch; indeed
+ a removable drive typically has a bare repository.
+ However, it does a scan for broken locks anyway if there's a problem
+ syncing. **done**
+* What about git-annex-shell? If the ssh remote has the assistant running,
+ it can take care of it, and if not, it's a server, and perhaps the user
+ should be required to fix up if it crashes during a commit. This should
+ not affect the assistant anyway.
+* **done** Seems that refs can also have stale lock files, for example
+ '/storage/emulated/legacy/DCIM/.git/refs/remotes/flick_phonecamera/synced/git-annex.lock'
+ All git lock files are now handled (except gc lock files).
## incremental fsck
-Add webapp UI to enable incremental fsck, and choose when to start and how
-long to run each day.
+Add webapp UI to enable incremental fsck **done**
+
+Of course, incremental fsck will run as an niced (and ioniced) background
+job. There will need to be a button in the webapp to stop it, in case it's
+annoying. **done**
When fsck finds a damanged file, queue a download of the file from a
-remote. If no accessible remote has the file, prompt the user to eg, connect
-a drive containing it.
+remote. **done**
+
+Detect when a removable drive is connected in the Cronner, and check
+and try to run its remote fsck jobs. **done** (Same mechanism will work for
+network remotes becoming connected.)
+
+TODO: If no accessible remote has a file that fsck reported missing,
+prompt the user to eg, connect a drive containing it. Or perhaps this is a
+special case of a general problem, and the webapp should prompt the user
+when any desired file is available on a remote that's not mounted?
## git-annex-shell remote fsck
+TODO: git-annex-shell fsck support, which would allow cheap fast fscks
+of ssh remotes.
+
Would be nice; otherwise remote fsck is too expensive (downloads
-everything) to have the assistant do. (remote fsck --fast might be worth
-having the assistant do)
+everything) to have the assistant do.
+
+Note that Remote.Git already tries to use this, but the assistant does not
+call it for non-local remotes.
+
+## git fsck and repair
+
+Add git fsck to scheduled self fsck **done**
+
+TODO: git fsck on ssh remotes? Probably not worth the complexity..
-## git fsck
+TODO: If committing to the repository fails, after resolving any dangling
+lock files (see above), it should git fsck. This is difficult, because
+git commit will also fail if the commit turns out to be empty, or due to
+other transient problems.. So commit failures are currently ignored by the
+assistant.
-Have the sanity checker run git fsck periodically (it's fairly inexpensive,
-but still not too often, and should be ioniced and niced).
+If git fsck finds problems, launch git repository repair. **done**
-If committing to the repository fails, after resolving any dangling lock
-files (see above), it should git fsck.
+git annex fsck --fast at end of repository repair to ensure
+git-annex branch is accurate. **done**
-If git fsck finds problems, launch git repository repair.
+If syncing with a local repository fails, try to repair it. **done**
+
+TODO: "Repair" gcrypt remotes, by removing all refs and objects,
+and re-pushing. (Since the objects are encrypted data, there is no way
+to pull missing ones from anywhere..)
+Need to preserve gcrypt-id while doing this!
+
+TODO: along with displaying alert when there is a problem detected
+by consistency check, send an email alert. (Using system MTA?)
+
+## nudge user to schedule fscks
+
+Make the webapp encourage users to schedule fscks of their
+local repositories. The goal here was that it should not be obnoxious about
+repeatedly pestering the user to set that up, but should still encourage
+anyone who cares to set it up.
+
+Maybe: Display a message only once per week, and only after the repository
+has existed for at least one full day. But, this will require storing
+quite a lot of state.
+
+Or: Display a message whenever a removable drive is detected to have been
+connected. I like this, but what about nudging the main repo? Could do it
+every webapp startup, perhaps? **done**
+
+There should be a "No thanks" button that prevents it nudging again for a
+repo. **done**
## git repository repair
@@ -51,3 +117,69 @@ clone the remote, sync from all other remotes, move over .git/config and
.git/annex/objects, and tar up the old broken git repo and `git annex add`
it. This should be automatable and get the user back on their feet. User
could just click a button and have this be done.
+
+This is useful outside git-annex as well, so make it a
+git-recover-repository command.
+
+### detailed design
+
+Run `git fsck` and parse output to find bad objects. **done** Note that
+fsck may fall over and fail to print out all bad objects, when
+files are corrupt. So if the fsck exits nonzero, need to collect all
+bad objects it did find, and:
+
+1. If the local repository contains packs, the packs may be corrupt.
+ So, start by using `git unpack-objects` to unpack all
+ packs it can handle (which may include parts of corrupt packs)
+ back to loose objects. And delete all packs. **done**
+2. Delete all loose corrupt objects. **done**
+
+Repeat until fsck finds no new problems. **done**
+
+Check if there's a remote. If so, and if the bad objects are all
+present on it, can simply get all bad objects from the remote,
+and inject them back into .git/objects to recover:
+
+3. Make a new (bare) clone from the remote.
+ (Note: git does not seem to provide a way to fetch specific missing
+ objects from the remote. Also, cannot use `--reference` against
+ a repository with missing refs. So this seems unavoidably
+ network-expensive.) **done**
+5. Rsync objects over. (Turned out to work better than git-cat-file,
+ because we don't have to walk the graph to add missing objects.)
+ **done**
+6. If each bad object was able to be repaired this way, we're done!
+ (If not, can reuse the clone for getting objects from the next remote.)
+ **done**
+
+If some missing objects cannot be recovered from remotes, find commits in each
+local branch that are broken by all remaining missing objects. Some of this can
+be parsed from git fsck output, but for eg blobs, the commits need to
+be walked to walk the trees, to find trees that refer to the blobs. **done**
+
+For each branch that is affected, look in the reflog and/or `git log
+$branch` to find the last good commit that predates all broken commits. (If
+the head commit of a branch is broken, git log is not going to show
+anything useful, but the reflog can be used to find past refs for the
+branch -- have to first delete the .git/HEAD file if it points to the
+broken ref.) **done**
+
+The basic idea then is to reset the branch to the last good commit
+that was found for it.
+
+* For the HEAD branch, can just reset it. (If no last good commit was found
+ for the HEAD branch, reset it to a dummy empty commit.) This will
+ leave git showing any changes made since then as staged in the index and
+ uncommitted. Or if the index is missing/corrupt, any files in the tree will
+ show as modified and uncommitted. User (or git-annex assistant) can then
+ commit as appropriate. Print appropriate warning message. **done**
+* Special handling for git-annex branch and index. **done**
+* Remote tracking branches can just be removed, and then `git fetch`
+ from the remote, which will re-download missing objects from it and
+ reinstate the tracking branch. **done**
+* For other branches, reset them to last good commit, or delete
+ if none was found. **done**
+* (Decided not to touch tags.)
+
+The index file can still refer to objects that were missing.
+Rewrite to remove them. **done**
diff --git a/doc/design/assistant/disaster_recovery/comment_1_955dc807196863da23aa8dbd15e04364._comment b/doc/design/assistant/disaster_recovery/comment_1_955dc807196863da23aa8dbd15e04364._comment
new file mode 100644
index 000000000..63c7e942d
--- /dev/null
+++ b/doc/design/assistant/disaster_recovery/comment_1_955dc807196863da23aa8dbd15e04364._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://nullroute.eu.org/~grawity/"
+ nickname="Mantas"
+ subject="comment 1"
+ date="2013-10-19T15:50:47Z"
+ content="""
+The restriction on fetching over the Git protocol is, partly, for security reasons – e.g. if one accidentally pushes a commit with private data, and then `push --force`'s a cleaned-up version, Git needs to prevent anyone from downloading the old commit by just giving its SHA1 (e.g. obtained from an IRC/email push notification). So it restricts fetching to the tips of any ref. (I've been told that it could check if the given object is merely *reachable* from any ref, but it doesn't do so for performance reasons.)
+
+git 1.8 has a minor way to relax this requirement – it allows giving a SHA1 to `git fetch` (although I think the protocol already worked this way), and it allows refs to be hidden server-side but still remain fetchable, so in theory there could be a (hidden) ref for every object, for easy fetching...
+"""]]
diff --git a/doc/design/assistant/encrypted_git_remotes.mdwn b/doc/design/assistant/encrypted_git_remotes.mdwn
index 63b7be67a..7d210a292 100644
--- a/doc/design/assistant/encrypted_git_remotes.mdwn
+++ b/doc/design/assistant/encrypted_git_remotes.mdwn
@@ -1,16 +1,17 @@
Encrypted git remotes are now possible
-using [git-remote-gcrypt](https://github.com/blake2-ppc/git-remote-gcrypt).
+using [git-remote-gcrypt](https://github.com/joeyh/git-remote-gcrypt).
There are at least two use cases for this in the assistant:
-* Storing an encrypted git repository on a local drive.
+* Storing an encrypted git repository on a local drive. **done**
* Or on a remote server. This could even allow using github. But more
likely would be a shell server that has git-annex-shell on it so can
also store file contents, and which is not trusted with unencrypted data.
+ **done**
git-remote-gcrypt is already usable with git-annex. What's needed is
to make sure it's installed (ie, get it packaged into distros or embedded
-into git-annex), and make it easy to set up from the webapp.
+into git-annex), and make it easy to set up from the webapp. **done**
Hmm, this will need gpg key creation, so would also be a good opportunity
to make the webapp allow using that for special remotes too.
@@ -18,4 +19,4 @@ to make the webapp allow using that for special remotes too.
One change is needed in git-annex core.. It currently does not support
storing encrypted files on git remotes, only on special remotes. Perhaps
the way to deal with this is to make it consider git-remote-grypt remotes
-to be a special remote type?
+to be a special remote type? **done**
diff --git a/doc/design/assistant/gpgkeys.mdwn b/doc/design/assistant/gpgkeys.mdwn
index 582082f2e..e3f2a3a93 100644
--- a/doc/design/assistant/gpgkeys.mdwn
+++ b/doc/design/assistant/gpgkeys.mdwn
@@ -2,7 +2,7 @@ Currently the assistant sets up a shared encryption key, which is checked
into git, so anyone who gets the repository can decrypt files that are
stored encrypted on special remotes.
-To support using gpg keys in the assistant, we need two things:
+To support using gpg keys in the assistant, we need some things:
1. Help user set up a gpg key if they don't have one. This could be a
special-purpose key dedicated to being used by git-annex. It might be
@@ -11,10 +11,23 @@ To support using gpg keys in the assistant, we need two things:
webapp. Indeed, the password prompt is the main problem here.
Best solution would be to get gpg agent working on all supported
platforms.
-2. Help user learn the gpg keys of people they want to share their repo
+
+ Update: For now, git-annex only assists in generating gpg keys that are
+ intended to only be used to encrypt a repo.
+
+2. After generating a gpg key, back it up. It might be the only way
+ some data is accessible.
+
+ One way I'm considering is generating a QR code
+ of the key, which could be printed to paper. Preliminary results
+ are good; a 4096 bit secret key fits in a QR code (a secret key
+ with many subkeys may not). Debian has command-line utilities that
+ can generate and read such a QR code.
+
+3. Help user learn the gpg keys of people they want to share their repo
with, and give them access. If the public key was recorded in the git-annex
branch, this could be easily determined when sharing repositories with
- friends. Or, use MonkeySphere..
+ friends. Or, use MonkeySphere, or Monkeysign..
-----
diff --git a/doc/design/assistant/polls/2013_user_survey.mdwn b/doc/design/assistant/polls/2013_user_survey.mdwn
new file mode 100644
index 000000000..d1bac0ef8
--- /dev/null
+++ b/doc/design/assistant/polls/2013_user_survey.mdwn
@@ -0,0 +1 @@
+The 2013 git-annex user survey is in progress [[here|/polls/2013]].
diff --git a/doc/design/assistant/polls/Android_default_directory.mdwn b/doc/design/assistant/polls/Android_default_directory.mdwn
index b294dcf78..067a05c82 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 54 "/sdcard/annex" 5 "Whole /sdcard" 4 "DCIM directory (photos and videos only)" 1 "Same as for regular git-annex. ~/annex/"]]
+[[!poll open=yes expandable=yes 61 "/sdcard/annex" 6 "Whole /sdcard" 4 "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 beebeaad8..505c6e3a0 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)" 20 "Tahoe-LAFS" 9 "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)" 23 "Tahoe-LAFS" 10 "OpenStack SWIFT" 31 "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/encryption.mdwn b/doc/design/encryption.mdwn
index 6a380abe1..cc0dd1684 100644
--- a/doc/design/encryption.mdwn
+++ b/doc/design/encryption.mdwn
@@ -103,14 +103,17 @@ use the special remote.
## risks
-A risk of this scheme is that, once the symmetric cipher has been obtained, it
-allows full access to all the encrypted content. This scheme does not allow
-revoking a given gpg key access to the cipher, since anyone with such a key
-could have already decrypted the cipher and stored a copy.
+A risk of this scheme is that, once the symmetric cipher has been
+obtained, it allows full access to all the encrypted content. Indeed
+anyone owning a key that used to be granted access could already have
+decrypted the cipher and stored a copy. While it is in possible to
+remove a key with `keyid-=`, it is designed for a
+[[completely_different_purpose|/encryption]] and does not actually revoke
+access.
If git-annex stores the decrypted symmetric cipher in memory, then there
is a risk that it could be intercepted from there by an attacker. Gpg
-amelorates these type of risks by using locked memory. For git-annex, note
+ameliorates these type of risks by using locked memory. For git-annex, note
that an attacker with local machine access can tell at least all the
filenames and metadata of files stored in the encrypted remote anyway,
and can access whatever content is stored locally.
diff --git a/doc/design/gcrypt.mdwn b/doc/design/gcrypt.mdwn
new file mode 100644
index 000000000..d5b9c064b
--- /dev/null
+++ b/doc/design/gcrypt.mdwn
@@ -0,0 +1,8 @@
+To integrate with git-remote-gcrypt, a key thing is to have a way to map
+from the gcrypt-id of an encrypted repository to a git-annex repository
+uuid.
+
+To do this, we'll make a v5 UUID, feeding in the gcrypt-id.
+The namespace used is itself a v5 UUID, generated using the URL
+namespace and the URL of this page at the time this scheme was
+developed: "http://git-annex.branchable.com/design/gcrypt/"
diff --git a/doc/design/roadmap.mdwn b/doc/design/roadmap.mdwn
new file mode 100644
index 000000000..2b8ccc67f
--- /dev/null
+++ b/doc/design/roadmap.mdwn
@@ -0,0 +1,18 @@
+## roadmap
+
+Now in the
+[sustaining git-annex development](https://campaign.joeyh.name/) year
+(starting September 2013).
+
+* Month 1 [[!traillink assistant/encrypted_git_remotes]]
+* Month 2 [[!traillink assistant/disaster_recovery]]
+* **Month 3 user-driven features and polishing**
+* Month 4 improve special remote interface & git-annex enhancement contest
+* Month 5 [[!traillink assistant/xmpp_security]]
+* Month 6 Windows assistant and webapp
+* Month 7 user-driven features and polishing
+* Month 8 [[!traillink assistant/gpgkeys]] [[!traillink assistant/sshpassword]]
+* Month 9 get [[assistant/Android]] out of beta
+* Month 10 user-driven features and polishing
+* Month 11 [[!traillink assistant/chunks]] [[!traillink assistant/deltas]]
+* Month 12 user-driven features and polishing
diff --git a/doc/devblog.mdwn b/doc/devblog.mdwn
new file mode 100644
index 000000000..aa66b0100
--- /dev/null
+++ b/doc/devblog.mdwn
@@ -0,0 +1,10 @@
+Work on git-annex is [crowdfunded](https://campaign.joeyh.name/).
+Joey blogs about his progress here on a semi-daily basis.
+
+[[!sidebar content="""
+[[!calendar type="month" pages="page(devblog/*)"]]
+[[!calendar type="month" month="-1" pages="page(devblog/*)"]]
+[[!calendar type="month" month="-2" pages="page(devblog/*)"]]
+"""]]
+
+[[!inline pages="page(devblog/*)" show=0]]
diff --git a/doc/devblog/day_-1__drop_dead.mdwn b/doc/devblog/day_-1__drop_dead.mdwn
new file mode 100644
index 000000000..97f7cf1d2
--- /dev/null
+++ b/doc/devblog/day_-1__drop_dead.mdwn
@@ -0,0 +1,5 @@
+Implemented `git annex forget --drop-dead`, which is finally a way to
+remove all references to old repositories that you've marked as dead.
+
+I've still not merged in the `forget` branch, because I developed this
+while slightly ill, and have not tested it very well yet.
diff --git a/doc/devblog/day_-3__.mdwn b/doc/devblog/day_-3__.mdwn
new file mode 100644
index 000000000..fa1473e06
--- /dev/null
+++ b/doc/devblog/day_-3__.mdwn
@@ -0,0 +1,29 @@
+John Millikin came through and fixed that haskell-gnutls segfault
+on OSX that I developed a reproducible test case for the other day.
+It's a bit hard to test, since the bug doesn't always happen, but the
+fix is already deployed for Mountain Lion autobuilder.
+
+However, I then found another way to make haskell-gnutls segfault, more
+reliably on OSX, and even sometimes on Linux. Just entering the wrong XMPP
+password in the assistant can trigger this crash. Hopefully John will work
+his magic again.
+
+---
+
+Meanwhile, I fixed the sync-after-forget problem. Now sync always forces
+its push of the git-annex branch (as does the assistant). I considered but
+rejected having sync do the kind of uuid-tagged branch push that the
+assistant sometimes falls back to if it's failing to do a normal sync. It's
+ugly, but worse, it wouldn't work in the workflow where multiple clients
+are syncing to a central bare repository, because they'd not pull down the
+hidden uuid-tagged branches, and without the assistant running on the
+repository, nothing would ever merge their data into the git-annex branch.
+Forcing the push of synced/git-annex was easy, once I satisfied myself
+that it was always ok to do so.
+
+Also factored out a module that knows about all the different log files
+stored on the git-annex branch, which is all the support infrastructure
+that will be needed to make `git annex forget --drop-dead` work. Since this
+is basically a routing module, perhaps I'll get around to making it use
+a nice bidirectional routing library like
+[Zwaluw](http://hackage.haskell.org/package/Zwaluw) one day.
diff --git a/doc/devblog/day_-4__forgetting.mdwn b/doc/devblog/day_-4__forgetting.mdwn
new file mode 100644
index 000000000..9cec51475
--- /dev/null
+++ b/doc/devblog/day_-4__forgetting.mdwn
@@ -0,0 +1,80 @@
+Yesterday I spent making a release, and shopping for a new laptop, since
+this one is dying. (Soon I'll be able to compile git-annex fast-ish! Yay!)
+And thinking about [[todo/wishlist:_dropping_git-annex_history]].
+
+Today, I added the `git annex forget` command. It's currently been lightly
+tested, seems to work, and is living in the `forget` branch until I gain
+confidence with it. It should be perfectly safe to use, even if it's buggy,
+because you can use `git reflog git-annex` to pull out and revert to an old
+version of your git-annex branch. So if you're been wanting this feature,
+please beta test!
+
+----
+
+I actually implemented something more generic than just forgetting git
+history. There's now a whole mechanism for git-annex doing distributed
+transitions of whatever sort is needed.
+
+There were several subtleties involved in distributed transitions:
+
+First is how to tell when a given transition has already been done on a
+branch. At first I was thinking that the transition log should include the
+sha of the first commit on the old branch that got rewritten. However, that
+would mean that after a single transition had been done, every git-annex
+branch merge would need to look up the first commit of the current branch,
+to see if it's done the transition yet. That's slow! Instead, transitions
+are logged with a timestamp, and as long as a branch contains a transition
+with the same timestamp, it's been done.
+
+A really tricky problem is what to do if the local repository has
+transitioned, but a remote has not, and changes keep being made to the
+remote. What it does so far is incorporate the changes from the remote into
+the index, and re-run the transition code over the whole thing to yeild a
+single new commit. This might not be very efficient (once I write the more
+full-featured transition code), but it lets the local repo keep up with
+what's going on in the remote, without directly merging with it (which
+would revert the transition). And once the remote repository has its
+git-annex upgraded to one that knows about transitions, it will finish up
+the transition on its side automatically, and the two branches will once
+again merge.
+
+Related to the previous problem, we don't want to keep trying to merge
+from a remote branch when it's not yet transitioned. So a blacklist is
+used, of untransitioned commits that have already been integrated.
+
+One really subtle thing is that when the user does a transition more
+complicated than `git annex forget`, like the `git annex forget --dead`
+that I need to implement to forget dead remotes, they're not just telling
+git-annex to forget whatever dead remotes it knows right now. They're
+actually telling git-annex to perform the transition one time on every
+existing clone of the repository, at some point in the future. Repositories
+with unfinished transitions could hang around for years, and at some future
+point when git-annex runs in the repository again, it would merge in the
+current state of the world, and re-do the transition. So you might tell it
+to forget dead remotes today, and then the very repository you ran that in
+later becomes dead, and a long-slumbering repo wakes up and forgets about
+the repo that started the whole process! I hope users don't find this
+massively confusing, but that's how the implementation works right now.
+
+----
+
+I think I have at least two more days of work to do to finish up this
+feature.
+
+* I still need to add some extra features like forgetting about dead remotes,
+ and forgetting about keys that are no longer present on any remote.
+
+* After `git annex forget`, `git annex sync`
+ will fail to push the synced/annex branch to remotes, since the branch
+ is no longer a fast-forward of the old one. I will probably fix this by
+ making `git annex sync` do a fallback push of a unique branch in this case,
+ like the assistant already does. Although I may need to adjust that code
+ to handle this case, too..
+
+* For some reason the automatic transitioning code triggers
+ a "(recovery from race)" commit. This is certianly a bug somewhere,
+ because you can't have a race with only 1 participant.
+
+----
+
+Today's work was sponsored by Richard Hartmann.
diff --git a/doc/devblog/day_-4__forgetting/comment_1_f3cc7a25af4c59fda3924c737a789419._comment b/doc/devblog/day_-4__forgetting/comment_1_f3cc7a25af4c59fda3924c737a789419._comment
new file mode 100644
index 000000000..4c926c1af
--- /dev/null
+++ b/doc/devblog/day_-4__forgetting/comment_1_f3cc7a25af4c59fda3924c737a789419._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Sandra.Devil"
+ ip="77.172.73.184"
+ subject="New laptop"
+ date="2013-09-01T09:38:32Z"
+ content="""
+What is the new laptop you are going to use? Specs please :)
+"""]]
diff --git a/doc/devblog/day_10__lazy_Sunday.mdwn b/doc/devblog/day_10__lazy_Sunday.mdwn
new file mode 100644
index 000000000..aa6a70918
--- /dev/null
+++ b/doc/devblog/day_10__lazy_Sunday.mdwn
@@ -0,0 +1,23 @@
+Fixed a typo that broke automatic youtube video support in `addurl`.
+
+----
+
+Now there's an easy way to get an overview of how close your repository
+is to meeting the configured numcopies settings (or when it exceeds them).
+
+<pre>
+# time git annex status .
+[...]
+numcopies stats:
+ numcopies +0: 6686
+ numcopies +1: 3793
+ numcopies +3: 3156
+ numcopies +2: 2743
+ numcopies -1: 1242
+ numcopies -4: 1098
+ numcopies -3: 1009
+ numcopies +4: 372
+</pre>
+
+This does make `git annex status` slow when run on a large directory tree,
+so --fast disables that.
diff --git a/doc/devblog/day_11__webapp_encrypted_drives.mdwn b/doc/devblog/day_11__webapp_encrypted_drives.mdwn
new file mode 100644
index 000000000..677c02491
--- /dev/null
+++ b/doc/devblog/day_11__webapp_encrypted_drives.mdwn
@@ -0,0 +1,12 @@
+Now the webapp can set up encrypted repositories on removable drives.
+
+[[assistant/encryptdrive.png]]
+
+This UI needs some work, and the button to create a new key is not wired
+up. Also if you have no gpg agent installed, there will be lots of password
+prompts at the console.
+
+Forked git-remote-gcrypt to fix a bug. Hopefully my patch will be merged;
+for now I recommend installing my worked version.
+
+Today's work was sponsored by Romain Lenglet.
diff --git a/doc/devblog/day_12__gpg_key_generation.mdwn b/doc/devblog/day_12__gpg_key_generation.mdwn
new file mode 100644
index 000000000..c79c49f85
--- /dev/null
+++ b/doc/devblog/day_12__gpg_key_generation.mdwn
@@ -0,0 +1,35 @@
+I decided to keep gpg key generation very simple for now. So it generates a
+special-purpose key that is only intended to be used by git-annex. It
+hardcodes some key parameters, like RSA and 4096 bits (maximum recommended
+by gpg at this time). And there is no password on the key, although you can
+of course edit it and set one. This is because anyone who can access the
+computer to get the key can also look at the files in your git-annex
+repository. Also because I can't rely on gpg-agent being installed
+everywhere. All these simplifying assumptions may be revisited later, but
+are enough for now for someone who doesn't know about gpg (so doesn't
+have a key already) and just wants an encrypted repo on a
+removable drive.
+
+Put together a simple UI to deal with gpg taking quite a while to
+generate a key ...
+
+[[assistant/genkey.png]]
+
+[[assistant/repoinfo.png]]
+
+Then I had to patch git-remote-gcrypt again, to have a per-remote
+signingkey setting, so that these special-purpose keys get used for signing
+their repo.
+
+Next, need to add support for adding an existing gcrypt repo as a remote
+(assuming it's encrypted to an available key). Then, gcrypt repos on ssh
+servers..
+
+----
+
+Also dealt with build breakage caused by a new version of the Haskell DNS
+library.
+
+----
+
+Today's work was sponsored by Joseph Liu.
diff --git a/doc/devblog/day_12__gpg_key_generation/comment_1_48cdfe3bd71fb348ae05fd90e8cf1dab._comment b/doc/devblog/day_12__gpg_key_generation/comment_1_48cdfe3bd71fb348ae05fd90e8cf1dab._comment
new file mode 100644
index 000000000..d7a6a8631
--- /dev/null
+++ b/doc/devblog/day_12__gpg_key_generation/comment_1_48cdfe3bd71fb348ae05fd90e8cf1dab._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://nullroute.eu.org/~grawity/"
+ nickname="Mantas"
+ subject="comment 1"
+ date="2013-09-18T05:00:12Z"
+ content="""
+Should be \"PGP\" or *at least* \"GnuPG\".
+"""]]
diff --git a/doc/devblog/day_13__encrypted_sneakernet_working.mdwn b/doc/devblog/day_13__encrypted_sneakernet_working.mdwn
new file mode 100644
index 000000000..777da255a
--- /dev/null
+++ b/doc/devblog/day_13__encrypted_sneakernet_working.mdwn
@@ -0,0 +1,13 @@
+Spent basically all of today getting the assistant to be able to handle
+gcrypt special remotes that already exist when it's told to add a USB
+drive. This was quite tricky! And I did have to skip handling gcrypt repos
+that are not git-annex special remotes.
+
+Anyway, it's now almost easy to set up an encrypted sneakernet
+using a USB drive and some computers running the webapp. The only part
+that the assistant doesn't help with is gpg key management.
+
+Plan is to make a release on Friday, and then try to also add support for
+encrypted git repositories on remote servers. Tomorrow I will try to get
+through some of the communications backlog that has been piling up while I
+was head down working on gcrypt.
diff --git a/doc/devblog/day_14__gcrypt_refinements_and_OOM_fixes.mdwn b/doc/devblog/day_14__gcrypt_refinements_and_OOM_fixes.mdwn
new file mode 100644
index 000000000..2ff1d16dd
--- /dev/null
+++ b/doc/devblog/day_14__gcrypt_refinements_and_OOM_fixes.mdwn
@@ -0,0 +1,26 @@
+Spent a few hours improving gcrypt in some minor ways, including adding a
+--check option that the assistant can use to find out if a given repo is
+encrypted with dgit, and also tell if the necessary gpg key is available to
+decrypt it. Also merged in a fix to support subkeys, developed by a
+git-annex user who is the first person I've heard from who is using gcrypt.
+I don't want to maintain gcrypt, so I am glad its author has shown up
+again today.
+
+Got mostly caught up on backlog. The main bug I was able to track down
+today is git-annex using a lot of memory in certian repositories. This
+turns out to have happened when a really large file was committed right
+intoo to the git repository (by mistake or on purpose). Some parts of
+git-annex buffer file contents in memory while trying to work out if
+they're git-annex keys. Fixed by making it first check if a file in git is
+marked as a symlink. Which was really hard to do!
+
+At least 4 people ran into this bug, which makes me suspect that lots of
+people are messing up when using direct mode (probably due to not reading
+the documentation, or having `git commit -a` hardwired into their fingers,
+and forcing git to commit large files into their repos, rather than having
+git-annex manage them. Implementing [[todo/direct_mode_guard]] seems more
+urgent now.
+
+----
+
+Today's work was sponsored by Amitai Schlair.
diff --git a/doc/devblog/day_15-17__Android_rebuild.mdwn b/doc/devblog/day_15-17__Android_rebuild.mdwn
new file mode 100644
index 000000000..758e2d097
--- /dev/null
+++ b/doc/devblog/day_15-17__Android_rebuild.mdwn
@@ -0,0 +1,67 @@
+Made a release on Friday. But I had to rebuild the OSX and Linux standalone
+builds today to fix a bug in them.
+
+Spent the past **three days** redoing the whole Android build environment.
+I've been progressively moving from my first hacked up Android build env to
+something more reproducible and sane. Finally I am at the point where I can
+run a shell script (well, actually, 3 shell scripts) and get an Android
+build chroot. It's still not immune to breaking when new versions of
+haskell libs are uploaded, but this is much better, and should be
+maintainable going forward.
+
+This is a good starting point for getting git-annex into the F-Droid app
+store, or for trying to build with a newer version of the Android SDK and
+NDK, to perhaps get it working on Android 4.3. (Eventually. I am so sick
+of building Android stuff right now..)
+
+Friday was all spent struggling to get ghc-android to build. I had not built
+it successfully since February. I finally did,
+on Saturday, and I have made my own fork of it which builds using a
+known-good snapshot of the current development version of ghc. Building
+this in a Debian stable chroot means that there should be no possibility
+that upstream changes will break the build again.
+
+With ghc built, I moved on to building all the haskell libs git-annex
+needs. Unfortunately my build script for these also has stopped working
+since I made it in April. I failed to pin every package at a defined
+version, and things broke.
+
+So, I redid the build script, and updated all the haskell libs to the
+newest versions while I was at it. I have decided not to pin the library
+versions (at least until I find a foolproof way to do it), so this new
+script will break in the future, but it should break in a way I can fix up
+easily by just refreshing a patch.
+
+The new ghc-android build has a nice feature of at least being able to
+compile Template Haskell code (though still not run it at compile time.
+This made the patching needed in the Haskell libs quite a lot less. Offset
+somewhat by me needing to make general fixes to lots of libs to build with
+ghc head. Including some fun with `==#` changing its type from `Bool` to
+`Int#`. In all, I think I removed around 2.5 thousand lines of patches!
+(Only 6 thousand lines to go...)
+
+Today I improved ghc-android some more so it cross builds several C libraries
+that are needed to build several haskell libraries needed for XMPP.
+I had only ever built those once, and done it by hand, and very hackishly.
+Now they all build automatically too.
+
+And, I put together a script that builds the debian stable chroot and
+installs ghc-android.
+
+And, I hacked on the EvilSplicer (which is sadly still needed) to
+work with the new ghc/yesod/etc.
+
+At this point, I have git-annex successfully building, including the APK!
+
+----
+
+In a bored hour waiting for a compile, I also sped up `git annex add`
+on OSX by I think a factor of 10. Using cryptohash for hash calculation
+now, when external hash programs are not available. It's still a few
+percentage points slower than external hash programs, or I'd use it by
+default.
+
+----
+
+This period of important drudgery was sponsored by an unknown bitcoin
+user, and by Bradley Unterrheiner and Andreas Olsson.
diff --git a/doc/devblog/day_19__moving_on.mdwn b/doc/devblog/day_19__moving_on.mdwn
new file mode 100644
index 000000000..7f4cd8244
--- /dev/null
+++ b/doc/devblog/day_19__moving_on.mdwn
@@ -0,0 +1,37 @@
+Finished moving the Android autobuilder over to the new clean build
+environment. Tested the Android app, and it still works. Whew!
+
+There's a small chance that the issue with the Android app not working on
+Android 4.3 has been fixed by this rebuild. I doubt it, but perhaps someone
+can download the daily build and give it another try..
+
+----
+
+I have 7 days left in which I'd like to get remote gcrypt repositories
+working in the assistant. I think that should be fairly easy, but a
+prerequisite for it is making git-annex-shell support being run on a gcrypt
+repository. That's needed so that the assistant's normal locked down ssh
+key setup can also be used for gcrypt repositories.
+
+At the same time, not all gcrypt endpoints will have git-annex-shell
+installed, and it *seems* to make sense to leave in the existing support
+for running raw rsync and git push commands against such a repository. So
+that's going to add some complication.
+
+It will also complicate git-annex-shell to support gcrypt repos. Basically,
+everything it does in git-annex repos will need to be reimplemented in
+gcrypt repositories. Generally in a more simple form; for example it
+doesn't need to (and can't) update location logs in a gcrypt repo.
+
+----
+
+I also need to find a good UI to present the three available choices
+(unencrypted git, encrypted git, encrypted rsync) when setting up a repo
+on a ssh server. I don't want to just remove the encrypted rsync option,
+because it's useful when using xmpp to sync the git repo, and is simpler to
+set up since it uses shared encryption rather than gpg public keys.
+
+My current thought is to offer just 2 choices, encrypted and non-encrypted.
+If they choose encrypted, offer a choice of shared encryption or encrypting
+to a specific key. I think I can word this so it's pretty clear what the
+tradeoffs are.
diff --git a/doc/devblog/day_19__moving_on/comment_1_870106f671f9a055b81e6fc83e0850b5._comment b/doc/devblog/day_19__moving_on/comment_1_870106f671f9a055b81e6fc83e0850b5._comment
new file mode 100644
index 000000000..b0ed97bcf
--- /dev/null
+++ b/doc/devblog/day_19__moving_on/comment_1_870106f671f9a055b81e6fc83e0850b5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmW0kg4uiMIhSHeVuvJFyo2VYMl7Qoej0s"
+ nickname="Chris"
+ subject="comment 1"
+ date="2013-09-23T20:58:45Z"
+ content="""
+The new version of the Android apk doesn't work for me on my Nexus 4.
+"""]]
diff --git a/doc/devblog/day_19__moving_on/comment_2_fad055c8860385ac6c012f897c96408f._comment b/doc/devblog/day_19__moving_on/comment_2_fad055c8860385ac6c012f897c96408f._comment
new file mode 100644
index 000000000..f2e754b3a
--- /dev/null
+++ b/doc/devblog/day_19__moving_on/comment_2_fad055c8860385ac6c012f897c96408f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 2"
+ date="2013-09-24T07:11:31Z"
+ content="""
+Yeah, no joy on Cyanogenmod 10.2(Android 4.3).
+
+Would be pretty surprising if it had worked.
+"""]]
diff --git a/doc/devblog/day_19__moving_on/comment_3_69e47d612159587f080ab761566d1830._comment b/doc/devblog/day_19__moving_on/comment_3_69e47d612159587f080ab761566d1830._comment
new file mode 100644
index 000000000..206fdd852
--- /dev/null
+++ b/doc/devblog/day_19__moving_on/comment_3_69e47d612159587f080ab761566d1830._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnR6E5iUghMWdUGlbA9CCs8DKaoigMjJXw"
+ nickname="Efraim"
+ subject="not working on my nexus 4 either"
+ date="2013-09-24T07:37:28Z"
+ content="""
+terminal output reads:
+
+Falling back to hardcoded app location; cannot find expected files in /data/app-lib
+
+git annex webapp
+
+u0_a124@mako:/sdcard/git-annex.home $ git annex webpp
+
+CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?)
+
+1|u0_a124@mako:/sdcard/git-annex.home $
+"""]]
diff --git a/doc/devblog/day_1__inauspicious_beginning.mdwn b/doc/devblog/day_1__inauspicious_beginning.mdwn
new file mode 100644
index 000000000..b14f763bb
--- /dev/null
+++ b/doc/devblog/day_1__inauspicious_beginning.mdwn
@@ -0,0 +1,11 @@
+I try hard to keep this devblog about git-annex development and not me.
+However, it is a shame that what I wanted to be the beginning of my first
+real month of work funded by the new campaign has been marred by my home's
+internet connection being taken out by a lightning strike, and by illness.
+Nearly back on my feet after that, and waiting for my new laptop to
+finally get here.
+
+Today's work: Finished up the `git annex forget` feature and merged it in.
+Fixed the bug that was causing the commit race detection code to
+incorrectly fire on the commit made by the transition code. Few other bits
+and pieces.
diff --git a/doc/devblog/day_1__inauspicious_beginning/comment_1_cc4dea43caf3126c6f814b589b701d70._comment b/doc/devblog/day_1__inauspicious_beginning/comment_1_cc4dea43caf3126c6f814b589b701d70._comment
new file mode 100644
index 000000000..03e3fec6d
--- /dev/null
+++ b/doc/devblog/day_1__inauspicious_beginning/comment_1_cc4dea43caf3126c6f814b589b701d70._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="rjc"
+ ip="86.22.66.200"
+ subject="laptop"
+ date="2013-09-04T21:42:52Z"
+ content="""
+Are you retiring your Dell mini?
+
+What kind of laptop are you getting?
+"""]]
diff --git a/doc/devblog/day_20__gcrypt_and_git-annex-shell.mdwn b/doc/devblog/day_20__gcrypt_and_git-annex-shell.mdwn
new file mode 100644
index 000000000..0e4142b7c
--- /dev/null
+++ b/doc/devblog/day_20__gcrypt_and_git-annex-shell.mdwn
@@ -0,0 +1,14 @@
+Added support for gcrypt remotes to git-annex-shell. Now gcrypt special
+remotes probe when they are set up to see if the remote system has a
+suitable git-annex-shell, and if so all commands are sent to it. Kept the
+direct rsync mode working as a fallback.
+
+It turns out I made a bad decision when first adding gcrypt support to
+git-annex. To make implementation marginally easier, I decided to not
+put objects inside the usual `annex/objects` directory in a gcrypt remote.
+But that lack of consistency would have made adding support to
+git-annex-shell a lot harder. So, I decided to change this. Which
+means that anyone already using gcrypt with git-annex will need to
+[[manually_move_files_around|upgrades/gcrypt]].
+
+Today's work was sponsored by Tobias Nix.
diff --git a/doc/devblog/day_21__bugfix_day.mdwn b/doc/devblog/day_21__bugfix_day.mdwn
new file mode 100644
index 000000000..a913fce56
--- /dev/null
+++ b/doc/devblog/day_21__bugfix_day.mdwn
@@ -0,0 +1,5 @@
+Did various bug fixes and followup today. Amazing how a day can vanish that
+way. Made 4 actual improvements.
+
+I still have 46 messages in unanswered backlog. Although only 8 of
+the are from this month.
diff --git a/doc/devblog/day_22__gcrypt_on_rsync.net.mdwn b/doc/devblog/day_22__gcrypt_on_rsync.net.mdwn
new file mode 100644
index 000000000..2c5951795
--- /dev/null
+++ b/doc/devblog/day_22__gcrypt_on_rsync.net.mdwn
@@ -0,0 +1,20 @@
+Being still a little unsure of the UI and complexity
+for configuring gcrypt on ssh servers, I thought I'd start today with the
+special case of gcrypt on rsync.net. Since rsync.net allows running some git
+commands, gcrypt can be used to make encrypted git repositories on it.
+
+Here's the UI I came up with. It's complicated a bit by needing to explain
+the tradeoffs between the rsync and gcrypt special remotes.
+
+[[!img /assistant/rsync.net.encryption.png]]
+
+This works fine, but I did not get a chance to add support for enabling
+existing gcrypt repos on rsync.net. Anyway, most of the changes to make
+this work will also make it easier to add general support for gcrypt on ssh
+servers.
+
+Also spent a while fixing a bug in git-remote-gcrypt. Oddly
+`gpg --list-keys --fast-list --fingerprint` does not show the fingerprints
+of some keys.
+
+Today's work was sponsored by Cloudier - Thomas Djärv.
diff --git a/doc/devblog/day_23__GNU_day.mdwn b/doc/devblog/day_23__GNU_day.mdwn
new file mode 100644
index 000000000..4f5b25ca7
--- /dev/null
+++ b/doc/devblog/day_23__GNU_day.mdwn
@@ -0,0 +1,23 @@
+Worked on making the assistant able to merge in existing encrypted
+git repositories from rsync.net.
+
+This had two parts. First, making the webapp UI where you click to enable a
+known special remote work with these encrypted repos. Secondly, handling
+the case where a user knows they have an encrypted repository on rsync.net,
+so enters in its hostname and path, but git-annex doesn't know about that
+special remote. The second case is important, for example, when the
+encrypted repository is a backup and you're restoring from it. It wouldn't
+do for the assistant, in that case, to make a *new* encrypted repo and
+push it over top of your backup!
+
+Handling that was a neat trick. It has to do quite a lot of probing, including
+downloading the whole encrypted git repo so it can decrypt it and merge it,
+to find out about the special remote configuration used for it. This all
+works with just 2 ssh connections, and only 1 ssh password prompt max.
+
+Next, on to generalizing this rsync.net specific code to work with
+arbitrary ssh servers!
+
+----
+
+Today's work was made possible by [RMS's vision 30 years ago](http://article.olduse.net/771@mit-eddie.UUCP).
diff --git a/doc/devblog/day_24__nearly_done_with_gcrypt.mdwn b/doc/devblog/day_24__nearly_done_with_gcrypt.mdwn
new file mode 100644
index 000000000..22d3fa70b
--- /dev/null
+++ b/doc/devblog/day_24__nearly_done_with_gcrypt.mdwn
@@ -0,0 +1,23 @@
+So close to being done with gcrypt support.. But still not quite there.
+
+Today I made the UI changes to support gcrypt when setting up a repository
+on a ssh server, and improved the probing and data types so it can tell
+which options the server supports. Fairly happy with how that is turning
+out.
+
+Have not yet hooked up the new buttons to make gcrypt repos. While I was
+testing that my changes didn't break other stuff, I found a bug in the
+webapp that caused it to sometimes fail to transfer one file to/from a
+remote that was just added, because the transferrer process didn't know
+about the new remote yet, and crashed (and was restarted knowing about it,
+so successfully sent any other files). So got sidetracked on fixing that.
+
+Also did some work to make the gpg bundled with git-annex on OSX be
+compatable with the config files written by MacGPG. At first I was going to
+hack it to not crash on the options it didn't support, but it turned out
+that upgrading to version 1.4.14 actually fixed the problem that was making
+it build without support for DNS.
+
+----
+
+Today's work was sponsored by Thomas Hochstein.
diff --git a/doc/devblog/day_25__finishing_up_gcrypt.mdwn b/doc/devblog/day_25__finishing_up_gcrypt.mdwn
new file mode 100644
index 000000000..9666282d0
--- /dev/null
+++ b/doc/devblog/day_25__finishing_up_gcrypt.mdwn
@@ -0,0 +1,25 @@
+Long day, but I did finally finish up with gcrypt support. More or less.
+
+Got both creating and enabling existing gcrypt repositories on ssh servers
+working in the webapp. (But I ran out of time to make it detect when the
+user is manually entering a gcrypt repo that already exists. Should be easy
+so maybe tomorrow.)
+
+Fixed several bugs in git-annex's gcrypt support that turned up in testing.
+Made git-annex ensure that a gcrypt repository does not have
+receive.denyNonFastForwards set, because gcrypt relies on always forcing
+the push of the branch it stores its manifest on. Fixed a bug in
+`git-annex-shell recvkey` when it was receiving a file from an annex in
+direct mode.
+
+Also had to add a new `git annex shell gcryptsetup` command, which is
+needed to make setting up a gcrypt repository work when the assistant
+has set up a locked-down ssh key that can only run git-annex-shell. Painted
+myself into a bit of a corner there.
+
+And tested, tested, tested. So many possibilities and edge cases in this
+part of the code..
+
+----
+
+Today's work was sponsored by Hendrik Müller Hofstede.
diff --git a/doc/devblog/day_26__gcrypt_really_done_this_time.mdwn b/doc/devblog/day_26__gcrypt_really_done_this_time.mdwn
new file mode 100644
index 000000000..347e4be5f
--- /dev/null
+++ b/doc/devblog/day_26__gcrypt_really_done_this_time.mdwn
@@ -0,0 +1,17 @@
+Did I say it would be easy to make the webapp detect when a gcrypt repository
+already existed and enable it? Well, it wasn't exactly hard, but it took
+over 300 lines of code and 3 hours..
+
+So, gcrypt support is done for now. The glaring omission is gpg key
+management for sharing gcrypt repositories between machines and/or people.
+But despite that, I think it's solid, and easy to use, and covers some
+great use cases.
+
+Pushed out a release.
+
+Now I really need to start thinking about
+[[design/assistant/disaster_recovery]].
+
+----
+
+Today's work was sponsored by Dominik Wagenknecht.
diff --git a/doc/devblog/day_27__locking_fun.mdwn b/doc/devblog/day_27__locking_fun.mdwn
new file mode 100644
index 000000000..ef0c4131f
--- /dev/null
+++ b/doc/devblog/day_27__locking_fun.mdwn
@@ -0,0 +1,49 @@
+Started the day by getting the builds updated for yesterday's release. This
+included making it possible to build git-annex with Debian stable's version
+of cryptohash. Also updated the Debian stable backport to the previous
+release.
+
+----
+
+The [[design/roadmap]] has this month devoted to improving git-annex's
+support for recovering from disasters, broken repos, and so on. Today I've
+been working on the first thing on [[the_list|design/assistant/disaster_recovery]],
+stale git index lock files.
+
+It's unfortunate that git uses simple files for locking, and does not use
+fcntl or flock to prevent the stale lock file problem. Perhaps they want
+it to work on broken NFS systems? The problem with that line of thinking is
+is means all non-broken systems end up broken by stale lock files. Not a
+good tradeoff IMHO.
+
+There are actually two lock files that can end up stale when using
+git-annex; both `.git/index.lock` and `.git/annex/index.lock`. Today I
+concentrated on the latter, because I saw a way to prevent it from ever
+being a problem. All updates to that index file are done by git-annex when
+committing to the git-annex branch. git-annex already uses fcntl locking
+when manipulating its journal. So, that can be extended to also cover
+committing to the git-annex branch, and then the git `index.lock` file
+is irrelevant, and can just be removed if it exists when a commit is
+started.
+
+To ensure this makes sense, I used the type system to prove that the journal
+locking was in effect everywhere I need it to be. Very happy I was able to
+do that, although I am very much a novice at using the type system for
+interesting proofs. But doing so made it very easily to build up to a point
+where I could unlink the `.git/annex/index.lock` and be sure it was safe to do
+that.
+
+----
+
+What about stale `.git/index.lock` files? I don't think it's appropriate
+for git-annex to generally recover from those, because it would change
+regular git command line behavior, and risks breaking something. However, I
+do want the assistant to be able to recover if such a file exists when it
+is starting up, since that would prevent it from running. Implemented that
+also today, although I am less happy with the way the assistant detects
+when this lock file is stale, which is somewhat heuristic (but should work
+even on networked filesystems with multiple writing machines).
+
+----
+
+Today's work was sponsored by Torbjørn Thorsen.
diff --git a/doc/devblog/day_27__locking_fun/comment_1_0eb247235fbf8f563934f3548e1d2e10._comment b/doc/devblog/day_27__locking_fun/comment_1_0eb247235fbf8f563934f3548e1d2e10._comment
new file mode 100644
index 000000000..261fa005c
--- /dev/null
+++ b/doc/devblog/day_27__locking_fun/comment_1_0eb247235fbf8f563934f3548e1d2e10._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="News page not updated"
+ date="2013-10-04T09:38:21Z"
+ content="""
+Already for the last three or so releases the News page wasn't updated. :-( I think many people (including me) used this page to check if their version is uptodate. Posting the newest version there motivates people to try the very latest which seems very desirable for the git-annex development.
+"""]]
diff --git a/doc/devblog/day_27__locking_fun/comment_2_e8b1dfe1b0641e031d05733448b7bc8b._comment b/doc/devblog/day_27__locking_fun/comment_2_e8b1dfe1b0641e031d05733448b7bc8b._comment
new file mode 100644
index 000000000..c073f735a
--- /dev/null
+++ b/doc/devblog/day_27__locking_fun/comment_2_e8b1dfe1b0641e031d05733448b7bc8b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.243"
+ subject="comment 2"
+ date="2013-10-04T20:13:37Z"
+ content="""
+Sorry about that. It turns out my release script was broken.
+"""]]
diff --git a/doc/devblog/day_27__locking_fun/comment_3_b67f8ef4ed42b49c8c2e6c4e53163b16._comment b/doc/devblog/day_27__locking_fun/comment_3_b67f8ef4ed42b49c8c2e6c4e53163b16._comment
new file mode 100644
index 000000000..39c840e84
--- /dev/null
+++ b/doc/devblog/day_27__locking_fun/comment_3_b67f8ef4ed42b49c8c2e6c4e53163b16._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm5iosFbL2By7UFeViqkc6v-hoAtqILeDA"
+ nickname="Laszlo"
+ subject="comment 3"
+ date="2013-10-07T09:17:30Z"
+ content="""
+Hi,
+
+Can you please enlighten us mere mortals, when this stale file locking problem occcurs?
+The typical situation. I tried to google up, and read locking files on wikipedia, but
+still have no exact knowledge when the \"stale\" part happens.
+
+How it gets outdated without noticing?
+
+Best,
+ Laszlo
+
+"""]]
diff --git a/doc/devblog/day_27__locking_fun/comment_4_0759644baf26b75f4e48dbb387d725a5._comment b/doc/devblog/day_27__locking_fun/comment_4_0759644baf26b75f4e48dbb387d725a5._comment
new file mode 100644
index 000000000..cbeae8b78
--- /dev/null
+++ b/doc/devblog/day_27__locking_fun/comment_4_0759644baf26b75f4e48dbb387d725a5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 4"
+ date="2013-10-12T23:31:16Z"
+ content="""
+Git simply creates a file as a lock file, and does not use any form of locking on it, so if the git process dies for any reason before it gets a chance to remove the lock file, a stale lock file remains, and future git commands will fall over it.
+
+It's really surprisingly bad..
+"""]]
diff --git a/doc/devblog/day_28__lazy_saturday.mdwn b/doc/devblog/day_28__lazy_saturday.mdwn
new file mode 100644
index 000000000..c2237b28b
--- /dev/null
+++ b/doc/devblog/day_28__lazy_saturday.mdwn
@@ -0,0 +1,17 @@
+Finished up the automatic recovery from stale lock files. Turns out git
+has quite a few lock files; the assistant handles them all.
+
+Improved URL and WORM keys so the filenames used for them
+will always work on FAT (which has a crazy assortmeny of illegal
+characters). This is a tricky thing to deal with without breaking backwards
+compatability, so it's only dealt with when creating new URL or WORM keys.
+
+-----
+
+I think my next step in this disaster recovery themed month will be adding
+periodic incremental fsck to the assistant. `git annex fsck` can already
+do an incremental fsck, so this should mostly involve adding a user
+interface to the webapp to configure when it should fsck. For example, you
+might choose to run it for up 1 hour every night, with a goal of checking
+all your files once per month. Also will need to make the assistant do
+something useful when fsck finds a bad file (ie, queue a re-download).
diff --git a/doc/devblog/day_29__scheduling.mdwn b/doc/devblog/day_29__scheduling.mdwn
new file mode 100644
index 000000000..98c928bf8
--- /dev/null
+++ b/doc/devblog/day_29__scheduling.mdwn
@@ -0,0 +1,10 @@
+Spent most of the day building some generic types for scheduling recurring
+events. Not sure if rolling my own was a good idea, but that's what I did.
+
+In the incrementalfsck branch, I have hooked this up in `git-annex vicfg`,
+which now accepts and parses scheduled events like
+"fsck self every day at any time for 60 minutes" and
+"fsck self on day 1 of weeks divisible by 2 at 3:45 for 120 minutes", and
+stores them in the git-annex branch. The exact syntax is of course subject
+to change, but also doesn't matter a whole lot since the webapp will have
+a better interface.
diff --git a/doc/devblog/day_2__new_laptop.mdwn b/doc/devblog/day_2__new_laptop.mdwn
new file mode 100644
index 000000000..000800742
--- /dev/null
+++ b/doc/devblog/day_2__new_laptop.mdwn
@@ -0,0 +1,8 @@
+Now I can build git-annex twice as fast! And a typical incremental build is
+down to 10 seconds, from 51 seconds.
+
+Spent a productive evening working with Guilhem to get his encryption
+patches reviewed and merged. Now there is a way to remove revoked gpg keys,
+and there is a new encryption scheme available that uses public key
+encryption by default rather than git-annex's usual approach. That's not
+for everyone, but it is a good option to have available.
diff --git a/doc/devblog/day_2__new_laptop/comment_1_93447dbd4eb09b4db96770644ea663cb._comment b/doc/devblog/day_2__new_laptop/comment_1_93447dbd4eb09b4db96770644ea663cb._comment
new file mode 100644
index 000000000..15d19b0c9
--- /dev/null
+++ b/doc/devblog/day_2__new_laptop/comment_1_93447dbd4eb09b4db96770644ea663cb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm5iosFbL2By7UFeViqkc6v-hoAtqILeDA"
+ nickname="Laszlo"
+ subject="comment 1"
+ date="2013-09-05T15:07:44Z"
+ content="""
+out of curiosity, what laptop model have you choosen finally?
+
+Laszlo
+"""]]
diff --git a/doc/devblog/day_2__new_laptop/comment_2_e1d022b25f2c16dbe72db07ad4b10a2d._comment b/doc/devblog/day_2__new_laptop/comment_2_e1d022b25f2c16dbe72db07ad4b10a2d._comment
new file mode 100644
index 000000000..052597521
--- /dev/null
+++ b/doc/devblog/day_2__new_laptop/comment_2_e1d022b25f2c16dbe72db07ad4b10a2d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="24.159.78.54"
+ subject="comment 2"
+ date="2013-09-06T18:02:08Z"
+ content="""
+Lenovo Yoga 11s
+"""]]
diff --git a/doc/devblog/day_30__cronner.mdwn b/doc/devblog/day_30__cronner.mdwn
new file mode 100644
index 000000000..f368407ca
--- /dev/null
+++ b/doc/devblog/day_30__cronner.mdwn
@@ -0,0 +1,17 @@
+Lots of progress from yesterday's modest start of building data types for
+scheduling. Last night I wrote the hairy calendar code to calculate when
+next to run a scheduled event. (This is actually quite superior to `cron`,
+which checks every second to see if it should run each event!) Today I
+built a "Cronner" thread that handles spawning threads to handle each
+scheduled event. It even notices when changes have been made to the its
+schedule and stops/starts event threads appropriately.
+
+Everything is hooked up, building, and there's a good chance it works
+without too many bugs, but while I've tested all the pure code (mostly
+automatically with quickcheck properties), I have not run the Cronner
+thread at all. And there is some tricky stuff in there, like noticing
+that the machine was asleep past when it expected to wake up, and deciding
+if it should still run a scheduled event, or should wait until next time.
+So tomorrow we'll see..
+
+Today's work was sponsored by Ethan Aubin.
diff --git a/doc/devblog/day_30__cronner/comment_1_53dfd9310e92f5225db52a13e20a46d4._comment b/doc/devblog/day_30__cronner/comment_1_53dfd9310e92f5225db52a13e20a46d4._comment
new file mode 100644
index 000000000..dc0c7dfe1
--- /dev/null
+++ b/doc/devblog/day_30__cronner/comment_1_53dfd9310e92f5225db52a13e20a46d4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://nullroute.eu.org/~grawity/"
+ nickname="Mantas"
+ subject="comment 1"
+ date="2013-10-09T06:04:15Z"
+ content="""
+The SysV Unix *cron* learned this same thing [in 1979][1].
+
+[1]: http://en.wikipedia.org/wiki/Cron#Multi-user_capability
+"""]]
diff --git a/doc/devblog/day_30__cronner/comment_2_f98357c6f7a6da23873ac27c2e1e9638._comment b/doc/devblog/day_30__cronner/comment_2_f98357c6f7a6da23873ac27c2e1e9638._comment
new file mode 100644
index 000000000..0fc310a78
--- /dev/null
+++ b/doc/devblog/day_30__cronner/comment_2_f98357c6f7a6da23873ac27c2e1e9638._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 2"
+ date="2013-10-11T17:07:24Z"
+ content="""
+However, if you strace a traditional cron, you will be sad at how it's implemented. So much statting of files, and checking of entries every second..
+
+0 polling or redundant calulcation in my code!
+"""]]
diff --git a/doc/devblog/day_31__blah.mdwn b/doc/devblog/day_31__blah.mdwn
new file mode 100644
index 000000000..672adbfd3
--- /dev/null
+++ b/doc/devblog/day_31__blah.mdwn
@@ -0,0 +1,17 @@
+Some neat stuff is coming up, but today was a pretty blah day for me.
+I did get the Cronner tested and working (only had a few little bugs). But
+I got stuck for quite a while making the Cronner stop `git-annex fsck`
+processes it was running when their jobs get removed. I had some code to do
+this that worked when run standalone, but not when run from git-annex.
+
+After considerable head-scratching, I found out this was due to
+`forkProcess` masking aync exceptions, which seems to be probably
+[a bug](http://ghc.haskell.org/trac/ghc/ticket/8433). Luckily was able to
+work around it. Async exceptions continue to strike me as the worst part of
+the worst part of Haskell (the worst part being exceptions in general).
+
+Was more productive after that.. Got the assistant to automatically queue
+re-downloads of any files that fsck throws out due to having bad contents,
+and made the webapp display an alert while fscking is running, which will
+go to the page to configure fsck schedules. Now all I need to do is
+build the UI of that page.
diff --git a/doc/devblog/day_32__fsck_config_UI.mdwn b/doc/devblog/day_32__fsck_config_UI.mdwn
new file mode 100644
index 000000000..66f4cfd54
--- /dev/null
+++ b/doc/devblog/day_32__fsck_config_UI.mdwn
@@ -0,0 +1,20 @@
+Last night, built this nice user interface for configuring periodic fscks:
+
+[[!img assistant/fsckconfig.png]]
+
+Rather happy that that whole UI needed only 140 lines of code to build.
+Though rather more work behind it, as seen in this blog..
+
+Today I added some support to git-annex for smart fscking of remotes.
+So far only git repos on local drives, but this should get extended to
+git-annex-shell for ssh remotes. The assistant can also run periodic fscks
+of these.
+
+Still need to test that, and find a way to make a removable drive's fsck
+job run when the drive gets plugged in. That's where picking "any time"
+will be useful; it'll let you configure fscking of removable drives when
+they're available, as long as they have not been fscked too recently.
+
+----
+
+Today's work was sponsored by Georg Bauer.
diff --git a/doc/devblog/day_33__fsck_on_connect.mdwn b/doc/devblog/day_33__fsck_on_connect.mdwn
new file mode 100644
index 000000000..36c226008
--- /dev/null
+++ b/doc/devblog/day_33__fsck_on_connect.mdwn
@@ -0,0 +1,9 @@
+Built everything needed to run a fsck when a remote gets connected. Have
+not tested it; only testing is blocking merging the incrementalfsck branch
+now.
+
+Also updated the OSX and Android builds to use a new gpg release (denial of
+service security fix), and updated the Debian backport, and did a small
+amount of bug fixing. I need to do several more days of bug fixing once
+I get this incremental fsck feature wrapped up before moving on to recovery
+of corrupt git repositories.
diff --git a/doc/devblog/day_34__wrapping_up_fsck.mdwn b/doc/devblog/day_34__wrapping_up_fsck.mdwn
new file mode 100644
index 000000000..b66708605
--- /dev/null
+++ b/doc/devblog/day_34__wrapping_up_fsck.mdwn
@@ -0,0 +1,7 @@
+Fixed a lot of bugs in the assistant's fsck handling today, and merged
+it into master. There are some enhancments that could be added to it,
+including fscking ssh remotes via git-annex-shell and adding the ability to
+schedule events to run every 30 days instead of on a specific day of the
+month. But enough on this feature for now.
+
+Today's work was sponsored by Daniel Brockman.
diff --git a/doc/devblog/day_35__anacron_and_bugfixing.mdwn b/doc/devblog/day_35__anacron_and_bugfixing.mdwn
new file mode 100644
index 000000000..af021d576
--- /dev/null
+++ b/doc/devblog/day_35__anacron_and_bugfixing.mdwn
@@ -0,0 +1,15 @@
+While I said I was done with fsck scheduling yesterday, I ended up adding
+one more feature to it today: Full anacron style scheduling. So a fsck can
+be scheduled to run once per week, or month, or year, and it'll run the
+fsck the next time it's available after that much time has passed. The nice
+thing about this is I didn't have to change Cronner *at all* to add this,
+just improved the Recurrance data type and the code that calculates when
+to run events.
+
+Rest of the day I've been catching up on some bug reports. The main bug I
+fixed caused git-annex on Android to hang when adding files. This turns out
+to be because it's using a new (unreleased) version of git, and
+`git check-attr -z` output format has changed in an incompatable way.
+
+I am currently 70 messages behind, which includes some ugly looking bug
+reports, so I will probably continue with this over the next couple days.
diff --git a/doc/devblog/day_36__bugfixing.mdwn b/doc/devblog/day_36__bugfixing.mdwn
new file mode 100644
index 000000000..0e31d54bf
--- /dev/null
+++ b/doc/devblog/day_36__bugfixing.mdwn
@@ -0,0 +1 @@
+Productive day, but I'm wiped out. Backlog down to 51.
diff --git a/doc/devblog/day_37__long_day.mdwn b/doc/devblog/day_37__long_day.mdwn
new file mode 100644
index 000000000..7882a746d
--- /dev/null
+++ b/doc/devblog/day_37__long_day.mdwn
@@ -0,0 +1,6 @@
+A long day of bugfixing. Split into two major parts. First I got back to a
+bug I filed in August to do with the assistant misbehaving when run in a
+subdirectory of a git repository, and did a nice type-driven fix of the
+underlying problem (that also found and fixed some other related bugs that
+would not normally occur). Then, spent 4 hours in Windows purgatory working
+around crazy path separator issues.
diff --git a/doc/devblog/day_38__starting_git_repo_repair.mdwn b/doc/devblog/day_38__starting_git_repo_repair.mdwn
new file mode 100644
index 000000000..3808abe38
--- /dev/null
+++ b/doc/devblog/day_38__starting_git_repo_repair.mdwn
@@ -0,0 +1,11 @@
+Goal for the rest of the month is to build automatic recovery git
+repository corruption. Spent today investigating how to do it and came up
+with a fairly [[detailed_design|design/assistant/disaster_recovery]]. It
+will have two parts, first to handle repository problems that can be fixed
+by fetching objects from remotes, and secondly to recover from problems
+where data never got sent to a remote, and has been lost.
+
+In either case, the assistant should be able to detect the problem and
+automatically recover well enough to keep running. Since this also affects
+non-git-annex repositories, it will also be available in a standalone
+`git-recover-repository` command.
diff --git a/doc/devblog/day_38__starting_git_repo_repair/comment_1_321468d9686db5dde072500bdaeb7d29._comment b/doc/devblog/day_38__starting_git_repo_repair/comment_1_321468d9686db5dde072500bdaeb7d29._comment
new file mode 100644
index 000000000..3a1ce7851
--- /dev/null
+++ b/doc/devblog/day_38__starting_git_repo_repair/comment_1_321468d9686db5dde072500bdaeb7d29._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="Idea: checksum left-over files in .git/annex/tmp for potential recovery"
+ date="2013-10-19T12:30:58Z"
+ content="""
+This just came to mind when I thought about the second case. I noticed quite often that files were left in .git/annex/tmp (seen on OS X) and sometimes these are the only instances of files on this particular computer.
+
+(It's on my todo list to file several bug reports about this and other issues on OS X...)
+"""]]
diff --git a/doc/devblog/day_39__git-recover-repository.mdwn b/doc/devblog/day_39__git-recover-repository.mdwn
new file mode 100644
index 000000000..f2c552eef
--- /dev/null
+++ b/doc/devblog/day_39__git-recover-repository.mdwn
@@ -0,0 +1,54 @@
+Built a `git-recover-repository` command today. So far it only does the
+detection and deletion of corrupt objects, and retrieves them from remotes
+when possible. No handling yet of missing objects that cannot be recovered
+from remotes.
+
+Here's a couple of sample runs where I do bad things to the git
+repository and it fixes them:
+
+<pre>
+joey@darkstar:~/tmp/git-annex>chmod 644 .git/objects/pack/*
+joey@darkstar:~/tmp/git-annex>echo > .git/objects/pack/pack-a1a770c1569ac6e2746f85573adc59477b96ebc5.pack
+joey@darkstar:~/tmp/git-annex>~/src/git-annex/git-recover-repository
+Running git fsck ...
+git fsck found a problem but no specific broken objects. Perhaps a corrupt pack file? Unpacking all pack files.
+fatal: early EOF
+Unpacking objects: 100% (148/148), done.
+Unpacking objects: 100% (354/354), done.
+Re-running git fsck to see if it finds more problems.
+Re-running git fsck to see if it finds more problems.
+Initialized empty Git repository in /home/joey/tmp/tmprepo.0/.git/
+Trying to recover missing objects from remote origin
+Successfully recovered repository!
+You should run "git fsck" to make sure, but it looks like
+everything was recovered ok.
+</pre>
+
+----
+
+<pre>
+joey@darkstar:~/tmp/git-annex>chmod 644 .git/objects/00/0800742987b9f9c34caea512b413e627dd718e
+joey@darkstar:~/tmp/git-annex>echo > .git/objects/00/0800742987b9f9c34caea512b413e627dd718e
+joey@darkstar:~/tmp/git-annex>~/src/git-annex/git-recover-repository
+Running git fsck ...
+error: unable to unpack 000800742987b9f9c34caea512b413e627dd718e header
+error: inflateEnd: stream consistency error (no message)
+error: unable to unpack 000800742987b9f9c34caea512b413e627dd718e header
+error: inflateEnd: stream consistency error (no message)
+git fsck found 1 broken objects. Unpacking all pack files.
+removing 1 corrupt loose objects
+Re-running git fsck to see if it finds more problems.
+Re-running git fsck to see if it finds more problems.
+Initialized empty Git repository in /home/joey/tmp/tmprepo.0/.git/
+Trying to recover missing objects from remote origin
+Successfully recovered repository!
+You should run "git fsck" to make sure, but it looks like
+everything was recovered ok.
+</pre>
+
+Works great! I need to move this and `git-union-merge` out of the git-annex
+source tree sometime.
+
+----
+
+Today's work was sponsored by Francois Marier.
diff --git a/doc/devblog/day_3__gcrypt_uuids.mdwn b/doc/devblog/day_3__gcrypt_uuids.mdwn
new file mode 100644
index 000000000..3182aca63
--- /dev/null
+++ b/doc/devblog/day_3__gcrypt_uuids.mdwn
@@ -0,0 +1,63 @@
+Started work on [gcrypt](https://github.com/blake2-ppc/git-remote-gcrypt)
+support.
+
+The first question is, should git-annex leave it up to gcrypt to transport
+the data to the encrypted repository on a push/pull? gcrypt hooks into git
+nicely to make that just work. However, if I go this route, it limits
+the places the encrypted git repositores can be stored to regular git
+remotes (and rsync). The alternative is to somehow use gcrypt to
+generate/consume the data, but use the git-annex special remotes to store
+individual files. Which would allow for a git repo stored on S3, etc.
+For now, I am going with the simple option, but I have not ruled out
+trying to make the latter work. It seems it would need changes to gcrypt
+though.
+
+Next question: Given a remote that uses gcrypt, how do I determine the
+annex.uuid of that repository. I found a nice solutuon to this. gcrypt has
+its own gcrypt-id, and I convert it to a UUID in a
+[[reproducible, and even standards-compliant way|design/gcrypt]]. So
+the same encrypted remote will automatically get the same annex.uuid
+wherever it's used. Nice. Does mean that git-annex cannot find a uuid
+until `git pull` or `git push` has been used, to let gcrypt get the
+gcrypt-id. Implemented that.
+
+The next step is actually making git-annex store data on gcrypt remotes.
+And it needs to store it encrypted of course. It seems best to avoid
+needing a `git annex initremote` for these gcrypt remotes, and just have
+git-annex automatically encrypt data stored on them. But I don't
+know. Without initializing them like a special remote is, I'm limited to
+using the gpg keys that gcrypt is configured to encrypt to, and cannot use
+the regular git-annex hybrid encryption scheme. Also, I need to generate
+and store a nonce anyway to HMAC ecrypt keys. (Or modify gcrypt
+to put enough entropy in gcrypt-id that I can use it?)
+
+Another concern I have is that gcrypt's own encryption scheme is simply
+to use a list of public keys to encrypt to. It would be nicer if the
+full set of git-annex encryption schemes could be used. Then the webapp
+could use shared encryption to avoid needing to make the user set up a gpg
+key, or hybrid encryption could be used to add keys later, etc.
+
+But I see why gcrypt works the way it does. Otherwise, you can't make an
+encrypted repo with a friend set as one of the particpants and have them be
+able to git clone it. Both hybrid and shared encryption store a secret
+inside the repo, which is not accessible if it's encrypted using that
+secret. There are use cases where not being able to blindly clone a gcrypt
+repo would be ok. For example, you use the assistant to pair with a friend
+and then set up an encrypted repo in the cloud for both of you to use.
+
+Anyway, for now, I will need to deal with
+setting up gpg keys etc in the assistant. I don't want to tackle
+full [[design/assistant/gpgkeys]] yet. Instead, I think I will start by
+adding some simple stuff to the assistant:
+
+* When adding a USB drive, offer to encrypt the repository on the drive
+ so that only you can see it.
+* When adding a ssh remote make a similar offer.
+* Add a UI to add an arbitrary git remote with encryption.
+ Let the user paste in the url to an empty remote they have,
+ which could be to eg github. (In most cases this won't be used for
+ annexed content..)
+* When the user has no gpg key, prompt to set one up. (Securely!)
+* Maybe have an interface to add another gpg key that can access the gcrypt
+ repo. Note that this will need to re-encrypt and re-push the whole
+ git history.
diff --git a/doc/devblog/day_40__another_fine_mess.mdwn b/doc/devblog/day_40__another_fine_mess.mdwn
new file mode 100644
index 000000000..dfe5bc564
--- /dev/null
+++ b/doc/devblog/day_40__another_fine_mess.mdwn
@@ -0,0 +1,15 @@
+Solid day of working on repository recovery. Got `git recover-repository
+--force` working, which involves fixing up branches that refer to missing
+objects. Mostly straightforward traversal of git commits, trees, blobs, to
+find when a branch has a problem, and identify an old version of it that
+predates the missing object. (Can also find them in the reflog.)
+
+The main complication turned out to be that `git branch -D` and `git
+show-ref` don't behave very well when the commit objects pointed to by refs
+are themselves missing. And git has no low-level plumbing that avoids
+falling over these problems, so I had to write it myself.
+
+Testing has turned up one unexpected problem: Git's index can itself refer
+to missing objects, and that will break future commits, etc. So I need to
+find a way to validate the index, and when it's got problems,
+either throw it out, or possibly recover some of the staged data from it.
diff --git a/doc/devblog/day_41__onward.mdwn b/doc/devblog/day_41__onward.mdwn
new file mode 100644
index 000000000..fd393b734
--- /dev/null
+++ b/doc/devblog/day_41__onward.mdwn
@@ -0,0 +1,17 @@
+I think that git-recover-repository is ready now. Made it deal with the
+index file referencing corrupt objects. The best approach I could think of
+for that is to just remove those objects from the index, so the user can
+re-add files from their work tree after recovery.
+
+Now to integrate this git repository repair capability into the git-annex
+assistant. I decided to run `git fsck` as part of a scheduled
+repository consistency check. It may also make sense for the assistant to
+notice when things are going wrong, and suggest an immediate check. I've
+started on the webapp UI to run a repository repair when fsck detects
+problems.
+
+[[!img /assistant/brokenrepositoryalert.png]]
+
+[[!img /assistant/repairrepository.png]]
+
+[[!meta title="the user interface I hope noone ever sees"]]
diff --git a/doc/devblog/day_41__onward/comment_1_a716c7b5a9ea3c949ff047cfb4e9a0a4._comment b/doc/devblog/day_41__onward/comment_1_a716c7b5a9ea3c949ff047cfb4e9a0a4._comment
new file mode 100644
index 000000000..0457a4bf0
--- /dev/null
+++ b/doc/devblog/day_41__onward/comment_1_a716c7b5a9ea3c949ff047cfb4e9a0a4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="aarone"
+ ip="2607:f470:8:d008:290:f5ff:fec3:a9e6"
+ subject="Email alert"
+ date="2013-10-22T21:23:24Z"
+ content="""
+I have at least one git-annex repository where I seldom open the web UI, but rather have the assistant humming along in the background. I think for my use case it would be best to receive an email notification that the assistant had detected a problem, which would prompt me to open the web UI and perform the recovery.
+"""]]
diff --git a/doc/devblog/day_41__onward/comment_2_33149e424cd5f03fac376288bcc4dfdc._comment b/doc/devblog/day_41__onward/comment_2_33149e424cd5f03fac376288bcc4dfdc._comment
new file mode 100644
index 000000000..fd26f9290
--- /dev/null
+++ b/doc/devblog/day_41__onward/comment_2_33149e424cd5f03fac376288bcc4dfdc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="excellent idea"
+ date="2013-10-22T22:13:58Z"
+ content="""
+Added to my todo. I think it would require the system have an MTA though, I really don't want git-annex to grow to the point it can send email. ;)
+"""]]
diff --git a/doc/devblog/day_41__onward/comment_3_3b07503bd79089ad3ce3ddd7535ed116._comment b/doc/devblog/day_41__onward/comment_3_3b07503bd79089ad3ce3ddd7535ed116._comment
new file mode 100644
index 000000000..1116b4d1b
--- /dev/null
+++ b/doc/devblog/day_41__onward/comment_3_3b07503bd79089ad3ce3ddd7535ed116._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://jasonwoof.com/"
+ nickname="JasonWoof"
+ subject="Please check if it needs help from the user first"
+ date="2013-10-23T23:30:10Z"
+ content="""
+Awesome that you're working on recovery, and recovery automation!
+
+Please only bother the user if there is a serious problem _and_ it can't be fixed without their help. Otherwise I fear people will learn to ignore your dialog boxes, like they do most dialog boxes. If you want to notify your user that some hard drive corruption happened (and it's been fixed already) then put a little yellow/orange line across somewhere with a warning message.
+
+When I read to the part about how it can (probably) be fixed automatically, I got a flash of annoyance and thought \"well, then fix it automatically, why are you bothering me?\"
+
+Please (if you aren't already) check if it can be automatically fixed without help from the user before telling the user about it. Then you can say \"The data to fix this could not be reached, please plug in another repo or something.\"
+"""]]
diff --git a/doc/devblog/day_42__repair_milestone.mdwn b/doc/devblog/day_42__repair_milestone.mdwn
new file mode 100644
index 000000000..61a1bea27
--- /dev/null
+++ b/doc/devblog/day_42__repair_milestone.mdwn
@@ -0,0 +1,35 @@
+The webapp now fully handles repairing damage to the repository.
+
+Along with all the git repository repair stuff already built, I added
+additional repairs of the git-annex branch and git-annex's index file.
+That was pretty easy actually, since git-annex already handles merging
+git-annex branches that can sometimes be quite out of date. So when git repo
+repair has to throw away recent changes to the git-annex branch, it just
+effectively becomes out of date. Added a `git annex fsck --fast` run to
+ensure that the git-annex branch reflects the current state of the
+repository.
+
+When the webapp runs a repair, it first stops the assistant from committing
+new files. Once the repair is done, that's started back up, and it runs a
+startup scan, which is just what is needed in this sitation; it will add
+any new files, as well as any old files that the git repository damange
+caused to be removed from the index.
+
+Also made `git annex repair` run the git repository repair code,
+for those with a more command-line bent. It can be used in non-git-annex
+repos too!
+
+----
+
+So, I'm nearly ready to wrap up working on disaster recovery. Lots has been
+accomplished this month. And I have put off making a release for entirely
+too long!
+
+The big missing piece is repair of git remotes located on removable drive.
+I may make a release before adding that, but removable drives are probably
+where git repository corruption is most likely to occur, so I certainly
+need to add that.
+
+----
+
+Today's work was sponsored by Scott Robinson.
diff --git a/doc/devblog/day_43__bugfix_day.mdwn b/doc/devblog/day_43__bugfix_day.mdwn
new file mode 100644
index 000000000..ad150f512
--- /dev/null
+++ b/doc/devblog/day_43__bugfix_day.mdwn
@@ -0,0 +1,26 @@
+Got well caught up on bug fixes and traffic. Backlog is down to 40.
+
+Made the assistant wait for a few seconds before doing the startup
+scan when it's autostarted, since the desktop is often busy starting
+up at that same time.
+
+Fixed an ugly bug with chunked webdav and directory special remotes
+that caused it to not write a "chunkcount" file when storing data,
+so it didn't think the data was present later. I was able to make it
+recover nicely from that mistake, by probing for what chunks are actually
+present.
+
+Several people turn out to have had problems with `git annex sync` not
+working because receive.denyNonFastForwards is enabled. I made the webapp
+not enable it when setting up a ssh repository, and I made `git annex sync`
+print out a hint about this when it's failed to push. (I don't think this
+problem affects the assistant's own syncing.)
+
+Made the assistant try to repair a damaged git repository without
+prompting. It will only prompt when it fails to fetch all the lost
+objects from remotes.
+
+Glad to see that others have managed to
+[get git-annex to build on Max OS X 10.9](http://git-annex.branchable.com/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/#comment-8e8ee5e50506a6fde029d236f4809df8).
+Now I just need someone to offer up a ssh account on that OS, and I could
+set up an autobuilder for it.
diff --git a/doc/devblog/day_44__automatic_removable_drive_repair.mdwn b/doc/devblog/day_44__automatic_removable_drive_repair.mdwn
new file mode 100644
index 000000000..444cf5f2e
--- /dev/null
+++ b/doc/devblog/day_44__automatic_removable_drive_repair.mdwn
@@ -0,0 +1,16 @@
+Finally got the assistant to repair git repositories on removable drives,
+or other local repos. Mostly this happens entirely automatically, whatever
+data in the git repo on the drive has been corrupted can just be copied
+to it from `~/annex/.git`.
+
+And, the assistant will launch a git fsck of such a repo whenever it fails
+to sync with it, so the user does not even need to schedule periodic fscks.
+Although it's still a good idea, since some git repository problems don't
+prevent syncing from happening.
+
+Watching git annex heal problems like this is quite cool!
+
+One thing I had to defer till later is repairing corrupted gcrypt
+repositories. I don't see a way to do it without deleting all the objects
+in the gcrypt repository, and re-pushing everything. And even doing that
+is tricky, since the `gcrypt-id` needs to stay the same.
diff --git a/doc/devblog/day_45__command_line.mdwn b/doc/devblog/day_45__command_line.mdwn
new file mode 100644
index 000000000..fa6a7ffc7
--- /dev/null
+++ b/doc/devblog/day_45__command_line.mdwn
@@ -0,0 +1,9 @@
+All command line stuff today..
+
+Added --want-get and --want-drop, which can be used to test preferred content settings
+of a repository. For example `git annex find --in . --want-drop` will list the same
+files that `git annex drop --auto` would try to drop. (Also renamed `git annex content`
+to `git annex wanted`.)
+
+Finally laid to rest problems with `git annex unannex` when multiple files point to the
+same key. It's a lot slower, but I'll stop getting bug reports about that.
diff --git a/doc/devblog/day_46__wrapping_up_the_month.mdwn b/doc/devblog/day_46__wrapping_up_the_month.mdwn
new file mode 100644
index 000000000..c6045178c
--- /dev/null
+++ b/doc/devblog/day_46__wrapping_up_the_month.mdwn
@@ -0,0 +1,18 @@
+Spent today reviewing my [[plans_for_the_month|assistant/disaster_recovery]]
+and filling in a couple of missing peices.
+
+Noticed that I had forgotten to make repository repair clean up any stale
+git locks, despite writing that code at the beginning of the month, and
+added that in.
+
+Made the webapp notice when a repository that is being used does not have
+any consistency checks configured, and encourage the user to set up checks.
+This happens when the assistant is started (for the local repository),
+and when removable drives containing repositories are plugged in. If the
+reminders are annoying, they can be disabled with a couple clicks.
+
+And I think that just about wraps up the month. (If I get a chance, I would
+still like to add recovery of git-remote-gcrypt encrypted git repositories.)
+
+My [[design/roadmap]] has next month dedicated to user-driven features
+and polishing and bugfixing.
diff --git a/doc/devblog/day_47__fell_off_the_blogging_wagon.mdwn b/doc/devblog/day_47__fell_off_the_blogging_wagon.mdwn
new file mode 100644
index 000000000..fd312a0d8
--- /dev/null
+++ b/doc/devblog/day_47__fell_off_the_blogging_wagon.mdwn
@@ -0,0 +1,3 @@
+Low activity the past couple of days. Released a new version of git-annex
+yesterday. Today fixed three bugs (including a local pairing one that was
+pretty compicated) and worked on getting caught up with traffic.
diff --git a/doc/devblog/day_48__direct_mode_guard_design.mdwn b/doc/devblog/day_48__direct_mode_guard_design.mdwn
new file mode 100644
index 000000000..bc2dbe316
--- /dev/null
+++ b/doc/devblog/day_48__direct_mode_guard_design.mdwn
@@ -0,0 +1,29 @@
+I've been investigating ways to implement a [[/todo/direct_mode_guard]].
+Preventing a stray `git commit -a` or `git add` doing bad things in a
+direct mode repository seems increasingly important.
+
+First, considered moving `.git`, so git won't know it's a git repository.
+This doesn't seem *too* hard to do, but there will certianly be unexpected
+places that assume `.git` is the directory name.
+
+I dislike it more and more as I think about it though, because it moves
+direct mode git-annex toward being entirely separate from git, and I don't
+want to write my own version control system. Nor do I want to complicate
+the git ecosystem with tools needing to know about git-annex to work in
+such a repository.
+
+So, I'm happy that one of the other ideas I tried today seems quite
+promising. Just set core.bare=true in a direct mode repository. This nicely
+blocks all git commands that operate on the working tree from doing
+anything, which is just what's needed in direct mode, since they don't know
+how to handle the direct mode files. But it lets all git commands and other
+tools that don't touch the working tree continue to be used. You can even
+run `git log file` in such a repository (surprisingly!)
+
+It also gives an easy out for anyone who really wants to use git commands
+that operate on the work tree of their direct mode repository, by just
+passing `-c core.bare=false`. And it's really easy to implement in
+git-annex too -- it can just notice if a repo has core.bare and
+annex.direct both set, and pass that parameter to every git command it
+runs. I should be able to get by with only modifying 2 functions to
+implement this.
diff --git a/doc/devblog/day_48__direct_mode_guard_design/comment_1_ec0147ccc55bad3a38652383f4098a65._comment b/doc/devblog/day_48__direct_mode_guard_design/comment_1_ec0147ccc55bad3a38652383f4098a65._comment
new file mode 100644
index 000000000..3f297d505
--- /dev/null
+++ b/doc/devblog/day_48__direct_mode_guard_design/comment_1_ec0147ccc55bad3a38652383f4098a65._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="70.82.37.38"
+ subject="awesome!"
+ date="2013-11-05T15:50:15Z"
+ content="""
+`core.bare=true` seems like an awesome idea!!! it probably means this can be factored into current installs without any change too right?
+"""]]
diff --git a/doc/devblog/day_49__direct_mode_guard_implementation.mdwn b/doc/devblog/day_49__direct_mode_guard_implementation.mdwn
new file mode 100644
index 000000000..ebc0dd494
--- /dev/null
+++ b/doc/devblog/day_49__direct_mode_guard_implementation.mdwn
@@ -0,0 +1,14 @@
+Long, long day coding up the direct mode guard today. About 90% of the fun
+is dealing with `receive.denyCurrentBranch` not preventing pushes that
+change the current branch, now that core.bare is set in direct mode.
+My current solution to this involves using a special branch when using
+direct mode, which nothing will ever push to (hopefully). A much nicer
+solution would be to use a `update` hook to deny pushes of the current
+branch -- but there are filesystems where repos cannot have git hooks.
+
+The test suite is falling over, but the `directguard` branch otherwise
+seems usable.
+
+----
+
+Today's work was sponsored by Carlo Matteo Capocasa.
diff --git a/doc/devblog/day_49__direct_mode_guard_implementation/comment_1_3ebe5c3f708070f164ecaf36b79f7bfc._comment b/doc/devblog/day_49__direct_mode_guard_implementation/comment_1_3ebe5c3f708070f164ecaf36b79f7bfc._comment
new file mode 100644
index 000000000..2a77d6d81
--- /dev/null
+++ b/doc/devblog/day_49__direct_mode_guard_implementation/comment_1_3ebe5c3f708070f164ecaf36b79f7bfc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 1"
+ date="2013-11-06T11:50:00Z"
+ content="""
+Thanks, Joey! I am very proud!
+"""]]
diff --git a/doc/devblog/day_4__unexpected_windows_day.mdwn b/doc/devblog/day_4__unexpected_windows_day.mdwn
new file mode 100644
index 000000000..6a448c3fc
--- /dev/null
+++ b/doc/devblog/day_4__unexpected_windows_day.mdwn
@@ -0,0 +1,10 @@
+Woke up with a pretty solid plan for gcrypt. It will be structured as a
+separate special remote, so `initremote` will be needed, with a gitrepo=
+parameter (unless the remote already exists). git-annex will then set up
+the git remote, including pushing to it (needed to get a gcrypt-id).
+
+Didn't feel up to implementing that today. Instead I expectedly spent
+the day doing mostly Windows work, including setting up a VM on my new
+laptop for development. Including a ssh server in Windows, so I can
+script local builds and tests on Windows without ever having to
+touch the desktop. Much better!
diff --git a/doc/devblog/day_50__grab_bag.mdwn b/doc/devblog/day_50__grab_bag.mdwn
new file mode 100644
index 000000000..e38ec065c
--- /dev/null
+++ b/doc/devblog/day_50__grab_bag.mdwn
@@ -0,0 +1,34 @@
+Started by tracking down a strange bug that was apparently
+ubuntu-specific and caused git-annex branch changes to get committed to
+master. Root cause turned out to failing to recover from an
+exception. I'm kicking myself about that, because I remember looking at the
+code where the bug was at least twice before and thinking "hmm, should add
+exception handling here? nah..". Exceptions are horrible.
+
+Made a release with a fix for that and a few minor other accumulated
+changes since last Friday's release. The pain point of this release is to
+fix building without the webapp (so it will propigate to Debian testing,
+etc). This release does not include the direct mode guard, so I'll have a
+few weeks until the next release to get that tested.
+
+Fixed the test suite in `directguard`. This branch is now nearly ready to
+merge to master, but one command that is badly needed in guarded direct
+mode is "git status". So I am planning to rename "git annex status" to
+"git annex info", and make "git annex status" display something similar
+to "git status".
+
+Also took half an hour and added optional [[EKG]] support to git-annex.
+This is a Haskell library that can add a terrific monitoring console web
+UI to any program in 2 lines of code. Here we can see the git-annex
+webapp using resources at startup, followed in a few seconds by the
+assistant's startup scan of the repository.
+
+[[!img ekg/ekg.png]]
+
+BTW, Kevin tells me that the machine used to build git-annex for OSX is
+going to be upgraded to 10.9 soon. So, hopefully I'll be making autobuilds
+of that. I may have to stop the 10.8.2 autobuilds though.
+
+----
+
+Today's work was sponsored by [Protonet](http://protonet.info/).
diff --git a/doc/devblog/day_50__grab_bag/comment_1_01846f6494fe843889391fd09fd127a0._comment b/doc/devblog/day_50__grab_bag/comment_1_01846f6494fe843889391fd09fd127a0._comment
new file mode 100644
index 000000000..1c1717180
--- /dev/null
+++ b/doc/devblog/day_50__grab_bag/comment_1_01846f6494fe843889391fd09fd127a0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="OS X builds"
+ date="2013-11-07T05:12:13Z"
+ content="""
+Joey, were you not interested in my offer of an OS X build server that I've posted elsewhere on this list, and also in e-mail to you?
+"""]]
diff --git a/doc/devblog/day_50__grab_bag/comment_2_12736014aa2c1af81e4b83072505e7d5._comment b/doc/devblog/day_50__grab_bag/comment_2_12736014aa2c1af81e4b83072505e7d5._comment
new file mode 100644
index 000000000..70d7b7cd1
--- /dev/null
+++ b/doc/devblog/day_50__grab_bag/comment_2_12736014aa2c1af81e4b83072505e7d5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 2"
+ date="2013-11-07T16:01:00Z"
+ content="""
+John, must have missed that; can't see to find it anywhere..
+"""]]
diff --git a/doc/devblog/day_51__direct_mode_guard_finished.mdwn b/doc/devblog/day_51__direct_mode_guard_finished.mdwn
new file mode 100644
index 000000000..9c637aa94
--- /dev/null
+++ b/doc/devblog/day_51__direct_mode_guard_finished.mdwn
@@ -0,0 +1,6 @@
+Finished the direct mode guard, including the new `git annex status`
+command.
+
+Spent the rest of the day working on various bug fixes. One of them turned
+into rather a lot of work to make the webapp's UI better for git
+remotes that do not have an annex.uuid.
diff --git a/doc/devblog/day_52__slowly_but_surely.mdwn b/doc/devblog/day_52__slowly_but_surely.mdwn
new file mode 100644
index 000000000..01019355b
--- /dev/null
+++ b/doc/devblog/day_52__slowly_but_surely.mdwn
@@ -0,0 +1,5 @@
+Been chipping away at my backlog of messages, and it's down to 23 items.
+
+Finally managed to get ghc to build with a newer version of the NDK.
+This *might* mean a solution to git-annex on Android 4.2. I
+[need help with testing](http://git-annex.branchable.com/bugs/git-annex_broken_on_Android_4.3/#comment-90b82735cd6090a7765f423b743fffd3).
diff --git a/doc/devblog/day_54__android_bisection_minions.mdwn b/doc/devblog/day_54__android_bisection_minions.mdwn
new file mode 100644
index 000000000..ed86c68d0
--- /dev/null
+++ b/doc/devblog/day_54__android_bisection_minions.mdwn
@@ -0,0 +1,9 @@
+Finally found the [root cause](http://git-annex.branchable.com/bugs/git-annex_broken_on_Android_4.3/#comment-452bee7d0a816300ccb4a34f9758134e)
+of the Android 4.3/4.4 trouble, and a fix is now in place!
+
+As a bonus, it looks like I've fixed a problem accessing the
+environment on Android that had been worked around in an ugly way before.
+
+Big thanks to my remote hands Michael Alan, Sören, and subito. All
+told they ran 19 separate tests to help me narrow down this tricky
+problem, often repeating long command lines on software keyboards.
diff --git a/doc/devblog/day_54__android_bisection_minions/comment_1_bea8fbe2b87d4a4865b92fa796298fa0._comment b/doc/devblog/day_54__android_bisection_minions/comment_1_bea8fbe2b87d4a4865b92fa796298fa0._comment
new file mode 100644
index 000000000..0f8e58827
--- /dev/null
+++ b/doc/devblog/day_54__android_bisection_minions/comment_1_bea8fbe2b87d4a4865b92fa796298fa0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmW0kg4uiMIhSHeVuvJFyo2VYMl7Qoej0s"
+ nickname="Chris"
+ subject="Woot!"
+ date="2013-11-12T15:52:48Z"
+ content="""
+Thanks for getting this fixed. I'm about to go on a long plane ride, and this will make it a lot easier for me to put movies on my tablet.
+"""]]
diff --git a/doc/devblog/day_55__fireside_porting.mdwn b/doc/devblog/day_55__fireside_porting.mdwn
new file mode 100644
index 000000000..c7469d953
--- /dev/null
+++ b/doc/devblog/day_55__fireside_porting.mdwn
@@ -0,0 +1,22 @@
+Annoyingly, the Android 4.3 fix breaks git-annex on Android 4.0 (probably
+through 4.2), so I now have two separate builds of the Android app.
+
+---
+
+Worked on Windows porting today. I've managed to get the assistant
+and watcher (but not yet webapp) to build on Windows.
+The `git annex transferrer` interface needs POSIX stuff, and seems to be
+the main thing that will need porting for Windows for the assistant to
+work, besides of course file change detection. For that, I've hooked up
+[Win32-notify](http://hackage.haskell.org/package/Win32-notify).
+
+So the watcher might work on Windows.
+At least in theory. Problem is, while all the code builds ok,
+it fails to link:
+
+ ghc.exe: could not execute: C:\Program Files (x86)\Haskell Platform\2012.4.0.0\lib/../mingw/bin/gcc.exe
+
+I wonder if this is case of too many parameters being passed?
+
+This happens both on the autobuilder and on my laptop, so I'm stuck here.
+Oh well, I was not planning to work on this anyway until February...
diff --git a/doc/devblog/day_55__fireside_porting/comment_1_d690a52db82f9594d99ae65fe51e1f1a._comment b/doc/devblog/day_55__fireside_porting/comment_1_d690a52db82f9594d99ae65fe51e1f1a._comment
new file mode 100644
index 000000000..74acc8322
--- /dev/null
+++ b/doc/devblog/day_55__fireside_porting/comment_1_d690a52db82f9594d99ae65fe51e1f1a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://nullroute.eu.org/~grawity/"
+ nickname="Mantas"
+ subject="comment 1"
+ date="2013-11-13T06:22:49Z"
+ content="""
+[ProcExp](http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) may be useful -- it can show process-related syscalls and their return codes _(among other things like file or registry access)_ so it should tell exactly why the exec failed.
+"""]]
diff --git a/doc/devblog/day_56__git-annex_user_survey.mdwn b/doc/devblog/day_56__git-annex_user_survey.mdwn
new file mode 100644
index 000000000..8c1c67994
--- /dev/null
+++ b/doc/devblog/day_56__git-annex_user_survey.mdwn
@@ -0,0 +1,20 @@
+One of my goals for this month is to get a better sense of how git-annex is
+being used, how it's working out for people, and what areas need to be
+concentrated on. To start on that, I am doing the
+[2013 git-annex user survey](http://git-annex-survey.branchable.com/polls/2013/), similar to the git user
+surveys. I will be adding some less general polls later (suggestions for
+topics appreciated!), but you can go vote in any or all of 10 polls now.
+
+----
+
+Found a workaround for yesterday's Windows build problem. Seems that only
+cabal runs gcc in a way that fails, so `ghc --make` builds is successfully.
+However, the watcher doesn't quite work on Windows. It does get events when
+files are created, but it seems to then hang before it can add the file to
+git, or indeed finish printing out a debug log message about the event.
+This looks like it could be a problem with the threaded ghc runtime on
+Windows, or something like that.
+
+Main work today was improving the git repository repair to handle corrupt
+index files. The assistant can now start up, detect that the index file is
+corrupt, and regenerate it all automatically.
diff --git a/doc/devblog/day_5__gcrypt_special_remote_part_1.mdwn b/doc/devblog/day_5__gcrypt_special_remote_part_1.mdwn
new file mode 100644
index 000000000..626b5edaf
--- /dev/null
+++ b/doc/devblog/day_5__gcrypt_special_remote_part_1.mdwn
@@ -0,0 +1,7 @@
+About half way done with a gcrypt special remote. I can initremote it (the
+hard part to get working), and can send files to it. Can't yet get files
+back, or remove files, and only local repositories work so far, but this is
+enough to know it's going to be pretty nice!
+
+Did find one issue in gcrypt that I may need to develop a patch for:
+<https://github.com/blake2-ppc/git-remote-gcrypt/issues/3>
diff --git a/doc/devblog/day_6__gcrypt_fully_working.mdwn b/doc/devblog/day_6__gcrypt_fully_working.mdwn
new file mode 100644
index 000000000..58abdbb60
--- /dev/null
+++ b/doc/devblog/day_6__gcrypt_fully_working.mdwn
@@ -0,0 +1,8 @@
+gcrpyt is fully working now. *Most* of the examples in
+[[tips/fully_encrypted_git_repositories_with_gcrypt]] should work.
+
+A few known problems:
+
+* `git annex sync` refuses to sync with gcrypt remotes. some url parsing issue.
+* Swapping two drives with gcrypt repositories on the same mount point doesn't work yet.
+* http urls are not supported
diff --git a/doc/devblog/day_6__gcrypt_fully_working/comment_1_136bb7537a9ba93d400ce6f6ea1932ac._comment b/doc/devblog/day_6__gcrypt_fully_working/comment_1_136bb7537a9ba93d400ce6f6ea1932ac._comment
new file mode 100644
index 000000000..adb298fd3
--- /dev/null
+++ b/doc/devblog/day_6__gcrypt_fully_working/comment_1_136bb7537a9ba93d400ce6f6ea1932ac._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ ip="82.36.235.9"
+ subject="Converting an rsync special remote to a gcrypt special remote"
+ date="2013-09-11T17:36:09Z"
+ content="""
+I'm guessing there is no way to convert an rsync special remote to a gcrypt special remote? It would be cool not to have to upload 100GB across the Atlantic again!
+"""]]
diff --git a/doc/devblog/day_6__gcrypt_fully_working/comment_2_1f8faa65bbd56a12588b43a5bc822d96._comment b/doc/devblog/day_6__gcrypt_fully_working/comment_2_1f8faa65bbd56a12588b43a5bc822d96._comment
new file mode 100644
index 000000000..a6859cf2f
--- /dev/null
+++ b/doc/devblog/day_6__gcrypt_fully_working/comment_2_1f8faa65bbd56a12588b43a5bc822d96._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 2"
+ date="2013-09-12T16:53:02Z"
+ content="""
+Well, rsync and gcrypt use the same locations for annexed content, so it's theoretically possible.
+
+However, it seems a lot easier to just add a gcrypt remote and let git-annex use the existing rsync remote for the content that is already stored in it.
+"""]]
diff --git a/doc/devblog/day_7__release_day.mdwn b/doc/devblog/day_7__release_day.mdwn
new file mode 100644
index 000000000..f377bb4be
--- /dev/null
+++ b/doc/devblog/day_7__release_day.mdwn
@@ -0,0 +1,10 @@
+Got git annex sync working with gcrypt. So went ahead and made a release
+today. Lots of nice new features!
+
+Unfortunately the linux 64 bit daily build is failing, because my build
+host only has 2 gb of memory and it is no longer enough. I am looking for a
+new build host, ideally one that doesn't cost me $40/month for 3 gb of ram
+and 15 gb of disk. (Extra special ideally one that I can run multiple builds
+per day on, rather than the current situation of only building overnight to
+avoid loading the machine during the day.) Until this is sorted out, no
+new 64 bit linux builds..
diff --git a/doc/devblog/day_7__release_day/comment_1_12bb94d903868ecddb3e348c9c4afeaf._comment b/doc/devblog/day_7__release_day/comment_1_12bb94d903868ecddb3e348c9c4afeaf._comment
new file mode 100644
index 000000000..266e843fd
--- /dev/null
+++ b/doc/devblog/day_7__release_day/comment_1_12bb94d903868ecddb3e348c9c4afeaf._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 1"
+ date="2013-09-09T21:51:47Z"
+ content="""
+Joey, I'd be happy to host 64-bit builds on both Mac and Linux using my personal Jenkins server (both machines are local and have 16+ GB of RAM). I might even be able to get you SSH jail access to the build tree for the 64-bit Linux build. Just let me know at johnw@fpcomplete.com.
+"""]]
diff --git a/doc/devblog/day_7__release_day/comment_2_d3e38d6f6bba179dab40d4d75ff061de._comment b/doc/devblog/day_7__release_day/comment_2_d3e38d6f6bba179dab40d4d75ff061de._comment
new file mode 100644
index 000000000..96fb5dce3
--- /dev/null
+++ b/doc/devblog/day_7__release_day/comment_2_d3e38d6f6bba179dab40d4d75ff061de._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 2"
+ date="2013-09-10T23:11:27Z"
+ content="""
+Everything is all setup now to build git-annex on both systems, at most once per hour (if there have been new Git commits), and only between 2am and 4pm. Just contact me on IRC or e-mail and I'll setup you up with credentials so that you can manipulate the jobs and access the build artifacts.
+"""]]
diff --git a/doc/devblog/day_8__ill.mdwn b/doc/devblog/day_8__ill.mdwn
new file mode 100644
index 000000000..c086a9dc1
--- /dev/null
+++ b/doc/devblog/day_8__ill.mdwn
@@ -0,0 +1,20 @@
+I've been out sick. However, some things kept happening. Mesar contributed
+a build host, and the linux and android builds are now happening, hourly,
+there. (Thanks as well to the two other people who also offered hostng.)
+And I made a minor release to fix a bug in the test suite that I was pleased
+three different people reported.
+
+Today, my main work was getting git-annex to notice when a gcrypt remote
+located on some removable drive mount point is not the same gcrypt remote
+that was mounted there before. I was able to finesse this so it
+re-configures things to use the new gcrypt remote, as long as it's a
+special remote it knows about. (Otherwise it has to ignore the remote.)
+So, encrypted repos on removable drives will work just as well as
+non-encrypted repos!
+
+Also spent a while with rsync.net tech support trying to work out why
+someone's git-annex apparently opened a lot of concurrent ssh connections
+to rsync.net. Have not been able to reproduce the problem though.
+
+Also, a lot of catch-up to traffic. Still 63 messages backlogged however,
+and still not entirely well..
diff --git a/doc/devblog/day_9__Friday_the_13th.mdwn b/doc/devblog/day_9__Friday_the_13th.mdwn
new file mode 100644
index 000000000..b8fe4bc19
--- /dev/null
+++ b/doc/devblog/day_9__Friday_the_13th.mdwn
@@ -0,0 +1,21 @@
+Worked to get git-remote-gcrypt included in every git-annex autobuild
+bundle.
+(Except Windows; running a shell script there may need some work later..)
+
+Next I want to work on making the assistant easily able to create encrypted
+git repositories on removable drives. Which will involve a UI to select
+which gpg key to use, or creating (and backing up!) a gpg key.
+
+But, I got distracted chasing down some bugs on Windows. These were
+quite ugly; more direct mode mapping breakage which resulted in
+files not being accessible. Also fsck on Windows failed to detect and fix
+the problem. All fixed now. (If you use git-annex on Windows, you should
+certianly upgrade and run `git annex fsck`.)
+
+As with most bugs in the Windows port, the underlying cause turned out to
+be stupid: `isSymlink` always returned False on Windows. Which makes sense
+from the perspective of Windows not quite having anything entirely like
+symlinks. But failed when that was being used to detect when files in the
+git tree being merged into the repository had the symlink bit set..
+
+Did bug triage. Backlog down to 32 (mostly messages from August).
diff --git a/doc/devblog/day_9__Friday_the_13th/comment_1_07195b4ec399ba1be6c8bdb3ae0fa50b._comment b/doc/devblog/day_9__Friday_the_13th/comment_1_07195b4ec399ba1be6c8bdb3ae0fa50b._comment
new file mode 100644
index 000000000..aff4dc264
--- /dev/null
+++ b/doc/devblog/day_9__Friday_the_13th/comment_1_07195b4ec399ba1be6c8bdb3ae0fa50b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://nullroute.eu.org/~grawity/"
+ nickname="Mantas"
+ subject="comment 1"
+ date="2013-09-13T22:05:37Z"
+ content="""
+Windows *does* have something very much like symlinks – they're called *symlinks* (\"symbolic links\") and they are meant to [\"function just like UNIX links\"][1] as the official docs say.
+
+But on the other hand, yes – `isSymlink` makes less sense on Windows, because symlinks are just a type of reparse points, and there may be several other types (e.g. directory junctions should also be treated like symlinks, but mount points shouldn't...)
+
+[1]: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365680(v=vs.85).aspx
+"""]]
diff --git a/doc/devblog/moving_blogs.mdwn b/doc/devblog/moving_blogs.mdwn
new file mode 100644
index 000000000..f6dac56c9
--- /dev/null
+++ b/doc/devblog/moving_blogs.mdwn
@@ -0,0 +1,5 @@
+I've started a new page for my devblog, since I'm not focusing extensively
+on the assistant and so keeping the blog [[here|design/assistant/blog]]
+increasingly felt wrong. Also, my new year of
+[crowdfunded development](https://campaign.joeyh.name)
+formally starts in September, so a new blog seemed good.
diff --git a/doc/devblog/moving_blogs/comment_1_6caa7e67461a6ea5de8155ae9cf75fab._comment b/doc/devblog/moving_blogs/comment_1_6caa7e67461a6ea5de8155ae9cf75fab._comment
new file mode 100644
index 000000000..46df4a7f6
--- /dev/null
+++ b/doc/devblog/moving_blogs/comment_1_6caa7e67461a6ea5de8155ae9cf75fab._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://pnijjar.livejournal.com/"
+ ip="99.236.22.229"
+ subject="comment 1"
+ date="2013-08-31T00:05:16Z"
+ content="""
+Do we need to update our RSS feeds? I appear to be getting your devblog posts in my old feed, but I do not know whether that will continue working.
+"""]]
diff --git a/doc/devblog/moving_blogs/comment_2_e3e2048fc2397b87a2f29c9fe49394cb._comment b/doc/devblog/moving_blogs/comment_2_e3e2048fc2397b87a2f29c9fe49394cb._comment
new file mode 100644
index 000000000..19b5ae1c6
--- /dev/null
+++ b/doc/devblog/moving_blogs/comment_2_e3e2048fc2397b87a2f29c9fe49394cb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 2"
+ date="2013-08-31T10:03:04Z"
+ content="""
+The old RSS feed will continue working.
+
+So sit back, relax, and enjoy the show.
+"""]]
diff --git a/doc/direct_mode.mdwn b/doc/direct_mode.mdwn
index b0e9a0adb..749d3a6e2 100644
--- a/doc/direct_mode.mdwn
+++ b/doc/direct_mode.mdwn
@@ -4,8 +4,7 @@ git, and in turn point at the content of large files that is stored in
The advantage of direct mode is that you can access files directly,
including modifying them. The disadvantage is that most regular git
-commands cannot safely be used, and only a subset of git-annex commands
-can be used.
+commands cannot be used in a direct mode repository.
Normally, git-annex repositories start off in indirect mode. With some
exceptions:
@@ -21,7 +20,7 @@ exceptions:
Any repository can be converted to use direct mode at any time, and if you
decide not to use it, you can convert back to indirect mode just as easily.
Also, you can have one clone of a repository using direct mode, and another
-using indirect mode; direct mode interoperates.
+using indirect mode.
To start using direct mode:
@@ -52,26 +51,43 @@ computers, and manage your files, this should not be a concern for you.
## use a direct mode repository
You can use most git-annex commands as usual in a direct mode repository.
-A very few commands don't work in direct mode, and will refuse to do anything.
Direct mode also works well with the git-annex assistant.
-You can use `git commit --staged`, or plain `git commit`.
-But not `git commit -a`, or `git commit <file>` ..
-that'd commit whole large files into git!
+The most important command to use in a direct mode repository is `git annex
+sync`. This will commit any files you have run `git annex add` on, as well
+as files that were added earlier and have been modified. It will push
+the changes to other repositories for `git annex sync` there to pick up,
+and will pull and merge any changes made on other repositories into the
+local repository.
## what doesn't work in direct mode
-`git annex status` shows incomplete information. A few other commands,
-like `git annex unlock` don't make sense in direct mode and will refuse to
-run.
+A very few git-annex commands don't work in direct mode, and will refuse
+to do anything. For example, `git annex unlock` doesn't make sense in
+direct mode.
-As for git commands, you can probably use some git working tree
-manipulation commands, like `git checkout` and `git revert` in useful
-ways... But beware, these commands can replace files that are present in
-your repository with broken symlinks. If that file was the only copy you
-had of something, it'll be lost.
+As for git commands, direct mode prevents using any git command that would
+modify or access the work tree. So you cannot `git commit` or `git pull`
+(use `git annex sync` for both instead), or run `git status` (use `git
+annex status` instead). These git commands will complain "fatal: This
+operation must be run in a work tree".
-This is one more reason it's wise to make git-annex untrust your direct mode
-repositories. Still, you can lose data using these sort of git commands, so
-use extreme caution.
+The reason for this is that git doesn't understand how git-annex uses the
+work tree in direct mode. Where git expects the symlinks that get checked
+into git to be checked out in the work tree, direct mode instead replaces
+them with the actual content of files, as managed by git-annex.
+
+There are still lots of git commands you can use in direct mode. For
+example, you can run `git log` on files, run `git push`, `git fetch`,
+`git config`, `git remote add` etc.
+
+## forcing git to use the work tree in direct mode
+
+This is for experts only. You can lose data doing this, or check enormous
+files directly into your git repository, and it's your fault if you do!
+Also, there should be no good reason to need to do this, ever.
+
+Ok, with the warnings out of the way, all you need to do to make any
+git command access the work tree in direct mode is pass it
+`-c core.bare=false`
diff --git a/doc/direct_mode/comment_11_1c79c93f4b17cfc354ab920e3775cc60._comment b/doc/direct_mode/comment_11_1c79c93f4b17cfc354ab920e3775cc60._comment
new file mode 100644
index 000000000..ad1b66bc0
--- /dev/null
+++ b/doc/direct_mode/comment_11_1c79c93f4b17cfc354ab920e3775cc60._comment
@@ -0,0 +1,26 @@
+[[!comment format=mdwn
+ username="http://www.gl-como.it/author/valhalla/"
+ nickname="valhalla"
+ subject="Direct mode clone of an indirect repo"
+ date="2013-08-18T08:47:35Z"
+ content="""
+I too have issues with mixing direct and indirect mode repositories.
+
+ I have a regular, existing repository with ebooks, shared between various clones on proper :) filesystems; now I would need a copy of some of them on an ereader which only offers a FAT filesystem, so it has to be direct mode.
+
+ mount $READER
+ cd $reader
+ git clone $REPO
+
+I get a directory full of small files, the way git manages links on FAT.
+
+ git annex init \"ebook reader\"
+
+This detects the fact that it is working on a crippled filesystem, enables direct mode and disables ssh connection caching; up to now everything seems to be fine, but then
+
+ git annex get $SOME_BOOK
+
+seems to work, downloads the file somewhere, but when I try to open $SOME_BOOK it is still the fake link, and the file has been downloaded in its destination, as if the repo wasn't in direct mode.
+
+I use version 4.20130723 on debian jessie
+"""]]
diff --git a/doc/direct_mode/comment_12_1b5218fdb6ee362d6df68ff1229590d4._comment b/doc/direct_mode/comment_12_1b5218fdb6ee362d6df68ff1229590d4._comment
new file mode 100644
index 000000000..1743d5df9
--- /dev/null
+++ b/doc/direct_mode/comment_12_1b5218fdb6ee362d6df68ff1229590d4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 12"
+ date="2013-08-23T17:48:54Z"
+ content="""
+There should be no obstacles to using direct mode on one clone of a git repository, and indirect mode on another clone. The data stored in git for either mode is identical, and I do this myself for some repositories.
+
+@valhalla, you probably need to run `git annex fsck`, and if that does not solve your problem, you need to file a bug report.
+"""]]
diff --git a/doc/direct_mode/comment_13_55108ac736ea450df89332ba5de4a208._comment b/doc/direct_mode/comment_13_55108ac736ea450df89332ba5de4a208._comment
new file mode 100644
index 000000000..b8d80cd7e
--- /dev/null
+++ b/doc/direct_mode/comment_13_55108ac736ea450df89332ba5de4a208._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 13"
+ date="2013-08-23T17:50:15Z"
+ content="""
+@obergix asked:
+
+> But then, how can a direct repo sync with changes made in other remotes, if there no pull/fetch available.
+
+The answer is simple: By running `git annex sync`, which handles all that.
+"""]]
diff --git a/doc/direct_mode/comment_14_ff4ffc2aabc5fd174d7386ef13860f78._comment b/doc/direct_mode/comment_14_ff4ffc2aabc5fd174d7386ef13860f78._comment
new file mode 100644
index 000000000..3a538e00b
--- /dev/null
+++ b/doc/direct_mode/comment_14_ff4ffc2aabc5fd174d7386ef13860f78._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="Git annex copy needed before git annex sync"
+ date="2013-08-23T19:59:35Z"
+ content="""
+Thanks for these details @joeyh. But AFAIU, one needs to proceed to the git annex copy before doing the git annex sync, otherwise, symlinks (or files containing the symlink path on SMB) will be created, instead of the plain \"direct\" files that are expected.
+
+I'm still not sure whether the git annex sync needs to be issued on either of the indirect or direct remotes first, or both, then in which sequence. I think a \"walkthrough\" script would help.
+"""]]
diff --git a/doc/direct_mode/comment_15_1cd32456630b25d5aaa6d2763e6eb384._comment b/doc/direct_mode/comment_15_1cd32456630b25d5aaa6d2763e6eb384._comment
new file mode 100644
index 000000000..d265118a0
--- /dev/null
+++ b/doc/direct_mode/comment_15_1cd32456630b25d5aaa6d2763e6eb384._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 15"
+ date="2013-08-24T15:56:47Z"
+ content="""
+No, you can sync before you copy, get, or whatever. git-annex will replace the symlinks with the actual files when they arrive at the repository.
+"""]]
diff --git a/doc/direct_mode/comment_1_93fc31e8dc0ad16248a2593a1482d375._comment b/doc/direct_mode/comment_1_93fc31e8dc0ad16248a2593a1482d375._comment
deleted file mode 100644
index 8de8cf9af..000000000
--- a/doc/direct_mode/comment_1_93fc31e8dc0ad16248a2593a1482d375._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- username="https://www.google.com/accounts/o8/id?id=AItOawl2Jj8q2upJL4ZQAc2lp7ugTxJiGtcICv8"
- nickname="Michael"
- subject="comment 1"
- date="2013-02-18T23:24:11Z"
- content="""
-So, just which git commands *are* safe? It seems like I'm going to have to use direct mode, so it'd be nice to know just what I'm allowed to do, and what the workflow should be.
-"""]]
diff --git a/doc/direct_mode/comment_2_7f7086b34ed136851963f145868a1d23._comment b/doc/direct_mode/comment_2_7f7086b34ed136851963f145868a1d23._comment
deleted file mode 100644
index ddabee7e3..000000000
--- a/doc/direct_mode/comment_2_7f7086b34ed136851963f145868a1d23._comment
+++ /dev/null
@@ -1,12 +0,0 @@
-[[!comment format=mdwn
- username="http://joeyh.name/"
- ip="4.152.108.183"
- subject="safe and unsafe commands"
- date="2013-02-19T02:55:13Z"
- content="""
-All git commands that do not change files in the work tee (and do not stage files from the work tree), are safe. I don't have a complete list; it includes `git log`, `git show`, `git diff`, `git commit` (but not -a or with a file as a parameter), `git branch`, `git fetch`, `git push`, `git grep`, `git status`, `git tag`, `git mv` (this one is somewhat surprising, but I've tested it and it's ok)
-
-git commands that change files in the work tree will replace your data with dangling symlinks. This includes things like `git revert`, `git checkout`, `git merge`, `git pull`, `git reset`
-
-git commands that stage files from the work tree will commit your data to git directly. This includes `git add`, `git commit -a`, and `git commit file`
-"""]]
diff --git a/doc/direct_mode/comment_4_97c26bd82f623a3b2d56bab4afff0126._comment b/doc/direct_mode/comment_4_97c26bd82f623a3b2d56bab4afff0126._comment
index 180018399..cf5ae2fb6 100644
--- a/doc/direct_mode/comment_4_97c26bd82f623a3b2d56bab4afff0126._comment
+++ b/doc/direct_mode/comment_4_97c26bd82f623a3b2d56bab4afff0126._comment
@@ -6,7 +6,6 @@
content="""
<pre>
git annex add $file
-git commit -m changed
git annex sync
git annex copy $file --to otherrepo
</pre>
diff --git a/doc/direct_mode/comment_7_5355ac418bfb26e990762b80f4c36b77._comment b/doc/direct_mode/comment_7_5355ac418bfb26e990762b80f4c36b77._comment
new file mode 100644
index 000000000..d416a01f6
--- /dev/null
+++ b/doc/direct_mode/comment_7_5355ac418bfb26e990762b80f4c36b77._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://caust1c.myopenid.com/"
+ nickname="asbraithwaite"
+ subject="comment 7"
+ date="2013-08-12T18:06:21Z"
+ content="""
+Would it be safe to add largefiles to gitignore in direct mode?
+
+Can git-annex still track large files ignored by git?
+
+Thanks. :-)
+"""]]
diff --git a/doc/direct_mode/comment_8_6cd15e2c5fd0bef48f60c6993322c2fc._comment b/doc/direct_mode/comment_8_6cd15e2c5fd0bef48f60c6993322c2fc._comment
new file mode 100644
index 000000000..72ba16baf
--- /dev/null
+++ b/doc/direct_mode/comment_8_6cd15e2c5fd0bef48f60c6993322c2fc._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 8"
+ date="2013-08-12T18:12:32Z"
+ content="""
+asbraithwaite:
+No, as far as I know it can not.
+"""]]
diff --git a/doc/ekg.mdwn b/doc/ekg.mdwn
new file mode 100644
index 000000000..3bbea8614
--- /dev/null
+++ b/doc/ekg.mdwn
@@ -0,0 +1,14 @@
+You can `cabal configure -fEKG` to build a git-annex that includes
+the EKG remote monitoring interface.
+
+To access the EKG control panel, go to
+<http://localhost:4242/> while a git-annex command is running.
+
+This EKG build is mostly useful for debugging resource usage problems.
+
+[[!img ekg.png caption="git-annex webapp startup, and assistant startup scan"]]
+
+Note that since only one process can open port 4242 at a time, running
+more than one git-annex process with EKG support at the same time can
+result in some "resource busy (Address already in use)" messages -- but
+git-annex will continue to work.
diff --git a/doc/ekg/ekg.png b/doc/ekg/ekg.png
new file mode 100644
index 000000000..a8d16a2d8
--- /dev/null
+++ b/doc/ekg/ekg.png
Binary files differ
diff --git a/doc/encryption.mdwn b/doc/encryption.mdwn
index d93bee9d2..1eba19a68 100644
--- a/doc/encryption.mdwn
+++ b/doc/encryption.mdwn
@@ -1,3 +1,5 @@
+[[!toc]]
+
git-annex mostly does not use encryption. Anyone with access to a git
repository can see all the filenames in it, its history, and can access
any annexed file contents.
@@ -6,50 +8,94 @@ Encryption is needed when using [[special_remotes]] like Amazon S3, where
file content is sent to an untrusted party who does not have access to the
git repository.
-Such an encrypted remote uses strong GPG encryption on the contents of files,
-as well as HMAC hashing of the filenames. The size of the encrypted files,
-and access patterns of the data, should be the only clues to what is
-stored in such a remote.
+Such an encrypted remote uses strong ([[symmetric|design/encryption]] or
+asymmetric) encryption on the contents of files, as well as HMAC hashing
+of the filenames. The size of the encrypted files, and access patterns
+of the data, should be the only clues to what is stored in such a
+remote.
You should decide whether to use encryption with a special remote before
any data is stored in it. So, `git annex initremote` requires you
to specify "encryption=none" when first setting up a remote in order
-to disable encryption.
+to disable encryption. To use encryption, you run
+run `git-annex initremote` in one of these ways:
-If you want to use encryption, run `git annex initremote` with
-"encryption=USERID". The value will be passed to `gpg` to find encryption keys.
-Typically, you will say "encryption=2512E3C7" to use a specific gpg key.
-Or, you might say "encryption=joey@kitenet.net" to search for matching keys.
+* `git annex initremote newremote type=... encryption=hybrid keyid=KEYID ...`
+* `git annex initremote newremote type=... encryption=shared`
+* `git annex initremote newremote type=... encryption=pubkey keyid=KEYID ...`
-The default MAC algorithm to be applied on the filenames is HMACSHA1. A
-stronger one, for instance HMACSHA512, one can be chosen upon creation
-of the special remote with the option `mac=HMACSHA512`. The available
-MAC algorithms are HMACSHA1, HMACSHA224, HMACSHA256, HMACSHA384, and
-HMACSHA512. Note that it is not possible to change algorithm for a
-non-empty remote.
+## hybrid encryption keys
-The [[encryption_design|design/encryption]] allows additional encryption keys
-to be added on to a special remote later. Once a key is added, it is able
-to access content that has already been stored in the special remote.
-To add a new key, just run `git annex enableremote` specifying the
-new encryption key:
+The [[hybrid_key_design|design/encryption]] allows additional
+encryption keys to be added on to a special remote later. Due to this
+flexability, it is the default and recommended encryption scheme.
+
+ git annex initremote newremote type=... [encryption=hybrid] keyid=KEYID ...
- git annex enableremote myremote encryption=788A3F4C
+Here the KEYID(s) are passed to `gpg` to find encryption keys.
+Typically, you will say "keyid=2512E3C7" to use a specific gpg key.
+Or, you might say "keyid=joey@kitenet.net" to search for matching keys.
-Note that once a key has been given access to a remote, it's not
-possible to revoke that access, short of deleting the remote. See
-[[encryption_design|design/encryption]] for other security risks
-associated with encryption.
+To add a new key and allow it to access all the content that is stored
+in the encrypted special remote, just run `git annex
+enableremote` specifying the new encryption key:
-## shared cipher mode
+ git annex enableremote myremote keyid+=788A3F4C
+
+While a key can later be removed from the list, note that
+that will **not** necessarily prevent the owner of the key
+from accessing data on the remote (which is by design impossible to prevent,
+short of deleting the remote). In fact the only sound use of `keyid-=` is
+probably to replace a revoked key:
+
+ git annex enableremote myremote keyid-=2512E3C7 keyid+=788A3F4C
+
+See also [[encryption_design|design/encryption]] for other security
+risks associated with encryption.
+
+## shared encryption key
Alternatively, you can configure git-annex to use a shared cipher to
encrypt data stored in a remote. This shared cipher is stored,
-**unencrypted** in the git repository. So it's shared amoung every
-clone of the git repository. The advantage is you don't need to set up gpg
-keys. The disadvantage is that this is **insecure** unless you
-trust every clone of the git repository with access to the encrypted data
-stored in the special remote.
-
-To use shared encryption, specify "encryption=shared" when first setting
-up a special remote.
+**unencrypted** in the git repository. So it's shared among every
+clone of the git repository.
+
+ git annex initremote newremote type=... encryption=shared
+
+The advantage is you don't need to set up gpg keys. The disadvantage is
+that this is **insecure** unless you trust every clone of the git
+repository with access to the encrypted data stored in the special remote.
+
+## regular public key encryption
+
+This alternative simply encrypts the files in the special remotes to one or
+more public keys. It might be considered more secure due to its simplicity
+and since it's exactly the way everyone else uses gpg.
+
+ git annex initremote newremote type=.... encryption=pubkey keyid=KEYID ...
+
+A disavantage is that is not easy to later add additional public keys
+to the special remote. While the `enableremote` parameters `keyid+=` and
+`keyid-=` can be used, they have **no effect** on files that are already
+present on the remote. Probably the only use for these parameters is
+to replace a revoked key:
+
+ git annex enableremote myremote keyid-=2512E3C7 keyid+=788A3F4C
+
+But even in this case, since the files are not re-encrypted, the revoked
+key has to be kept around to be able to decrypt those files.
+(Of course, if the reason for revocation is
+that the key has been compromised, it is **insecure** to leave files
+encrypted using that old key, and the user should re-encrypt everything.)
+
+(Because filenames are MAC'ed, a cipher still needs to be
+generated (and encrypted to the given key IDs).)
+
+## MAC algorithm
+
+The default MAC algorithm to be applied on the filenames is HMACSHA1. A
+stronger one, for instance HMACSHA512, one can be chosen upon creation
+of the special remote with the option `mac=HMACSHA512`. The available
+MAC algorithms are HMACSHA1, HMACSHA224, HMACSHA256, HMACSHA384, and
+HMACSHA512. Note that it is not possible to change algorithm for a
+non-empty remote.
diff --git a/doc/footer/column_a.mdwn b/doc/footer/column_a.mdwn
index 400193ed0..92c77d840 100644
--- a/doc/footer/column_a.mdwn
+++ b/doc/footer/column_a.mdwn
@@ -2,6 +2,6 @@
[[!inline pages="news/* and !*/Discussion" archive=yes show=2 feeds=no]]
-### [[Dev blog|design/assistant/blog]]
+### [[devblog|devblog]]
-[[!inline pages="design/assistant/blog/* and !*/Discussion" archive=yes show=5 feeds=no]]
+[[!inline pages="devblog/* and !*/Discussion" archive=yes show=5 feeds=no]]
diff --git a/doc/forum/--print0_option_as_in___34__find__34__.mdwn b/doc/forum/--print0_option_as_in___34__find__34__.mdwn
deleted file mode 100644
index 7d9a2284d..000000000
--- a/doc/forum/--print0_option_as_in___34__find__34__.mdwn
+++ /dev/null
@@ -1,5 +0,0 @@
-It would be nice if git annex find supported a --print0 option as GNU
-find does. That way, file names that are printed could be piped to
-xargs even if they have spaces.
-
-> Done. --[[Joey]]
diff --git a/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__.mdwn b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__.mdwn
new file mode 100644
index 000000000..c6c67a291
--- /dev/null
+++ b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__.mdwn
@@ -0,0 +1,12 @@
+Hello,
+
+I went through several of the questions on the forum but could not find the answer to this. I have the following scenario, which seems very similar to the nomad case.
+
+I have a server at home with many big media files. I want to keep a subset of these files on my laptop, to watch when I travel. When I'm done watching the files, I want to either delete them (i.e, they should no longer be on any machine) or archive them (i.e., they should remain on the server, but no longer be on the laptop). I think I know how to do this from the command line, but I still have a few questions.
+
+- How do I drop a file from _every_ repository? If I understood correctly, `git annex drop foo` will only drop foo locally.
+- Is it possible to follow this use case using the assistant, or should I use the command line instead (which would be very fine with me)? In particular, how do I choose the file I want to put on the laptop? (It seems `git annex get` is the command line way, is there an assistant equivalent?)
+- Can I use both the assistant and the command line at the same time? Is there a description of the command-line version of what the assistant is doing behind the scenes?
+- Can the server repository be both a "transfer" repository (to hold the files I haven't watch) and an "archive" repository (to keep the files I've watched and decided to keep), or do I need two repositories (on the server) for that?
+
+Thanks a lot for any suggestion.
diff --git a/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_1_fe291cd6cd8e2d5b8e23f8e3689d824b._comment b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_1_fe291cd6cd8e2d5b8e23f8e3689d824b._comment
new file mode 100644
index 000000000..3eb2697a6
--- /dev/null
+++ b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_1_fe291cd6cd8e2d5b8e23f8e3689d824b._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-21T22:41:44Z"
+ content="""
+You can use `git annex drop foo --from remote` to drop the file from the remote. Of course, the remote has to be accessible. You can't drop files from an offline drive that's stored in a safe..
+
+What you might be looking for is `git annex drop foo; rm foo`, followed by a git commit, and then later you can run `git annex unused` on a remote and it will let you then easily drop the files you've removed from the repository. This approach of just deleting files when you're done with them also works when using the assistant.
+
+The assistant isn't really about only keeping a subset of files on your laptop. It would like to get them all, except for ones in \"archive\" directories.
+You can configure the assistant to use manual mode, and then it doesn't download any files on its own (so you have to manually `git annex get` them), but it will still handle all the other stuff the assistant does, like automatically committing and syncing changes.
+
+An archive repository wants one copy of every file that is not already stored in some other archive repository. So an archive repository could certianly be used instead of a transfer repository. (But not a small archive repository; those only want files that are moved to \"archive\" directories.) A better choice might be to make that server be a backup repository. That makes it want *every* file, no matter what, and it follows that it would archive everything, and have everything the client wants available for transferring to it.
+"""]]
diff --git a/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_2_f0dbc3c723999bf0f22502e3a89d1d4a._comment b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_2_f0dbc3c723999bf0f22502e3a89d1d4a._comment
new file mode 100644
index 000000000..3ae6b94c5
--- /dev/null
+++ b/doc/forum/A_question_an_the_nomad_use_cases:_files_to_fetch__44___files_to_delete__44___files_to_keep__63__/comment_2_f0dbc3c723999bf0f22502e3a89d1d4a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="comment 2"
+ date="2013-10-23T10:06:53Z"
+ content="""
+Thank you for the suggestions and explanations. I'm using a manual repo and I find that it works quite well.
+"""]]
diff --git a/doc/forum/Accessing_files_directly_on__a_USB_device.mdwn b/doc/forum/Accessing_files_directly_on__a_USB_device.mdwn
new file mode 100644
index 000000000..7b16f6523
--- /dev/null
+++ b/doc/forum/Accessing_files_directly_on__a_USB_device.mdwn
@@ -0,0 +1,11 @@
+Using the assistant, I have created a repository on my laptop plus a synced repository on a USB disk. Looking into the first repository, I see my files accompanied by a .git directory. However, looking on the USB disk (e.g. /media/usb/annex), all I see is what looks like the content of a .git directory.
+
+This means that it is difficult to retrieve any file directly from this disk -- it has to be synced to another local repository first.
+
+Is there any way to change this ? E.g. to have a copy of the working tree, plus a .git directory, on the disk ?
+
+My use case: I have added plenty of media files to my repository. In addition to using the USB disk as a backup/medium for transfering these files to another computer, I'd like to be able to plug the disk to e.g. a media player and read the files directly from the tree, but it does not work at the moment.
+
+Is there anything I am missing ?
+
+Edited: yes, there is something I was missing: the forum entry at [[forum/USB_backup_with_files_visible/]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with.mdwn b/doc/forum/Adding_existing_S3_bucket_to_sync_with.mdwn
new file mode 100644
index 000000000..af138c101
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with.mdwn
@@ -0,0 +1,16 @@
+Hello,
+
+I am just starting to learn git-annex so forgive me if this is a naive question.
+
+I have the following repositories:
+
+1. Home (laptop)
+2. Work (mac mini)
+3. S3 bucket
+4. USB drive, full backup, attached to Home laptop.
+
+I want to sync files between Home and Work via the S3 bucket. It is not clear to me how to accomplish this through the git-annex assistant. Is this possible? Are there instructions online?
+
+Thanks in advance!
+
+Scott
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_1_30b9a70d367dd5b8781e9a86e42d4c3e._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_1_30b9a70d367dd5b8781e9a86e42d4c3e._comment
new file mode 100644
index 000000000..d68af19f9
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_1_30b9a70d367dd5b8781e9a86e42d4c3e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://marco.paga.myopenid.com/"
+ ip="2001:4dd0:ff00:917b:d575:780:2c27:d982"
+ subject="Yes, it is possible"
+ date="2013-08-19T17:59:56Z"
+ content="""
+You can sync both repos. The simplest way is to have both clients signed on to jabber. This way the clients exchange information when the two are online.
+
+Additionally you need to have a cloud special remote available on both ends. The cloud repository is needed to push and retrieve data for the clients. You need to configure the cloud as a transfer reposity. The clients as - what else - client. The USB Drive can be used as a backup repository on one or both ends and perhaps even for syncing very large files around.
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_2_a8525c1a7e5f89c30c9503fe8bfed02e._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_2_a8525c1a7e5f89c30c9503fe8bfed02e._comment
new file mode 100644
index 000000000..9e1d27af4
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_2_a8525c1a7e5f89c30c9503fe8bfed02e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://marco.paga.myopenid.com/"
+ ip="2001:4dd0:ff00:917b:d575:780:2c27:d982"
+ subject="I forgot to mention"
+ date="2013-08-19T18:01:47Z"
+ content="""
+You might want to have a look at this: https://git-annex.branchable.com/assistant/remote_sharing_walkthrough/
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_3_c3878989f74e740c0ed42f440750f3a4._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_3_c3878989f74e740c0ed42f440750f3a4._comment
new file mode 100644
index 000000000..9925f8274
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_3_c3878989f74e740c0ed42f440750f3a4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkjQhXk8KAh9yD0p1R6QzT-Sw7FtHE3d54"
+ nickname="Scott"
+ subject="comment 3"
+ date="2013-08-19T18:03:41Z"
+ content="""
+Great thanks! I'll try it out tonight and report back.
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_4_c06cc86496f9d4c0c42a8c89aa5a7b35._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_4_c06cc86496f9d4c0c42a8c89aa5a7b35._comment
new file mode 100644
index 000000000..5e1a39713
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_4_c06cc86496f9d4c0c42a8c89aa5a7b35._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkjQhXk8KAh9yD0p1R6QzT-Sw7FtHE3d54"
+ nickname="Scott"
+ subject="comment 4"
+ date="2013-08-20T16:18:24Z"
+ content="""
+When I try to setup my Jabber client, using my gmail address, the assistant crashes. I thought this might be due to having two-factor authentication enabled so I generated an application specific password and tried that. The assistant still crashes. The log is huge, I am not sure what would be relevant to show here.
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_5_0a1c2dd0929511ff824be8de2c8d85eb._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_5_0a1c2dd0929511ff824be8de2c8d85eb._comment
new file mode 100644
index 000000000..2c4927b19
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_5_0a1c2dd0929511ff824be8de2c8d85eb._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://marco.paga.myopenid.com/"
+ ip="2001:4dd0:ff00:917b:f87b:5579:3820:5db"
+ subject="Please post the log"
+ date="2013-08-21T15:49:00Z"
+ content="""
+I don't know what is going wrong. It is not a bad idea to post the log information.
+
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_6_1444c2f89885f028f20a4d3ce225a403._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_6_1444c2f89885f028f20a4d3ce225a403._comment
new file mode 100644
index 000000000..21c3d80e3
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_6_1444c2f89885f028f20a4d3ce225a403._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkjQhXk8KAh9yD0p1R6QzT-Sw7FtHE3d54"
+ nickname="Scott"
+ subject="comment 6"
+ date="2013-08-21T20:05:31Z"
+ content="""
+I tried a different approach and attempted to setup s3 at the command line. This is what I did:
+
+zombie:annex scott$ export AWS_ACCESS_KEY_ID=\"my key\"
+zombie:annex scott$ export AWS_SECRET_ACCESS_KEY=\"my secret key\"
+zombie:annex scott$ git annex initremote S3 type=S3 encryption=shared
+[2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"show-ref\",\"git-annex\"]
+[2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+[2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"log\",\"refs/heads/git-annex..da801570f9ed8d28e5a0cea6cc51f1a2003317d6\",\"--oneline\",\"-n1\"]
+[2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"log\",\"refs/heads/git-annex..8015f3fed32792b558d16008d20816fab0fc50c2\",\"--oneline\",\"-n1\"]
+[2013-08-21 13:03:42 PDT] chat: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"cat-file\",\"--batch\"]
+[2013-08-21 13:03:42 PDT] read: git [\"config\",\"--null\",\"--list\"]
+initremote S3 (encryption setup) [2013-08-21 13:03:42 PDT] read: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--gen-random\",\"--armor\",\"2\",\"512\"]
+(shared cipher) (checking bucket...)
+git-annex: connect: does not exist (Connection refused)
+failed
+git-annex: initremote: 1 failed
+"""]]
diff --git a/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_7_1c30944010d541096baff18198a5560d._comment b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_7_1c30944010d541096baff18198a5560d._comment
new file mode 100644
index 000000000..7e05bf59a
--- /dev/null
+++ b/doc/forum/Adding_existing_S3_bucket_to_sync_with/comment_7_1c30944010d541096baff18198a5560d._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkjQhXk8KAh9yD0p1R6QzT-Sw7FtHE3d54"
+ nickname="Scott"
+ subject="comment 7"
+ date="2013-08-21T20:07:58Z"
+ content="""
+Sorry that didnt format properly
+
+ zombie:annex scott$ export AWS_ACCESS_KEY_ID=\"key\"
+ zombie:annex scott$ export AWS_SECRET_ACCESS_KEY=\"secret\"
+ zombie:annex scott$ git annex initremote S3 type=S3 encryption=shared
+ [2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"show-ref\",\"git-annex\"]
+ [2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"log\",\"refs/heads/git-annex..da801570f9ed8d28e5a0cea6cc51f1a2003317d6\",\"--oneline\",\"-n1\"]
+ [2013-08-21 13:03:42 PDT] read: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"log\",\"refs/heads/git-annex..8015f3fed32792b558d16008d20816fab0fc50c2\",\"--oneline\",\"-n1\" ]
+ [2013-08-21 13:03:42 PDT] chat: git [\"--git-dir=/Network/Servers/filer004/vol/office_homes/scott/annex/.git\",\"--work-tree=/Network/Servers/filer004/vol/office_homes/scott/annex\",\"cat-file\",\"--batch\"]
+ [2013-08-21 13:03:42 PDT] read: git [\"config\",\"--null\",\"--list\"]
+ initremote S3 (encryption setup) [2013-08-21 13:03:42 PDT] read: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--gen-random\",\"--armor\",\"2\",\"512\"]
+ (shared cipher) (checking bucket...)
+ git-annex: connect: does not exist (Connection refused)
+ failed
+ git-annex: initremote: 1 failed
+"""]]
diff --git a/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__.mdwn b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__.mdwn
new file mode 100644
index 000000000..0392dbb38
--- /dev/null
+++ b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__.mdwn
@@ -0,0 +1,3 @@
+While running the Git Annex App on Android, the app causes a constant cpu usage of about 50% when idling. I've seen this behavior on two devices (phone and tablet) with a CM 10.1 nightly build. The app causes this high cpu usage even when it is in the background, not performing any synchronization and managing only one repository containing just one file. Unfortunately I couldn't figure out what causes the cpu usage. The daemon.log file remains unchanged and I couldn't find any other log files.
+
+Is this expected behavior or unusual high cpu usage?
diff --git a/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_1_7880fc38792a1fcbf3e5c47e8bcaabce._comment b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_1_7880fc38792a1fcbf3e5c47e8bcaabce._comment
new file mode 100644
index 000000000..28f3dfb92
--- /dev/null
+++ b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_1_7880fc38792a1fcbf3e5c47e8bcaabce._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmKKg3Vmzk7KwRGRKjHVdtyoj1JfxLX6NM"
+ nickname="Tom"
+ subject="comment 1"
+ date="2013-10-01T17:38:03Z"
+ content="""
+I've had this issue as well. Saw a comment on Joey's blog that implies he knows about it and that a fix will be released soon.
+"""]]
diff --git a/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_2_840fbce18b4fdec21ee557fdf52c366e._comment b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_2_840fbce18b4fdec21ee557fdf52c366e._comment
new file mode 100644
index 000000000..eaf42c9e2
--- /dev/null
+++ b/doc/forum/Android:_is_constant_high_cpu_usage_to_be_expected__63__/comment_2_840fbce18b4fdec21ee557fdf52c366e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 2"
+ date="2013-10-16T16:57:02Z"
+ content="""
+This was fixed.
+
+(Please file bug reports for bugs in the future, so they don't clutter up this forum once fixed.)
+"""]]
diff --git a/doc/forum/Annex_contents_just_disappeared__63__.mdwn b/doc/forum/Annex_contents_just_disappeared__63__.mdwn
new file mode 100644
index 000000000..d18e2bf91
--- /dev/null
+++ b/doc/forum/Annex_contents_just_disappeared__63__.mdwn
@@ -0,0 +1,12 @@
+Joey,
+
+I have git-annex now to manage many of the repositories on my system. I have them both on my local machine, and on a very large file server, and a backup system on the Internet.
+
+Today I went to look at a file in one of my annexes and it wasn't there. This really surprised me. But what surprised me most is that around 90% of the files in *all* of my annexes on both my local system and my file server are completely missing. Only the Internet backup system has them.
+
+How could something like this happen, when I haven't been interacting with these annexes at all during this time? Can you think of any scenario that might lead to this? This is pretty much the absolute worst case scenario for an archival data system.
+
+I am running on Mac OS X 10.8, using GHC 7.6.3 to build git-annex, and I keep my git-annex binary updated often.
+
+Thanks,
+ John
diff --git a/doc/forum/Annex_contents_just_disappeared__63__/comment_1_4ab5ca00f912c0c95fabc10f2d9600d3._comment b/doc/forum/Annex_contents_just_disappeared__63__/comment_1_4ab5ca00f912c0c95fabc10f2d9600d3._comment
new file mode 100644
index 000000000..fe4edbc27
--- /dev/null
+++ b/doc/forum/Annex_contents_just_disappeared__63__/comment_1_4ab5ca00f912c0c95fabc10f2d9600d3._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 1"
+ date="2013-08-23T03:06:00Z"
+ content="""
+Wait, I think this comes from a backend switch. I changed my .gitattributes file at one point to read:
+
+* annex.backend=SHA512E annex.numcopies=2
+
+I thought this would just affect new files, not existing annexed content. Could this do it?
+"""]]
diff --git a/doc/forum/Annex_contents_just_disappeared__63__/comment_2_657f737c5d64d440aa133ddb41408fbc._comment b/doc/forum/Annex_contents_just_disappeared__63__/comment_2_657f737c5d64d440aa133ddb41408fbc._comment
new file mode 100644
index 000000000..e30ff02ca
--- /dev/null
+++ b/doc/forum/Annex_contents_just_disappeared__63__/comment_2_657f737c5d64d440aa133ddb41408fbc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 2"
+ date="2013-08-23T03:14:15Z"
+ content="""
+Yes, that was the problem, sorry to bother you. None of my data is gone, it's just sitting there under unknown names. I can roll back to when it knew the names, and migrate them forward.
+"""]]
diff --git a/doc/forum/Annex_contents_just_disappeared__63__/comment_3_9b4c35feb14b37d43d053d7430da9abf._comment b/doc/forum/Annex_contents_just_disappeared__63__/comment_3_9b4c35feb14b37d43d053d7430da9abf._comment
new file mode 100644
index 000000000..6c40a1cac
--- /dev/null
+++ b/doc/forum/Annex_contents_just_disappeared__63__/comment_3_9b4c35feb14b37d43d053d7430da9abf._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 3"
+ date="2013-08-23T04:28:45Z"
+ content="""
+If you change the backend, and then in one repository you run `git annex migrate`, other repositories that have the old keys will not know about the new names. For this reason, then multiple repositories have the files, it's best to run it redundantly in each repository.
+
+TBH, migration is a bit of a PITA because of this. Best to aovid it in most cases.
+
+Git-annex will never perform a migration begind your back. You must have run `git annex migrate` at some point. You can check the git history for details.
+"""]]
diff --git a/doc/forum/Annex_contents_just_disappeared__63__/comment_4_c3625409652bff5f2165260803269a8a._comment b/doc/forum/Annex_contents_just_disappeared__63__/comment_4_c3625409652bff5f2165260803269a8a._comment
new file mode 100644
index 000000000..236f8cfde
--- /dev/null
+++ b/doc/forum/Annex_contents_just_disappeared__63__/comment_4_c3625409652bff5f2165260803269a8a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 4"
+ date="2013-08-30T06:06:16Z"
+ content="""
+Just to confirm, this wasn't a git-annex problem at all, but just a misstep during migration as you suggested.
+
+I think what I'm going to do now is to just wipe the slate clean and start over again, by using `unannex -fast` on all the files, wiping `.git`, and then adding everything back in using my new default backend of SHA512E. The bigger pain is doing the same thing on all the servers where I have this data (to avoid having to upload it again), but in such a way that I'm not replicating file history. I think I should be able to just clone, `mv $OLDREPO/.git/annex/objects objects`, `git annex add objects`, `git rm -r --cached objects`, and then everything should be good without even needing a new commit on the remote machine, just a git-annex sync.
+"""]]
diff --git a/doc/forum/Annex_dropping_files.mdwn b/doc/forum/Annex_dropping_files.mdwn
new file mode 100644
index 000000000..7ec19caa1
--- /dev/null
+++ b/doc/forum/Annex_dropping_files.mdwn
@@ -0,0 +1,12 @@
+It seems like one of my repos dropped files by itself, my setup involved 3 distributed repos (non bare repos, not using assistant), A/B/C then one client died I've created another one in its place called D cloned from B and marked C as dead. I have now A/B/D. I have updated files in A synced it to D (central) I then tried dropping unused, it listed none (I've dropped the files from A which has full copy) at this point I thought B did not sync to it maybe thats why it did not drop them. I went home sync my laptop B (B dropped its share of unused files) but cental D still show no unused.
+
+A-D has full copies of the repo
+B has partial.
+
+At this point I checked out a old commit from a week ago, checked where the links for the files are pointing to, they point to no where files are not there. Repo sized reported with du -hcs show both repos are the same size (132GB) looks like D managed to drop unused files by itself. I am wondering what caused this?
+
+My annex version is,
+
+git-annex version: 4.20130902-g307537a
+
+on all clients.
diff --git a/doc/forum/Annex_dropping_files/comment_1_62fbea95248fda2ff075b5a8952a728f._comment b/doc/forum/Annex_dropping_files/comment_1_62fbea95248fda2ff075b5a8952a728f._comment
new file mode 100644
index 000000000..3844d3f0d
--- /dev/null
+++ b/doc/forum/Annex_dropping_files/comment_1_62fbea95248fda2ff075b5a8952a728f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T21:01:03Z"
+ content="""
+If you have just created repository D and have just copied some files to it, then it will only contain those files, and not old deleted files or old versions of files. You can run `git annex copy --all --to D` to copy all those files to D, although if you're only wanting to dropunused them, there is not much point in that..
+"""]]
diff --git a/doc/forum/Assistant:_configure_auto-sync.mdwn b/doc/forum/Assistant:_configure_auto-sync.mdwn
new file mode 100644
index 000000000..48c4dc455
--- /dev/null
+++ b/doc/forum/Assistant:_configure_auto-sync.mdwn
@@ -0,0 +1,11 @@
+I have large central repositories of data. Therefore, on each client I want to save part data(to save space of disk). In command line I do
+
+ [...]
+ git-annex webapp
+ git-annex drop [DeleteContentDirectory]
+ [...]
+
+After this command Assistant performs automatic synchronization getting content of files from this directory(DeleteContentDirectory), but I don't want. I want it's was only symlink of file in this directory.
+
+How can I configure Assistant which files have to get content on the client? It's possible?
+
diff --git a/doc/forum/Assistant:_configure_auto-sync/comment_1_c8cabd38114582bbdbad49f2d81959d7._comment b/doc/forum/Assistant:_configure_auto-sync/comment_1_c8cabd38114582bbdbad49f2d81959d7._comment
new file mode 100644
index 000000000..34fffb846
--- /dev/null
+++ b/doc/forum/Assistant:_configure_auto-sync/comment_1_c8cabd38114582bbdbad49f2d81959d7._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmWg4VvDTer9f49Y3z-R0AH16P4d1ygotA"
+ nickname="Tobias"
+ subject="comment 1"
+ date="2013-08-26T07:44:22Z"
+ content="""
+You should set your repository to \"manual\" mode instead of \"client\" mode.
+
+But then no data will be synced at all by the assistant, only metadata. You would have to do \"get/drop\" manually for commandline for all files.
+
+Alternatively you could use the special \"archive\" folders that are supported by the assistant.
+
+"""]]
diff --git a/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days.mdwn b/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days.mdwn
new file mode 100644
index 000000000..77b092891
--- /dev/null
+++ b/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days.mdwn
@@ -0,0 +1,72 @@
+I've been experiencing problems with Box.com for a few days now and I don't know what's causing them. Is anyone else experiencing anything similar?
+
+I paste the log.
+
+ [2013-09-02 12:27:26 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "c9e1d5421e78924c21e3d68e84f80a8d1f64f9488020107ca0eeee0c4f10e763.py", keyBackendName = "SHA256E", keySize = Just 1891, keyMtime = Nothing}}
+ [2013-09-02 12:27:26 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/kant.xml Nothing : expensive scan found missing object
+ [2013-09-02 12:27:26 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/argecho.py Nothing
+ [2013-09-02 12:27:26 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/argecho.py Nothing
+ [2013-09-02 12:27:26 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/argecho.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:27:26 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/argecho.py Just 437
+ ResponseTimeout
+ ResponseTimeout
+
+
+ [2013-09-02 12:27:44 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "dd3cc45d91430c6f7d68eb807f4ac1561cd0297b11a2de77b5fe66017d125798.py", keyBackendName = "SHA256E", keySize = Just 437, keyMtime = Nothing}}
+ [2013-09-02 12:27:44 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/kgp.dtd Nothing : expensive scan found missing object
+ [2013-09-02 12:27:44 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/autosize.py Nothing
+ [2013-09-02 12:27:44 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/autosize.py Nothing
+ [2013-09-02 12:27:44 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/autosize.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:27:44 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/autosize.py Just 2861
+ ResponseTimeout
+ ResponseTimeout
+
+
+ [2013-09-02 12:28:02 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "d6b7940ac68768a8e37e72f248e2d94f19fb0d47062084d9baf0ec08cebbf692.py", keyBackendName = "SHA256E", keySize = Just 2861, keyMtime = Nothing}}
+ [2013-09-02 12:28:02 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/kgp.py Nothing : expensive scan found missing object
+ [2013-09-02 12:28:02 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/builddialectexamples.py Nothing
+ [2013-09-02 12:28:03 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/builddialectexamples.py Nothing
+ [2013-09-02 12:28:03 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/builddialectexamples.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:28:03 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/builddialectexamples.py Just 1090
+ ResponseTimeout
+ ResponseTimeout
+
+
+ [2013-09-02 12:28:21 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "f1492b80d05b96cc7cf2904d461c99d430fa86a4eb1d99f1b155c9147ff4420f.py", keyBackendName = "SHA256E", keySize = Just 1090, keyMtime = Nothing}}
+ [2013-09-02 12:28:21 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/russiansample.xml Nothing : expensive scan found missing object
+ [2013-09-02 12:28:21 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/colorize.py Nothing
+ [2013-09-02 12:28:21 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/colorize.py Nothing
+ [2013-09-02 12:28:21 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/colorize.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:28:21 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/colorize.py Just 4864
+ ResponseTimeout
+ ResponseTimeout
+
+
+ [2013-09-02 12:28:40 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "b577eaf8b6ddbf9fef866c455cae248aec3b22e3f2e91aa2b75ece90f1801689.py", keyBackendName = "SHA256E", keySize = Just 4864, keyMtime = Nothing}}
+ [2013-09-02 12:28:40 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/stderr.py Nothing : expensive scan found missing object
+ [2013-09-02 12:28:40 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/dialect.py Nothing
+ [2013-09-02 12:28:40 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/dialect.py Nothing
+ [2013-09-02 12:28:40 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/dialect.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:28:40 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/dialect.py Just 4449
+ ResponseTimeout
+ ResponseTimeout
+
+
+ [2013-09-02 12:28:58 CEST] TransferWatcher: transfer finishing: Transfer {transferDirection = Upload, transferUUID = UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9", transferKey = Key {keyName = "c5e5d9b1bee2710c7ed05270a363d3e93270b0fb6779c4c8d59ace06c11db684.py", keyBackendName = "SHA256E", keySize = Just 4449, keyMtime = Nothing}}
+ [2013-09-02 12:28:58 CEST] TransferScanner: queued Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/kgp/stdout.py Nothing : expensive scan found missing object
+ [2013-09-02 12:28:58 CEST] Transferrer: Transferring: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/fibonacci.py Nothing
+ [2013-09-02 12:28:58 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/fibonacci.py Nothing
+ [2013-09-02 12:28:58 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/fibonacci.py Nothing
+
+
+ 100% 0.0 B/s 0s[2013-09-02 12:28:58 CEST] TransferWatcher: transfer starting: Upload UUID "72111b4c-28fe-42fd-a77b-e4cb9240a1c9" Documentos/diveintopython-5.4/py/fibonacci.py Just 532
diff --git a/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days/comment_1_6ca872c241399b9129cf9a18f42ebd43._comment b/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days/comment_1_6ca872c241399b9129cf9a18f42ebd43._comment
new file mode 100644
index 000000000..2c7d98b49
--- /dev/null
+++ b/doc/forum/Box.com_hasn__39__t_been_working_for_a_few_days/comment_1_6ca872c241399b9129cf9a18f42ebd43._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://sunny256.sunbase.org/"
+ nickname="sunny256"
+ subject="It works here"
+ date="2013-09-02T11:47:00Z"
+ content="""
+I set up a box.com remote a couple of months ago or so just for testing. Haven't used it that much, but I tested it now to see if it still works. No errors or problems. I have pasted the output from a session where I copied a file to box.com, dropped it locally, then got it back from box.com here: <https://gist.github.com/sunny256/6411972>. The computer I ran the test on is using the newest git-annex binary (v4.20130827), Ubuntu 10.04.4 LTS. Pretty old distro, but it still works.
+"""]]
diff --git a/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook.mdwn b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook.mdwn
new file mode 100644
index 000000000..9c0f5c7d7
--- /dev/null
+++ b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook.mdwn
@@ -0,0 +1,41 @@
+I'm trying to automate syncing of two repos A and B. My goal is to run `git annex sync` from A and have the working copy of B updated automatically. According to the manual page, `git annex merge` should to the trick. It works just fine when I run it manually in B, but not when I run it from the post-receive hook, as suggested in the manual page.
+
+Here is a test script that illustrates the issue: <https://gist.github.com/anonymous/6197019>
+
+The output I get:
+
+ [...]
+ file1 exists after manual git annex merge
+ [...]
+ file2 does not exist after git annex merge in post-receive
+
+From the output I can see that `git annex merge` is run on the remote end, and seems to do it's thing (`file2` is added):
+
+ remote: merge git-annex (merging synced/git-annex into git-annex...)
+ remote: ok
+ remote: merge synced/master Updating 6e5bfba..0dcbcfd
+ remote: Fast-forward
+ remote: file2 | 1 +
+ remote: 1 file changed, 1 insertion(+)
+ remote: create mode 120000 file2
+ remote:
+ remote: ok
+
+However, the working copy in B does not have the file `file2`. Even worse, `git status` in B shows the file as deleted:
+
+ # On branch master
+ # Your branch is ahead of 'origin/master' by 2 commits.
+ #
+ # Changes not staged for commit:
+ # (use "git add/rm <file>..." to update what will be committed)
+ # (use "git checkout -- <file>..." to discard changes in working directory)
+ #
+ # deleted: file2
+ #
+ no changes added to commit (use "git add" and/or "git commit -a")
+
+So when running `git annex sync` from B now, the file will be deleted from A as well, which is not what I expected.
+
+This is on Ubuntu 12.04, using the precompiled git-annex tarball (amd64).
+
+What am I doing wrong?
diff --git a/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_1_8b71cb6772b219c27c17392d5099907a._comment b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_1_8b71cb6772b219c27c17392d5099907a._comment
new file mode 100644
index 000000000..cfaff89b1
--- /dev/null
+++ b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_1_8b71cb6772b219c27c17392d5099907a._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://kallesoderman.myopenid.com/"
+ ip="85.224.35.48"
+ subject="Same problem here"
+ date="2013-08-14T20:20:42Z"
+ content="""
+I'm trying to achieve [[USB_backup_with_files_visible/]] but can't make the post-recieve or post-update hooks have any effect. The filesystem is vfat so there are some issues with mounting defaults and executables (do the hooks have to be executable?) but regardless of mount options no dice.
+
+ ``git-annex merge`` at the cli works perfectly. I havent been bitten by files being deleted and propagated though.
+
+Manually merging ruins my \"late for work need to bring data but to tired to think properly\" use case.
+"""]]
diff --git a/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_2_af2a2634d8d128868022d033d6adb549._comment b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_2_af2a2634d8d128868022d033d6adb549._comment
new file mode 100644
index 000000000..0623ed1db
--- /dev/null
+++ b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_2_af2a2634d8d128868022d033d6adb549._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-23T18:35:01Z"
+ content="""
+Having just set up <http://annex.debconf.org> which uses a git hook to run `git annex merge`, I can say that the main problems you are likely to run into are:
+
+1. The hook might be run with the cwd not set to the top of the git repository. cd to the git repository in the hook to fix.
+2. The hook might be run with `GIT_DIR` set to a strange value (in my case, it was set to \".\"), which is not the actual .git directory location. Unsetting it fixes that.
+
+I don't know about how to get git hooks to work on FAT filesystems though. Hooks have to be executable, and most systems probably don't mount such filesystems with executability allowed.
+"""]]
diff --git a/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_3_31ec762a0684d2ce87d229ed2924db93._comment b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_3_31ec762a0684d2ce87d229ed2924db93._comment
new file mode 100644
index 000000000..2a56b57e9
--- /dev/null
+++ b/doc/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/comment_3_31ec762a0684d2ce87d229ed2924db93._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlq495p0WtZDUpxzYN9YnToZGODfCGnqOw"
+ nickname="Stanis"
+ subject="comment 3"
+ date="2013-08-24T13:30:52Z"
+ content="""
+Thanks joey, that's exactly what was happening.
+
+Just to repeat it here, if anyone else runs into the same problem, your post-receive hook has to look like this:
+
+ #!/bin/sh
+ unset GIT_DIR
+ cd ..
+ git annex merge
+
+"""]]
diff --git a/doc/forum/Can_we_have_remotes_that_aren__39__t_tracked__63___/comment_1_35e5a963b9e58ed7773dfcb884f8ecbd._comment b/doc/forum/Can_we_have_remotes_that_aren__39__t_tracked__63___/comment_1_35e5a963b9e58ed7773dfcb884f8ecbd._comment
new file mode 100644
index 000000000..955c256ca
--- /dev/null
+++ b/doc/forum/Can_we_have_remotes_that_aren__39__t_tracked__63___/comment_1_35e5a963b9e58ed7773dfcb884f8ecbd._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:27:21Z"
+ content="""
+This seems like a reasonable request, so I've opened [[todo/untracked_remotes]]
+
+I will note that if you know the annex.uuid of the previous AAA repository, you can make the new one use that same uuid, just `git config annex.uuid $UUID`. (`git annex fsck --fast` would be a good idea after doing that.)
+"""]]
diff --git a/doc/forum/Change_remote_server_address.mdwn b/doc/forum/Change_remote_server_address.mdwn
new file mode 100644
index 000000000..722b4ada4
--- /dev/null
+++ b/doc/forum/Change_remote_server_address.mdwn
@@ -0,0 +1,6 @@
+Hi again,
+
+I have a SSH remote server that I registered to my git-annex repository via git-annex assistant. When I go to edit the settings for the repository from within git-annex assistant I noticed I can't edit the server address. If the server IP changes, how should I go about letting git-annex know of this? Can I just (1) shutdown git-annex assistant, (2) edit the 'url' line of the remote entry inside the repository's ``.git/config`` file, and then (3) start up git-annex assistant again? Is this a safe method for doing this?
+
+Regards,
+Blake
diff --git a/doc/forum/Change_remote_server_address/comment_1_401c3d2530ac7ba41dd3857ab4737ed5._comment b/doc/forum/Change_remote_server_address/comment_1_401c3d2530ac7ba41dd3857ab4737ed5._comment
new file mode 100644
index 000000000..1e4cbbf97
--- /dev/null
+++ b/doc/forum/Change_remote_server_address/comment_1_401c3d2530ac7ba41dd3857ab4737ed5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-01T16:35:47Z"
+ content="""
+Yes, you can certianly edit .git/config in any way you like and the assistant will use the new values when started back up.
+
+It shouldn't be using a hardcoded IP address normally, unless you manually entered an IP address when setting up that ssh remote. Using DNS is better..
+"""]]
diff --git a/doc/forum/Effectively_replicating_backup_files.mdwn b/doc/forum/Effectively_replicating_backup_files.mdwn
new file mode 100644
index 000000000..85d8f4b52
--- /dev/null
+++ b/doc/forum/Effectively_replicating_backup_files.mdwn
@@ -0,0 +1,25 @@
+I currently use duply/duplicity to back up my networked computers to my home server. I have two external HDDs and, every week or so, I bring one of these home and copy the backup files to the hard drive (I leave them on the server to easily restore files and because I have a large hard drive in that). I use some hand-written scripts to keep a copy these backup files in the cloud (Ubuntu One) until they have been copied to both hard drives, ensuring that there are always two copies of the files somewhere offsite. Out of paranoia, I also have some "standalone backups" that are just huge encrypted archives of important folders (say, my entire Photos directory) as at a certain date - in case for some reason duplicity ever stops working or I need to roll something back to a version years earlier. I am less worried about these standalone backups and manually keep one copy of each somewhere.
+
+It sounds like Git-Annex could automate things quite nicely (and give me some neat extras, like knowing where they were). This is how I understand I should do it, but please let me know if it is the right approach or if you have any suggestions:
+
+1. Create a folder on my server called "annex" and make a Git-Annex "large backup" repository in there.
+2. Create a folder within that called "archive" and put a "backup" folder within that. I understand that having the backups within an archive folder will mean that they aren't automatically copied to my desktop machines etc.
+3. Within that "backup" folder, create two folders, one called "duplicity" and one called "standalone". Put the backups in the respective folders.
+4. Set up gcrypt Git-Annex repositories on my two external HDDs as "small backups". This seems to just start copying files across. That surprised me, as the files are in the archive folder and I thought the default was numcopies=1. Is there some autosync option that I need to turn off? Ideally, I would like it to encrypt/decrypt primarily with my server GPG key (which I'm not worried about copying around my computers), but also encrypt to my personal GPG key (where I'd only put my public key on the server, but I know I will not lose the secret key for that). Am I right that to do that I would need to set the repos up manually with:
+
+ git init --bare /mnt/externalHDD1
+
+ git annex initremote externalHDD1 type=gcrypt gitrepo=/mnt/externalHDD1 keyid=$serverkey keyid=$personalkey
+
+ git annex sync externalHDD1
+
+ Or should the gitrepo be the location of my main Git-Annex repository? How do I make it sync up with my other repos?
+
+5. I understand that I would then need to set numcopies=3 in a .gitattributes file in the "archive/backup/duplicity" directory and, say, a numcopies=2 in the "archive/backup/standalone".
+6. I could then add a cloud repository as a "transfer" repository and Git-Annex should only keep files on that that are not already in the right number of places (similar to what my scripts are doing now).
+7. I have recently upgraded my hard drive, so I have my old 1TB internal hard drive that I will be putting in a cupboard somewhere. I was thinking that I could make this an archive drive for things like one copy of my duplicity/standalone backups. I wouldn't want it to be the only copy of anything. If I just set it as an archive drive, would this work?
+8. Are there more clever ways of doing this? I consider my external HDDs and the cloud repo as "offsite" repositories and ideally there would always be one copy of my backups offsite (in addition to at least three overall). There would also ideally be one of each of my files "live" (in most cases my server) that could instantly push files into a cloud repo and then to wherever I am. Is there any ability to put repositories in groups and write rules like that?
+
+Any thoughts greatly appreciated!
+
+Aaron
diff --git a/doc/forum/Effectively_replicating_backup_files/comment_1_b1ab0da82db076c5244b0dcc95282ddd._comment b/doc/forum/Effectively_replicating_backup_files/comment_1_b1ab0da82db076c5244b0dcc95282ddd._comment
new file mode 100644
index 000000000..54f7f782a
--- /dev/null
+++ b/doc/forum/Effectively_replicating_backup_files/comment_1_b1ab0da82db076c5244b0dcc95282ddd._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-07T16:42:14Z"
+ content="""
+This all sounds reasonable to me.
+
+gitrepo= is the location of the repository you are setting up with gcrypt, not your existing git-annex repository.
+
+numcopies configures the lower bound of the number of copies, not the upper bound. There's no \"small backup\" type, you must mean either small archive, or incremental backup. Either type of repository is going to want to have files that have not previously been archived, or backed up.
+
+You might eventually want to write your own [[preferred_content]] expressions to handle offsite repositories. I'd recommend starting simple and building up.
+"""]]
diff --git a/doc/forum/Effectively_replicating_backup_files/comment_2_472ab9c973b475f7f3ce7e3934f94281._comment b/doc/forum/Effectively_replicating_backup_files/comment_2_472ab9c973b475f7f3ce7e3934f94281._comment
new file mode 100644
index 000000000..668416c04
--- /dev/null
+++ b/doc/forum/Effectively_replicating_backup_files/comment_2_472ab9c973b475f7f3ce7e3934f94281._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnFjuvfPpi1kf6l54bxfFUm0Aw_Gf_IO0o"
+ nickname="Aaron"
+ subject="comment 2"
+ date="2013-11-07T19:46:32Z"
+ content="""
+Thanks Joey!
+
+> gitrepo= is the location of the repository you are setting up with gcrypt, not your existing git-annex repository.
+
+Great, thanks. If I set these up outside of the WebApp, what is the best way to link them up to my main repositories?
+
+> numcopies configures the lower bound of the number of copies, not the upper bound. There's no \"small backup\" type,
+> you must mean either small archive, or incremental backup. Either type of repository is going to want to have files
+> that have not previously been archived, or backed up.
+
+Yes, I meant incremental backup. Thanks, understood. The page on preferred content ( http://git-annex.branchable.com/preferred_content/ ) made things a bit clearer. I didn't realise that the incremental backups etc want a copy even if it isn't necessary to satisfy numcopies. Does that mean that once it is on one backup drive, it will not be sent to the other unless I increase numcopies?
+
+"""]]
diff --git a/doc/forum/Effectively_replicating_backup_files/comment_3_826493bd59b81786c1f6a56f1c438004._comment b/doc/forum/Effectively_replicating_backup_files/comment_3_826493bd59b81786c1f6a56f1c438004._comment
new file mode 100644
index 000000000..9088de9e7
--- /dev/null
+++ b/doc/forum/Effectively_replicating_backup_files/comment_3_826493bd59b81786c1f6a56f1c438004._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 3"
+ date="2013-11-08T17:06:02Z"
+ content="""
+The webapp can use remotes that you have configured at the command line just as well as it can use remotes you configure using the webapp.
+
+Each file only gets backed up to one incremental backup repository. If you have a full backup repository it will (try to) get another copy of every single file.
+"""]]
diff --git a/doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn b/doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn
deleted file mode 100644
index 38865f49a..000000000
--- a/doc/forum/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__.mdwn
+++ /dev/null
@@ -1 +0,0 @@
-Moved to [[bugs|bugs/Error_while_adding_a_file___34__createSymbolicLink:_already_exists__34__]] --[[Joey]]
diff --git a/doc/forum/Feature_Request:_add_filename_to_hash_objects.mdwn b/doc/forum/Feature_Request:_add_filename_to_hash_objects.mdwn
new file mode 100644
index 000000000..173cd2d94
--- /dev/null
+++ b/doc/forum/Feature_Request:_add_filename_to_hash_objects.mdwn
@@ -0,0 +1,6 @@
+hi,
+i just did git annex unused in 2 repos, one with WORM and one with SHA1.
+with WORM i instantly could see which file it was, with SHA1 not.
+
+so would it be possible to just add the first seen filename to the hashes identifier? the name could just be ignored but it would help with unused to see which file i am searching for.
+thanks!
diff --git a/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_1_73dc0a9cad486cf2d34faf064c6193b1._comment b/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_1_73dc0a9cad486cf2d34faf064c6193b1._comment
new file mode 100644
index 000000000..8a2f9fb00
--- /dev/null
+++ b/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_1_73dc0a9cad486cf2d34faf064c6193b1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-16T15:19:25Z"
+ content="""
+Adding a filename would defeat deduplication. You suggest adding the \"first seen\" filename, but then git-annex would need to maintain a lookup between hashes and hashes with the first seen filename to use when adding new files.
+
+There is already [[todo/wishlist: option to print more info with 'unused']].
+"""]]
diff --git a/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_2_f818b3ecfeb1d1dd83df4668c061718a._comment b/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_2_f818b3ecfeb1d1dd83df4668c061718a._comment
new file mode 100644
index 000000000..638492822
--- /dev/null
+++ b/doc/forum/Feature_Request:_add_filename_to_hash_objects/comment_2_f818b3ecfeb1d1dd83df4668c061718a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="orb"
+ ip="178.11.228.69"
+ subject="comment 2"
+ date="2013-10-17T21:12:09Z"
+ content="""
+thanks! (i hope a thanks is wanted, i know people who are just distracted and consider \"thanks\" posts unnecessary)
+"""]]
diff --git a/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files.mdwn b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files.mdwn
new file mode 100644
index 000000000..827383f9f
--- /dev/null
+++ b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files.mdwn
@@ -0,0 +1 @@
+With numcopies it is possible to control how many copies there should be of a file overall in all of the remotes. Is it also possible, using .gitattributes or something else, to force one of the repos (e.g. a server) to contain a copy of all files, or does this have to be done manually?
diff --git a/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_1_702b1b94c735f1b9cde16daa77a80c12._comment b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_1_702b1b94c735f1b9cde16daa77a80c12._comment
new file mode 100644
index 000000000..d964a253b
--- /dev/null
+++ b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_1_702b1b94c735f1b9cde16daa77a80c12._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="99.54.57.201"
+ subject="comment 1"
+ date="2013-09-14T20:36:53Z"
+ content="""
+That is what the \"backup\" preferred content group is for. Depending on how your repos connect to each other it might take some more trickery to make all content migrate to it, but that will make it \"want\" all the files if it can get them.
+"""]]
diff --git a/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_2_3df7fcbcd482bb9377ead238b314995b._comment b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_2_3df7fcbcd482bb9377ead238b314995b._comment
new file mode 100644
index 000000000..e59af71fb
--- /dev/null
+++ b/doc/forum/Forcing_one_repo_to_contain_a_copy_of_all_files/comment_2_3df7fcbcd482bb9377ead238b314995b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="Ed's right"
+ date="2013-09-19T18:56:39Z"
+ content="""
+What we don't have is something to enforce a particular preferred content setting. Ie, refuse to allow dropping a file from a repo if it's preferred content there. Currently you have to remember to use `git annex drop --auto` to cause the preferred content to be honored.
+"""]]
diff --git a/doc/forum/GPG_passphrase_handling.txt b/doc/forum/GPG_passphrase_handling.txt
new file mode 100644
index 000000000..b0f82cb89
--- /dev/null
+++ b/doc/forum/GPG_passphrase_handling.txt
@@ -0,0 +1,76 @@
+[[!meta title="GPG passphrase handling on OSX"]]
+
+Hello!
+I'm using OSX 10.9 and have installed gpg (and gpg2, if it matters) through
+homebrew and git-annex through cabal. I also installed
+https://github.com/joeyh/git-remote-gcrypt like the UI told me.
+
+Whenever I'm trying to add an encrypted remote through the web UI I get a
+lot of "You need a passphrase to unlock the secret key for user:" on stdout
+and, obviously, I can't enter my passphrase (If I could I wouldn't make this
+post to begin with :))
+Is this behavior normal? What should I do to work around it?
+I did also try to not use the web UI by using this command:
+git annex initremote rsync.net type=gcrypt gitrepo=user@host:directory encryption=pubkey keyid=X
+
+Because of this I can't copy files to my remotes. All I get is:
+-----
+$ git annex copy --to rsync.net
+copy MySecretFile (gpg)
+You need a passphrase to unlock the secret key for
+user: "user"
+4096-bit RSA key, ID X, created 2013-10-01 (main key ID Y)
+
+(checking rsync.net...) (to rsync.net...) gpg: no valid addressees
+gpg: [stdin]: encryption failed: No user ID
+failed
+-----
+
+Yes, I am using gpg-agent. When other applications ask for my passphrase I get
+the pinentry dialog from GPGTools, just like I've configured it in
+~/.gnupg/gpg-agent.conf, but this isn't the case with git-annex.
+
+If I remove GPGTools from /usr/local/bin with: ``brew link --overwrite gnupg &&
+brew link --overwrite gnupg2'' it works *slightly* better.
+I get that pinentry dialog I want but when I do a copy I get:
+-----
+$ git annex copy --to rsync.net
+copy MySecretFile (gpg) (checking rsync.net...) (to rsync.net...) gpg: no valid addressees
+gpg: [stdin]: encryption failed: no such user id
+failed
+-----
+
+--debug shows me it is executing gpg llke so:
+-----
+gpg ["--batch","--no-tty","--use-agent","--quiet","--trust-model","always","--batch","--encrypt","--no-encrypt-to","--no-default-recipient","--force-mdc","--no-textmode"]
+-----
+
+$ git annex version
+git-annex version: 4.20131024
+build flags: Assistant Webapp 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 glacier hook
+
+$ gpg --version
+gpg (GnuPG) 2.0.22
+libgcrypt 1.5.3
+Copyright (C) 2013 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Home: ~/.gnupg
+Supported algorithms:
+Pubkey: RSA, ELG, DSA, ?, ?
+Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
+ CAMELLIA128, CAMELLIA192, CAMELLIA256
+Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
+Compression: Uncompressed, ZIP, ZLIB, BZIP2
+
+ $ gpg-agent --version
+gpg-agent (GnuPG/MacGPG2) 2.0.22
+libgcrypt 1.5.3
+Copyright (C) 2013 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff --git a/doc/forum/GPG_passphrase_handling/comment_1_11ba130e8bea6698858d0a1a5b01830f._comment b/doc/forum/GPG_passphrase_handling/comment_1_11ba130e8bea6698858d0a1a5b01830f._comment
new file mode 100644
index 000000000..f2709f18c
--- /dev/null
+++ b/doc/forum/GPG_passphrase_handling/comment_1_11ba130e8bea6698858d0a1a5b01830f._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
+ nickname="dxtrish"
+ subject="comment 1"
+ date="2013-10-31T00:06:22Z"
+ content="""
+In fact I just tried this with a key without a passphrase and I STILL get:
+
+[2013-10-31 01:00:50 CET] Pusher: Syncing with rsync.net
+gpg: no valid addressees
+gpg: [stdin]: encryption failed: no such user id
+
+In addition I also noticed a lot of:
+git-annex: fd:28: hPutBuf: resource vanished (Broken pipe)
+"""]]
diff --git a/doc/forum/GPG_passphrase_handling/comment_2_ef9d58d15b7bbe0b3c7140bb01d73a31._comment b/doc/forum/GPG_passphrase_handling/comment_2_ef9d58d15b7bbe0b3c7140bb01d73a31._comment
new file mode 100644
index 000000000..d15248ab7
--- /dev/null
+++ b/doc/forum/GPG_passphrase_handling/comment_2_ef9d58d15b7bbe0b3c7140bb01d73a31._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
+ nickname="dxtrish"
+ subject="comment 2"
+ date="2013-10-31T02:42:47Z"
+ content="""
+I think I have found two ways I can make this happen.
+
+1) If a filename contains UTF-8 it seems to happen (At least with this specific filename I have right here)
+
+2) Finder.app does not seem to play nice with git-annex (I got the same error when I tried using Finder to copy files to my git-annex thing)
+
+
+
+"""]]
diff --git a/doc/forum/GPG_passphrase_handling/comment_3_84eb129c8483b87b3ae6ecaf8b4a8309._comment b/doc/forum/GPG_passphrase_handling/comment_3_84eb129c8483b87b3ae6ecaf8b4a8309._comment
new file mode 100644
index 000000000..298e2f13d
--- /dev/null
+++ b/doc/forum/GPG_passphrase_handling/comment_3_84eb129c8483b87b3ae6ecaf8b4a8309._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T20:39:36Z"
+ content="""
+There seem to be a lot of different ways to install gpg on OSX, with different results in what works and not. I don't know what's going on with that. Advice from those who understand Mac OS would be appreciated.
+
+As far as the \"gpg: no valid addressees\" bug goes, I can reproduce it on Linux, and have fixed it. Only affected using gcrypt with encryption=pubkey.
+
+(Please file bug reports in [[bugs]] in the future, not in the forum!)
+"""]]
diff --git a/doc/forum/GPG_passphrase_handling/comment_4_8724297f6d7ac140ab395a940bab0d7d._comment b/doc/forum/GPG_passphrase_handling/comment_4_8724297f6d7ac140ab395a940bab0d7d._comment
new file mode 100644
index 000000000..983c35c3a
--- /dev/null
+++ b/doc/forum/GPG_passphrase_handling/comment_4_8724297f6d7ac140ab395a940bab0d7d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
+ nickname="dxtrish"
+ subject="comment 4"
+ date="2013-11-03T13:10:11Z"
+ content="""
+I would have filed it in the bug section if I knew it was a bug. I just thought I had done something wrong :)
+"""]]
diff --git a/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__.mdwn b/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__.mdwn
new file mode 100644
index 000000000..0a3aac911
--- /dev/null
+++ b/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__.mdwn
@@ -0,0 +1,11 @@
+Hi,
+
+I am trying to use Git Annex Assistant on my Fedora Linux computer. I currently have a local repository that assistant monitors, but now I want to use my personal server as a git remote for the repository. I click on Configuration > Remote server and it prompts me for my server login credentials and then click the "Check this server" button. After this I am shown a screen that assistant is "Ready to add remote server" and then states:
+> The server <MY IP ADDRESS HERE> can be used as is, but installing git-annex on it would make it work better, and provide more options below.
+>
+> If you're able to install software on the server, do so and click Retry
+
+The information shown below this message is regarding encrypting the data (if I have git-annex installed on the server, which I don't). So my question is, what do I do now? There is no button to just add the remote from within git annex assistant? I created a bare repository on my server and added a remote manually inside the repository on my local machine, but git annex assistant doesn't notice it. I'm clueless on what git annex assistant is expecting from me at this point. I would think what I'm trying to do is one of the most common use cases for git annex, but I can't find any documentation or materials on the correct procedure for this. Any help is appreciated.
+
+Regards,
+Blake
diff --git a/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__/comment_1_d0a3d0090928790d5a05e9f8e5f05320._comment b/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__/comment_1_d0a3d0090928790d5a05e9f8e5f05320._comment
new file mode 100644
index 000000000..5c3a596a5
--- /dev/null
+++ b/doc/forum/Git_Annex_Assistant:_How_to_add_a_remote__63__/comment_1_d0a3d0090928790d5a05e9f8e5f05320._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-21T22:20:53Z"
+ content="""
+You have two choices:
+
+1. Install git-annex on your server. You can then use the webapp to set up a git repository, or use the git repository you've already set up.
+
+2. Don't install git-annex on your server. Select the option in the webapp to use an encrypred rsync repository on your server. (The screen you described the webapp showing had a button to use this option, but you seem to have misread it.)
+"""]]
diff --git a/doc/forum/Git_annex___39__corrupting__39___itself.mdwn b/doc/forum/Git_annex___39__corrupting__39___itself.mdwn
new file mode 100644
index 000000000..fe1edc17d
--- /dev/null
+++ b/doc/forum/Git_annex___39__corrupting__39___itself.mdwn
@@ -0,0 +1,34 @@
+Hi,
+
+Since the I updated to `2013-10-24` `git annex` has corrupted itself twice on my setup. I'm not claiming causality here and thus I haven't filled it as a bug (probably the mistake is mine).
+
+I use three laptops and one remote ssh server. The motherboard on laptop *T* seems to have broken and I haven't fixed it yet. I have disabled sync to *T* on the webapp dashboard.
+
+First, one computer, called *W*, broke on Friday. I got the dreaded [serious problem](http://git-annex.branchable.com/devblog/day_41__onward/) screen. `git fsck` reported lots of missing blobs and tree problem, though my data seemed OK. I git cloned the repo from computer *X*. Now, last night both X and W reported the same problem (log below). *W* recovered itself somehow, but *X* is now in a cycle of re-adding all files in the repo and the posting the below error that has to do with computer *T* (IP ending with 107).
+
+I would appreciate hints on why this suddenly started happen. Computer T has been out of sync for almost 14 days (since the 24th of October I think).
+
+ error: refs/remotes/192.168.1.107_annex/git-annex does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/master does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/synced/git-annex does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/synced/master does not point to a valid object!
+ error: refs/synced/2ed58ecf-8e8c-44b8-ad34-d42ddfb35315/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/git-annex does not point to a valid object!
+ error: refs/synced/2ed58ecf-8e8c-44b8-ad34-d42ddfb35315/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/master does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/git-annex does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/master does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/git-annex does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/master does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/git-annex does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/master does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/synced/git-annex does not point to a valid object!
+ error: refs/remotes/192.168.1.107_annex/synced/master does not point to a valid object!
+ error: refs/synced/2ed58ecf-8e8c-44b8-ad34-d42ddfb35315/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/git-annex does not point to a valid object!
+ error: refs/synced/2ed58ecf-8e8c-44b8-ad34-d42ddfb35315/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/master does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/git-annex does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/cmFzbXVzQGNvZGVyb2xsZXJzLmNvbQ==/master does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/git-annex does not point to a valid object!
+ error: refs/synced/f54b8200-8ec1-43d2-8710-b73ec118addc/master does not point to a valid object!
+ error: invalid object 100644 1ca66de3cdd9c79cde26a7555cf3b8d26d0e371d for '000/147/SHA256E-s347--1ab8084bf9ae06407ce0a7260a83638ea6e9a028dc59b4815fd60aec61dbd747.txt.log.log'
+ fatal: git-write-tree: error building trees
+ TransferScanner crashed: failed to read sha from git write-tree
+ [2013-11-04 09:45:41 CET] TransferScanner: warning TransferScanner crashed: failed to read sha from git write-tree
diff --git a/doc/forum/Git_annex___39__corrupting__39___itself/comment_1_bcf50a215e2f8771e098aadfff4c300c._comment b/doc/forum/Git_annex___39__corrupting__39___itself/comment_1_bcf50a215e2f8771e098aadfff4c300c._comment
new file mode 100644
index 000000000..2fe95ab33
--- /dev/null
+++ b/doc/forum/Git_annex___39__corrupting__39___itself/comment_1_bcf50a215e2f8771e098aadfff4c300c._comment
@@ -0,0 +1,43 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEXAlu8qKv_FHYOv-uEohdGgMY_Lw-Ges"
+ nickname="Jonas"
+ subject="Just happened for me as well."
+ date="2013-11-12T08:10:56Z"
+ content="""
+This was the first search result when I googled the error message, I'm not sure what has happened (or if it is a problem since I don't change my files that often).
+
+git-annex version: 4.20131101
+
+Also running git annex with one ssh remote ( laptop1 & laptop2 synching through a ssh remote server ).
+
+Got a bunch of
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/git-annex does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/master does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/git-annex does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/master does not point to a valid object!
+when I tried a manual git annex sync, and noticed that I had a bunch of those in the log in the webapp as well...
+
+The gui doesn't show that anything is wrong, and looking at the log it seems that things are atleast uploading
+
+ [2013-11-12 09:05:46 CET] Committer: Committing changes to git
+ [2013-11-12 09:05:46 CET] Pusher: Syncing with born
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/git-annex does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/master does not point to a valid object!
+ Everything up-to-date
+
+ FILE
+
+ 32768 42% 0.00kB/s 0:00:00
+ 76972 100% 42.16MB/s 0:00:00 (xfer#1, to-check=0/1)
+
+ sent 77056 bytes received 31 bytes 51391.33 bytes/sec
+ total size is 76972 speedup is 1.00
+ [2013-11-12 09:05:48 CET] Transferrer: Uploaded FILE
+ [2013-11-12 09:05:48 CET] Pusher: Syncing with born
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/git-annex does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/master does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/git-annex does not point to a valid object!
+ error: refs/synced/dbb70cea-4b83-416f-93af-e59082c4d633/master does not point to a valid object!
+ To ssh://me@born/annex
+ 54e04cf..333cf10 git-annex -> synced/git-annex
+"""]]
diff --git a/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_75f957e7be6c1ad8936c0a2a5374db3e._comment b/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_75f957e7be6c1ad8936c0a2a5374db3e._comment
new file mode 100644
index 000000000..80f778bb1
--- /dev/null
+++ b/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_75f957e7be6c1ad8936c0a2a5374db3e._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEXAlu8qKv_FHYOv-uEohdGgMY_Lw-Ges"
+ nickname="Jonas"
+ subject="comment 3"
+ date="2013-11-13T09:03:24Z"
+ content="""
+I did a change of one of the files and that totally broke all other repositories, git fsck reports a lot of missing trees (I'm not sure if it is normal), and git annex fsck started reporting invalid object for another file for some reason, also got a (git annex repair still reports everything is fine though.)
+
+ fatal: git-write-tree: error building trees
+ git-annex: failed to read sha from git write-tree
+
+
+
+I tried following those instructions but I don't think I had a good repository, git annex repair reported everything was ok but git fsck said a lot of trees where missing and it stopped updating.
+I noticed I was running different git version (git version 1.7.9.5 on the server and git version 1.8.4.2 on one of the clients), so maybe that was part of the reason.
+
+I couldn't find out what remote dbb70cea-4b83-416f-93af-e59082c4d633 was supposed to be either, it wasn't any of the active ones and it didn't show up with git annex status either (I've lost a few repositories when I reinstalled my computer).
+
+I ended up recreating the repository (by copying the raw files) from what I think is the most recent version from one of my computers and hope that it was a error that happened due to upgrades.
+"""]]
diff --git a/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_ab062b1df3b55fd49852a6220c98249e._comment b/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_ab062b1df3b55fd49852a6220c98249e._comment
new file mode 100644
index 000000000..76e9d00de
--- /dev/null
+++ b/doc/forum/Git_annex___39__corrupting__39___itself/comment_3_ab062b1df3b55fd49852a6220c98249e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 3"
+ date="2013-11-12T17:19:32Z"
+ content="""
+I have been getting this too. Here is what I have done to fix it:
+
+[[tips/recovering_from_a_corrupt_git_repository]]
+"""]]
diff --git a/doc/forum/Git_annex_assistant_on_EC2.mdwn b/doc/forum/Git_annex_assistant_on_EC2.mdwn
new file mode 100644
index 000000000..27f20ae46
--- /dev/null
+++ b/doc/forum/Git_annex_assistant_on_EC2.mdwn
@@ -0,0 +1,5 @@
+With Amazon EC2, it is possible to take a snapshot of the virtual machine and then bring up multiple instances based on the snapshot.
+
+If I configure git annex assistant to sync a folder to S3, will it work correctly if I spin up multiple instances, all identical git annex assistant configurations?
+
+My use case is to allow users of my forums to upload attachments with their posts. The attachments are stored locally on disk, but I'm hoping that git annex assistant can help synchroise the attachments across all forum instances (I usually run only 1 instance, but their could be as many as 3 under heavy load).
diff --git a/doc/forum/Git_annex_assistant_on_EC2/comment_1_bbdb4611373117a2176c225378110a05._comment b/doc/forum/Git_annex_assistant_on_EC2/comment_1_bbdb4611373117a2176c225378110a05._comment
new file mode 100644
index 000000000..cab80f976
--- /dev/null
+++ b/doc/forum/Git_annex_assistant_on_EC2/comment_1_bbdb4611373117a2176c225378110a05._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmBUR4O9mofxVbpb8JV9mEbVfIYv670uJo"
+ nickname="Justin"
+ subject="comment 1"
+ date="2013-09-06T22:57:05Z"
+ content="""
+If you are using ec2 and s3 why don't you just serve the attachments directly from s3? Not sure how git-annex adds anything here.
+"""]]
diff --git a/doc/forum/Git_annex_assistant_on_EC2/comment_2_614ed11f7134137d6376d36a61c293f5._comment b/doc/forum/Git_annex_assistant_on_EC2/comment_2_614ed11f7134137d6376d36a61c293f5._comment
new file mode 100644
index 000000000..dfb629d62
--- /dev/null
+++ b/doc/forum/Git_annex_assistant_on_EC2/comment_2_614ed11f7134137d6376d36a61c293f5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.251.174"
+ subject="comment 2"
+ date="2013-09-07T17:08:27Z"
+ content="""
+You are going to need to make each repository have a distinct UUID. Otherwise, the assistant will get confused.
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows.mdwn b/doc/forum/Git_annex_on_Windows.mdwn
new file mode 100644
index 000000000..b5ca80bee
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows.mdwn
@@ -0,0 +1,11 @@
+Hi,
+I want to download some files in git and git annex in Windows OS.
+I have installed msysgit for git-scm in D:\Git directory,
+Now I download git-annex assistant for Windows, and install it
+in D:\Git\cmd directory.
+But when I run the command "git annex" in git-bash, it says it can not
+found the "git annex" command.
+My question is that, how should I use git annex in Windows to download files?
+For example, git annex get <filename>.
+Doea anyone has any idear to help me figure it out?
+Thanks in advance!
diff --git a/doc/forum/Git_annex_on_Windows/comment_1_da24ba0219a164f9ab93fe75dd85127e._comment b/doc/forum/Git_annex_on_Windows/comment_1_da24ba0219a164f9ab93fe75dd85127e._comment
new file mode 100644
index 000000000..be50ece07
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_1_da24ba0219a164f9ab93fe75dd85127e._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.251.174"
+ subject="comment 1"
+ date="2013-09-07T17:00:03Z"
+ content="""
+Are you able to run git commands? IIRC msysgit prompts when it's installed about whether you want to put it in the path or not. git-annex just piggybacks on this path setting. It is installed in the same folder as the git.exe and should work as long as that is in path.
+Otherwise, consult windows documentation to add git-annex to the path, or you can copy the git-annex.exe to somewhere else I suppose.
+
+I built a clean Windows system yesterday and have just re-tested it and it does work.
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_2_c0880ce3ee13d388ab5b46a740170845._comment b/doc/forum/Git_annex_on_Windows/comment_2_c0880ce3ee13d388ab5b46a740170845._comment
new file mode 100644
index 000000000..bdf30b3b7
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_2_c0880ce3ee13d388ab5b46a740170845._comment
@@ -0,0 +1,50 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkQrsXK-icnYXg6kJNd-jDjMgOixnhwE34"
+ nickname="x"
+ subject="reply to Comment 1"
+ date="2013-09-10T13:46:45Z"
+ content="""
+Thanks for your helpful comment.I add the path to windows, and the
+problem disappears now.
+But I meet another problem when I download the data using git annex.
+I use the command \"git annex get foo.nc\" to download data. The foo.nc
+is actually symlink. For example:
+foo.nc -> ../../.git/annex/objects/jK/v7/WORM-s16009120-m1337754158--
+foo.nc/WORM-s16009120-m1337754158--foo.nc
+Could you help me to figure it out?
+Thank you.
+
+The erro information when using git annex in Windows, is as below:
+
+$ git annex get tau.nc
+
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+
+*** Please tell me who you are.
+
+
+
+Run
+
+ git config --global user.email \"you@example.com\"
+
+ git config --user.name \"Your Name\"
+
+to set your account's default identity.
+
+Omit --global to set the identity only in this repository.
+
+
+
+fatal: unable to auto-detect email address (got 'xshao@DELL-PC.(none')
+
+git-annex :tau.nc not found
+
+(Recording state in git ...)
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_3_70c22716fde60d14fd0c7e74acf4a224._comment b/doc/forum/Git_annex_on_Windows/comment_3_70c22716fde60d14fd0c7e74acf4a224._comment
new file mode 100644
index 000000000..772d9348a
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_3_70c22716fde60d14fd0c7e74acf4a224._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkQrsXK-icnYXg6kJNd-jDjMgOixnhwE34"
+ nickname="x"
+ subject="Comment3"
+ date="2013-09-10T15:36:57Z"
+ content="""
+In addition, because the file is actually symlink direct to the data stored in Amazon S3
+How could I get the URL, given the symlink for git annex. For example:
+foo.nc -> ../../.git/annex/objects/jK/v7/WORM-s16009120-m1337754158--foo.nc/WORM-s16009120-m1337754158--foo.nc
+Thank you.
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_4_b9232deab6bc5036d7339aa202013218._comment b/doc/forum/Git_annex_on_Windows/comment_4_b9232deab6bc5036d7339aa202013218._comment
new file mode 100644
index 000000000..6fd2f8c3d
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_4_b9232deab6bc5036d7339aa202013218._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 4"
+ date="2013-09-12T20:58:30Z"
+ content="""
+Once `git annex get` has downloaded the file, it will replace the symlink with the contents of the file.
+
+If that is not happening, you might try running `git annex fsck`
+
+
+"""]]
diff --git a/doc/forum/Git_annex_on_Windows/comment_5_27af3c431b50b540d2bd1d3af3f21080._comment b/doc/forum/Git_annex_on_Windows/comment_5_27af3c431b50b540d2bd1d3af3f21080._comment
new file mode 100644
index 000000000..5db96f08e
--- /dev/null
+++ b/doc/forum/Git_annex_on_Windows/comment_5_27af3c431b50b540d2bd1d3af3f21080._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 5"
+ date="2013-09-13T18:03:17Z"
+ content="""
+Turns out that there was a bug in the Windows port that could lead to the behavior described, and another bug that prevented `git annex fsck` from fixing it. I have fixed both bugs, so you should upgrade and then run `git annex fsck`.
+"""]]
diff --git a/doc/forum/Help_Windows_walkthrough.mdwn b/doc/forum/Help_Windows_walkthrough.mdwn
new file mode 100644
index 000000000..dbe61b556
--- /dev/null
+++ b/doc/forum/Help_Windows_walkthrough.mdwn
@@ -0,0 +1,177 @@
+Hello,
+
+i am trying to run the walkthrough on Windows 7. When i try to get the contents of a file, i only get a some git annex text string and not the real file. Both repositories are on the same ntfs filesystem.
+
+C:\tmp>git annex version
+git-annex version: 4.20130827-g4f18612
+build flags: Pairing Testsuite S3 WebDAV DNS
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 2
+
+C:\tmp\server>git --version
+git version 1.8.3.msysgit.0
+
+
+# walkthrough.bat
+
+ doskey /history > commands.log
+ mkdir laptop
+ cd laptop
+ git init
+ git annex init laptop
+ cd ..
+
+ git clone laptop server
+ cd server
+ git annex init server
+ git remote add laptop c:\tmp\laptop
+
+ cd ..\laptop
+ git remote add server c:\tmp\server
+ copy ..\1.pdf .
+ git annex add 1.pdf
+ git commit -m add
+ dir
+
+ cd ..\server
+ dir
+ git fetch laptop
+ git merge laptop/master
+ git annex get 1.pdf
+ dir
+ type 1.pdf
+
+
+# walkthrough.log
+
+ C:\tmp>walkthrough.bat
+
+ C:\tmp>doskey /history 1>commands.log
+
+ C:\tmp>mkdir laptop
+
+ C:\tmp>cd laptop
+
+ C:\tmp\laptop>git init
+ Initialized empty Git repository in C:/tmp/laptop/.git/
+
+ C:\tmp\laptop>git annex init laptop
+ init laptop
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ ok
+ (Recording state in git...)
+
+ C:\tmp\laptop>cd ..
+
+ C:\tmp>git clone laptop server
+ Cloning into 'server'...
+ done.
+ warning: remote HEAD refers to nonexistent ref, unable to checkout.
+
+
+ C:\tmp>cd server
+
+ C:\tmp\server>git annex init server
+ init server
+ Detected a crippled filesystem.
+
+ Enabling direct mode.
+
+ Detected a filesystem without fifo support.
+
+ Disabling ssh connection caching.
+ ok
+ (Recording state in git...)
+
+ C:\tmp\server>git remote add laptop c:\tmp\laptop
+
+ C:\tmp\server>cd ..\laptop
+
+ C:\tmp\laptop>git remote add server c:\tmp\server
+
+ C:\tmp\laptop>copy ..\1.pdf .
+ 1 file(s) copied.
+
+ C:\tmp\laptop>git annex add 1.pdf
+ add 1.pdf (checksum...) ok
+ (Recording state in git...)
+
+ C:\tmp\laptop>git commit -m add
+ [master (root-commit) 7ad1514] add
+ 1 file changed, 1 insertion(+)
+ create mode 120000 1.pdf
+
+ C:\tmp\laptop>dir
+ Volume in drive C has no label.
+ Volume Serial Number is x
+
+ Directory of C:\tmp\laptop
+
+ 09/01/2013 11:03 AM <DIR> .
+ 09/01/2013 11:03 AM <DIR> ..
+ 08/30/2013 12:43 PM 37,500 1.pdf
+ 1 File(s) 37,500 bytes
+ 2 Dir(s) 7,698,817,024 bytes free
+
+ C:\tmp\laptop>cd ..\server
+
+ C:\tmp\server>dir
+ Volume in drive C has no label.
+ Volume Serial Number is x
+
+ Directory of C:\tmp\server
+
+ 09/01/2013 11:03 AM <DIR> .
+ 09/01/2013 11:03 AM <DIR> ..
+ 0 File(s) 0 bytes
+ 2 Dir(s) 7,698,817,024 bytes free
+
+ C:\tmp\server>git fetch laptop
+ remote: Counting objects: 9, done.
+ remote: Compressing objects: 100% (6/6), done.
+ remote: Total 8 (delta 1), reused 0 (delta 0)
+ Unpacking objects: 100% (8/8), done.
+ From c:\tmp\laptop
+ * [new branch] git-annex -> laptop/git-annex
+ * [new branch] master -> laptop/master
+
+ C:\tmp\server>git merge laptop/master
+
+ C:\tmp\server>git annex get 1.pdf
+ get 1.pdf (merging laptop/git-annex origin/git-annex into git-annex...)
+ (Recording state in git...)
+ (from laptop...)
+ 1.pdf
+ 37500 100% 4.51MB/s 0:00:00 (xfer#1, to-check=0/1)
+
+ sent 37573 bytes received 31 bytes 75208.00 bytes/sec
+ total size is 37500 speedup is 1.00
+ ok
+ (Recording state in git...)
+
+ C:\tmp\server>dir
+ Volume in drive C has no label.
+ Volume Serial Number is x
+
+ Directory of C:\tmp\server
+
+ 09/01/2013 11:03 AM <DIR> .
+ 09/01/2013 11:03 AM <DIR> ..
+ 09/01/2013 11:03 AM 194 1.pdf
+ 1 File(s) 194 bytes
+ 2 Dir(s) 7,698,767,872 bytes free
+
+ C:\tmp\server>type 1.pdf
+ .git/annex/objects/kM/0q/SHA256E-s37500--32d8190c7e189d45f48245a100e4cc981ea1bbc
+ 02ac8bfa6188db73e41ce06f3.pdf/SHA256E-s37500--32d8190c7e189d45f48245a100e4cc981e
+ a1bbc02ac8bfa6188db73e41ce06f3.pdfC:\tmp\server>
+ C:\tmp\server>
+
diff --git a/doc/forum/Help_Windows_walkthrough/comment_1_5fc22393a1b28235eabb2871ad83d0a7._comment b/doc/forum/Help_Windows_walkthrough/comment_1_5fc22393a1b28235eabb2871ad83d0a7._comment
new file mode 100644
index 000000000..95623a645
--- /dev/null
+++ b/doc/forum/Help_Windows_walkthrough/comment_1_5fc22393a1b28235eabb2871ad83d0a7._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.7"
+ subject="comment 1"
+ date="2013-09-03T17:59:03Z"
+ content="""
+The walkthrough assumes a system that uses indirect mode by default, so it won't work quite right on Windows, which is forced to use direct mode.
+
+Running `git annex fsck` in the server repository will fix up this situation, but the right thing on Windows is to use `git annex sync` rather than the manual `git fetch + git merge` the walkthrough shows.
+
+Guess I'll make the walkthrough use sync, although it may make it harder for people to understand what's going on internally.
+"""]]
diff --git a/doc/forum/Help_on_my_usecase.mdwn b/doc/forum/Help_on_my_usecase.mdwn
new file mode 100644
index 000000000..ef670aa25
--- /dev/null
+++ b/doc/forum/Help_on_my_usecase.mdwn
@@ -0,0 +1,22 @@
+I am using git-annex assistant for a few months now and still don't think I have it all setup correctly. My setup is:
+
+* Laptop Computer with low storage. Content creator, assistant: file source
+* Desktop Computer with medium storage capacity. Consumer, assistant: manual Mode
+* 2TB USB HD (EXT4) Backup, assistant: full backup
+* 2.5" portable 500GB drive NTFS formatted. transfer to backup: assistant: tried transfer and partial backup
+* Root Server on the web, not yet in the mix. Planned: Index only / content creator
+
+My primary goal is getting the stuff from the Laptop to the 2TB USB drive, syncing the annex with the desktop so I can get files on the desktop from the backup.
+What works:
+
+* Checking stuff into the annex on the Laptop
+* When the 2TB drive is connected to the Laptop, stuff is automatically moved there too
+* Bare Repo on the 2.5" configured as partial backup automatically backups the data
+
+What doesn't work:
+
+* Connecting the 2.5" bare repo to the Desktop to move stuff to the backup drive automatically
+* Having a human readable folder Structure on the 2.5" NTFS drive. I'd be ok to have a bare repo plus a special remote on the drive, but I don't know how to configure it
+* How do I drop stuff from the bare repo on the 2.5" drive? I think a partial backup should drop content that is in a full backup, but it doesn't
+
+Thanks for reading this long post. If anyone has any tips on how to configure the assistant, thats much appreciated.
diff --git a/doc/forum/Help_on_my_usecase/comment_1_a35b35c7927640f21d47c3df4f91dabb._comment b/doc/forum/Help_on_my_usecase/comment_1_a35b35c7927640f21d47c3df4f91dabb._comment
new file mode 100644
index 000000000..25116a7c4
--- /dev/null
+++ b/doc/forum/Help_on_my_usecase/comment_1_a35b35c7927640f21d47c3df4f91dabb._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-09T18:18:49Z"
+ content="""
+An incremental backup is supposed to drop content once it reaches a full backup. But, the assistant can only do that if it's able to verify that the full backup drive (or some other repository it can access) has a file, at the same time it's dropping it from the incremental backup drive. If you don't have both the incremental and full backup drives plugged in at the same time, you could consider making git-annex [[trust]] the full backup drive, which would avoid this explicit check.
+
+It sounds like you want a non-bare git repository on the 2.5\" drive. The assistant does not currently support setting that up, but you can do it by just using `git clone` as shown in the [[walkthrough]].
+
+I'm not clear on what doesn't work when you connect the 2.5\" drive to your desktop.
+"""]]
diff --git a/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__.mdwn b/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__.mdwn
new file mode 100644
index 000000000..a4bcc4843
--- /dev/null
+++ b/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__.mdwn
@@ -0,0 +1 @@
+I had accidentally chosen the wrong directory for the repository. What should I do to clean all of git-annex?
diff --git a/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__/comment_1_e14757c2c106770c2d7069ace4987b3b._comment b/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__/comment_1_e14757c2c106770c2d7069ace4987b3b._comment
new file mode 100644
index 000000000..b051aa704
--- /dev/null
+++ b/doc/forum/How_do_I_cleanly_remove_an_Android_git-annex_installation__63__/comment_1_e14757c2c106770c2d7069ace4987b3b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T18:43:08Z"
+ content="""
+It should be sufficient to delete `/sdcard/git-annex.home` and delete the .git directory inside whatever directory you set up as the repository.
+"""]]
diff --git a/doc/forum/How_to_cancel_an_add__63__.mdwn b/doc/forum/How_to_cancel_an_add__63__.mdwn
new file mode 100644
index 000000000..e0b0f1c8f
--- /dev/null
+++ b/doc/forum/How_to_cancel_an_add__63__.mdwn
@@ -0,0 +1,5 @@
+What is the safest way to cancel a `git annex add` before the first commit?
+
+Say I first added a directory with a lot of small files to the annex and then (while watching the endless list of checksum operations) decide I should actually put them in a tar file and annex that instead.
+
+The problem seems to be that `git annex add` immediately replaces the files with symlinks instead of waiting for a commit, so I can't just `git reset largedir/; tar cvfz largedir.tgz largedir/; git annex add largedir.tgz`.
diff --git a/doc/forum/How_to_cancel_an_add__63__/comment_1_f768ce5dc7c76f96ee6eb352f167be44._comment b/doc/forum/How_to_cancel_an_add__63__/comment_1_f768ce5dc7c76f96ee6eb352f167be44._comment
new file mode 100644
index 000000000..cef938469
--- /dev/null
+++ b/doc/forum/How_to_cancel_an_add__63__/comment_1_f768ce5dc7c76f96ee6eb352f167be44._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-03T00:50:48Z"
+ content="""
+Run `git annex unannex` on the files.
+"""]]
diff --git a/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__.mdwn b/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__.mdwn
new file mode 100644
index 000000000..0e72582d3
--- /dev/null
+++ b/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__.mdwn
@@ -0,0 +1,14 @@
+Hello,
+
+I want to be safe and have two copies of my files on two different backend. Currently I only have a SSH backend, that stores all my data. I have full(root) access to that machine/backend. On my laptop I have only a few bytes of data, because all is moved/copied to that SSH backend. Now, I want to duplicate the data on the SSH backend to a Google Drive account (or any other). How could I do that (without downloading all data from the SSH backend)??? Encryption is not a must.
+
+I looked into the annex/objects folder on the SSH backend, but there are 3 char length directories compared to what I see on a test Google Drive backend, where only 2 char length directory names are.
+
+Example SSH backend: [git-annex root]/annex/objects/c10/90a/SHA256E-s445227--14c3f85d6dd3464f116f6a5bbd411012781d36794549d136b18d1914c4158820.jpg/SHA256E-s445227--14c3f85d6dd3464f116f6a5bbd411012781d36794549d136b18d1914c4158820.jpg
+
+Example Google Drive: [Google Drive root]/annex/W7/xQ/SHA256E-s913904--29f9800b0dd34d4200c4e9ee152b79c3556a9a473848720be7cf83d20eff65a4.JPG
+
+Is there a way to convert these directory names and do a simpe copy???
+
+Thank you,
+Bence
diff --git a/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__/comment_1_7973928b1aa9e0fcfeb6bf80885441f5._comment b/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__/comment_1_7973928b1aa9e0fcfeb6bf80885441f5._comment
new file mode 100644
index 000000000..3c7d07258
--- /dev/null
+++ b/doc/forum/How_to_copy__47__duplicate_all_data_from_rsync__47__ssh_backend_to_other_backend__63__/comment_1_7973928b1aa9e0fcfeb6bf80885441f5._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.251.174"
+ subject="comment 1"
+ date="2013-09-07T17:11:03Z"
+ content="""
+Just run `git annex copy --all --to remote`
+
+(Needs git-annex 4.20130709 or newer.)
+"""]]
diff --git a/doc/forum/How_to_delete_a_remote__63__/comment_2_33c429ffa7e9e2ed9c5fac760ee8e82c._comment b/doc/forum/How_to_delete_a_remote__63__/comment_2_33c429ffa7e9e2ed9c5fac760ee8e82c._comment
new file mode 100644
index 000000000..2866710c8
--- /dev/null
+++ b/doc/forum/How_to_delete_a_remote__63__/comment_2_33c429ffa7e9e2ed9c5fac760ee8e82c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 2"
+ date="2013-09-04T06:43:26Z"
+ content="""
+Recently git-annex has gotten the ability to do this: `git annex forget --drop-dead`
+
+That prunes all history relating to all dead remotes. You need to be running a git-annex that supports this on all computers you use the repos on, or the pruned history will get merged back in.
+
+I don't recommend doing this just because you want to \"clean history\". Think of it as something you can do at some point in the future if the .git/objects somehow gets too large or too slow. Put off deleting data until tomorrow if you don't absolutely need to do it today.
+"""]]
diff --git a/doc/forum/How_to_delete_a_remote__63__/comment_3_e9c5508092ca2983f458b16bf1e07082._comment b/doc/forum/How_to_delete_a_remote__63__/comment_3_e9c5508092ca2983f458b16bf1e07082._comment
new file mode 100644
index 000000000..337ef2efe
--- /dev/null
+++ b/doc/forum/How_to_delete_a_remote__63__/comment_3_e9c5508092ca2983f458b16bf1e07082._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="konubinix"
+ ip="82.243.233.186"
+ subject="Dropping dead repositories"
+ date="2013-09-04T07:40:22Z"
+ content="""
+Actually, it may be a good idea to remove repositories made for tests purposes.
+
+I now have 2 dead repositories that are USB_test1 and USB_test2 that I created before knowing I could reuse the annex uuid.
+
+They are now there and it is difficult to remove them.
+
+For that special case, the --drop-dead feature is very welcome.
+"""]]
diff --git a/doc/forum/Import_options.txt b/doc/forum/Import_options.txt
new file mode 100644
index 000000000..543d1a4ec
--- /dev/null
+++ b/doc/forum/Import_options.txt
@@ -0,0 +1,14 @@
+Thank you for adding import options to handle duplicates. Very handy when consolidating data from various sources.
+
+Can deletion of the source files be decoupled from annex duplication/deduplication options? For example, I would like to import source files without deleting them and at the same time do not import duplicates.
+
+Better yet, since deletion of source files is potentially dangerous, a delete option could be required for deletion to be performed. Example:
+
+git annex import --deduplicate --delete_all_source_files
+git annex import --deduplicate --delete_source_duplicates
+
+Also, it would be great to have import "status" option which goes over files to be imported and logs their status ( to be imported, duplicate etc. ) without actually performing any changes. It would be great for testing and trial runs.
+
+I hope the above make sense. It would make import feature more flexible.
+
+Cheers,
diff --git a/doc/forum/Import_options/comment_1_118a5f978090a3909299876a01c0adec._comment b/doc/forum/Import_options/comment_1_118a5f978090a3909299876a01c0adec._comment
new file mode 100644
index 000000000..3475a0d73
--- /dev/null
+++ b/doc/forum/Import_options/comment_1_118a5f978090a3909299876a01c0adec._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkeJKC5Sy0stmcTWyePOLEVv0G-x1yaT_w"
+ nickname="Josef"
+ subject="wishlist"
+ date="2013-09-26T11:11:19Z"
+ content="""
+Posted the above yesterday before realizing that it should probably go to wishlist requests. I am sorry about that.
+
+Basically it is a request to extend import options and perhaps make the options easier to use/understand.
+
+Suggested Import Options:
+
+- source directory,
+- destination directory,
+- deduplicate in annex ( yes, no )
+- delete source files ( yes, no )
+- trial run ( screen output only )
+
+Many thanks for a great product!
+
+"""]]
diff --git a/doc/forum/Import_options/comment_2_21da91f08cb6b28ae3e79ade033db516._comment b/doc/forum/Import_options/comment_2_21da91f08cb6b28ae3e79ade033db516._comment
new file mode 100644
index 000000000..a3e259624
--- /dev/null
+++ b/doc/forum/Import_options/comment_2_21da91f08cb6b28ae3e79ade033db516._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkeJKC5Sy0stmcTWyePOLEVv0G-x1yaT_w"
+ nickname="Josef"
+ subject="Additional Comments"
+ date="2013-09-30T21:33:31Z"
+ content="""
+Imported several thousand files to annex and would like to add the following comments:
+
+- it would be great to have an option to exclude hidden dot files from import,
+
+- empty directories should be deleted when files located in the directories are deleted,
+
+- \"git annex add\" seems to process directories and files alphabetically, unfortunately import processes files in a different order, which makes it hard to predict which files are deleted when deduplicating,
+
+Cheers,
+
+"""]]
diff --git a/doc/forum/Is_git-annex_in_a_precarious_state_before_the_initial_commit__63__/comment_4_4bf460c5826c36b205e418c4f3f7d770._comment b/doc/forum/Is_git-annex_in_a_precarious_state_before_the_initial_commit__63__/comment_4_4bf460c5826c36b205e418c4f3f7d770._comment
new file mode 100644
index 000000000..9d5dc042c
--- /dev/null
+++ b/doc/forum/Is_git-annex_in_a_precarious_state_before_the_initial_commit__63__/comment_4_4bf460c5826c36b205e418c4f3f7d770._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="Xyem"
+ ip="87.194.19.134"
+ subject="comment 4"
+ date="2013-10-22T11:28:52Z"
+ content="""
+I've had this a few times (or situations very similar).
+
+ git init
+is now always followed by
+
+ git commit -m \"CREATE GIT REPOSITORY\" --allow-empty
+
+.. which I should really set as an alias :)
+"""]]
diff --git a/doc/forum/Is_it_possible_to_make_git-sync_not_nullify_symlinks__63__/comment_1_d6f2d2cdc5f4ffde9eee9f3a8c215a06._comment b/doc/forum/Is_it_possible_to_make_git-sync_not_nullify_symlinks__63__/comment_1_d6f2d2cdc5f4ffde9eee9f3a8c215a06._comment
new file mode 100644
index 000000000..0c20b9dd6
--- /dev/null
+++ b/doc/forum/Is_it_possible_to_make_git-sync_not_nullify_symlinks__63__/comment_1_d6f2d2cdc5f4ffde9eee9f3a8c215a06._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:18:52Z"
+ content="""
+I'd recommend that you just copy your files to the repository to publish them before running git-annex sync.
+
+Alternatively, unless your web pages are very large, you can just check them into git directly, still use git-annex sync if you want (and still using git-annex for large files), and avoid the complication of being able to have files that are listed in the repository but whose content is not present.
+"""]]
diff --git a/doc/forum/Links_or_actual_files__63___Confused__33__.mdwn b/doc/forum/Links_or_actual_files__63___Confused__33__.mdwn
new file mode 100644
index 000000000..8d7ef2c17
--- /dev/null
+++ b/doc/forum/Links_or_actual_files__63___Confused__33__.mdwn
@@ -0,0 +1,21 @@
+I don't think it's a bug or a todo, just a request for clarification.
+
+So, I installed git-annex first on a Mac, and created the initial repository, and started dropping stuff into it. All fine.
+
+Created a second repository on an external (but never disconnected, also does Time Machine) drive. All fine. Everything's there.
+
+Went across the room to my Linux desktop, installed git-annex, and tried to pair it to my Mac's git-annex repo. Hit <a href="http://git-annex.branchable.com/bugs/bad_comment_in_ssh_public_key_ssh-rsa/#comment-0ee00f307909723fdf8c73695787f067">this bug</a>, installed latest git-annex from tarball and got past that and got the pairing done. Syncing happened, all looked well...
+
+But when I look in the annex dir on that Linux machine, I now just see symlinks to the actual files in the repo's .git/annex stuff. It kinda works, but it's a bit distracting, especially if you open such a file in any desktop app and you can see it's got the target of the link (some sha-value filename.ext) rather than the sensibly-named link. Including files created and coped into that annex on that machine. (In Nautilus they all show with symlink & lock emblems.)
+
+Look again at some documentation, and apparently it's <a href="http://git-annex.branchable.com/how_it_works/">supposed to do this</a>
+
+Which makes me wonder why it *isn't* doing it on the Mac I started the repository on?
+
+Went to another mac (laptop) and installed git-annex, and set up pairing to the first mac - as far as I can tell, doing the exact same procedure as I did under Linux. TBH through the webapp there's not much scope for doing it a different way. Files sync across...
+
+And there they are, the actual files, directly in the annex dir, not symlinks.
+
+(I am by the way confirming this at the commandline, it's not just what Finder/Nautilus may be displaying to me graphically.)
+
+Now, seeing the actual files in the annex directory is what I *prefer*; but I'm a: confused as to why the Macs are doing it that way but Linux isn't, and b: given the "how it works" link, why everything isn't using the links.
diff --git a/doc/forum/Links_or_actual_files__63___Confused__33__/comment_1_779cee2448d7070b1dd636d01296c01e._comment b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_1_779cee2448d7070b1dd636d01296c01e._comment
new file mode 100644
index 000000000..0122cf45b
--- /dev/null
+++ b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_1_779cee2448d7070b1dd636d01296c01e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T17:58:24Z"
+ content="""
+When you create a git-annex repository using the webapp, it uses [[direct_mode]]. That is not the default if you create a repository by hand at the command line, although you can enable it if you prefer it.
+"""]]
diff --git a/doc/forum/Links_or_actual_files__63___Confused__33__/comment_2_bccda88697ab7beec0b9fe9ee0230688._comment b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_2_bccda88697ab7beec0b9fe9ee0230688._comment
new file mode 100644
index 000000000..c6a851eff
--- /dev/null
+++ b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_2_bccda88697ab7beec0b9fe9ee0230688._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEhzszkzOIy8-Rx8b2mcr75QcnIc6O_OA"
+ nickname="Rachel"
+ subject="webapp/direct"
+ date="2013-09-12T18:17:51Z"
+ content="""
+well, i did it using the webapp both times; i've barely scratched at the git-annex commandline so far.
+
+However... I then tried to repeat it on another linux box (running ubuntu saucy and the version of git-annex in that repo) and it worked as expected: Real files in the annex directory, ie: as I understand it, direct mode.
+
+So, went back to the first linux box (running ubuntu raring), and cleared everything off, quit and started again, doing the same thing again, and *it* did the direct mode thing itself this time.
+
+Which I think leaves me with it the way I want it. :-)
+
+My only guess is, maybe it got set up in non-direct mode when I first started using the older git-annex in the raring repos, before failing with the bad comment in ssh public key bug, at which point I switched to the downloaded-today tarball and just tried to resume. Starting from scratch with the newer version worked.
+
+I'm sure more questions to come later; am a Dropbox fugitive by way of ownCloud (won't-fix bug on version upgrades) basically trying to replicate that kind of convenience. But those are for other postings.
+"""]]
diff --git a/doc/forum/Links_or_actual_files__63___Confused__33__/comment_3_c2a9da3f03b55ff294dc0d2010380119._comment b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_3_c2a9da3f03b55ff294dc0d2010380119._comment
new file mode 100644
index 000000000..5df67c605
--- /dev/null
+++ b/doc/forum/Links_or_actual_files__63___Confused__33__/comment_3_c2a9da3f03b55ff294dc0d2010380119._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 3"
+ date="2013-09-12T20:22:44Z"
+ content="""
+Yep, relatively ancient (from last year) versions of the webapp didn't use direct mode by default, and have various bugs as well.
+"""]]
diff --git a/doc/forum/Manual_Setup_of_a_Central_Repo.mdwn b/doc/forum/Manual_Setup_of_a_Central_Repo.mdwn
new file mode 100644
index 000000000..82a1c70ba
--- /dev/null
+++ b/doc/forum/Manual_Setup_of_a_Central_Repo.mdwn
@@ -0,0 +1 @@
+My current setup involves 3 computers, one desktop one laptop and a vps. In my current setup I have created annex repos on the server and cloned from it, both machines sync to the server. All three use non base repos. Now I have another annex folder on the desktop that I would like to sync between the three. Both machines are behind NAT so server can not communicate with the machines. In order to init the repo on the vps, I was thinking of setting up a temporary VPN/port forward between the desktop and the VPS then clone from the desktop finally remove the remote section in .git/config on the server so VPS becomes the master again. First of all is there an easier way to do this? if not is it safe to do this? or is it going to cause problems down the line.
diff --git a/doc/forum/Manual_Setup_of_a_Central_Repo/comment_1_3a163fd5629dc40423f1290a78ae1c07._comment b/doc/forum/Manual_Setup_of_a_Central_Repo/comment_1_3a163fd5629dc40423f1290a78ae1c07._comment
new file mode 100644
index 000000000..7fe30c6dd
--- /dev/null
+++ b/doc/forum/Manual_Setup_of_a_Central_Repo/comment_1_3a163fd5629dc40423f1290a78ae1c07._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-26T18:46:06Z"
+ content="""
+You could certianly do that. I don't think it's the easiest way.
+
+Note that this is essentially a git question. It really has nothing to do with git-annex, unless you want to use the git-annex assistant, which can sync a repository over XMPP without needing a central git repository at all.
+
+If I had this problem with git in general, I would make a new empty repository on the server, and push the local repository I have on the one machine to it. Then on the other machine, I would clone from the server. Problem solved, I think?
+"""]]
diff --git a/doc/forum/Manual_mode_option_in_assistant_auto-syncs.mdwn b/doc/forum/Manual_mode_option_in_assistant_auto-syncs.mdwn
new file mode 100644
index 000000000..49b58e529
--- /dev/null
+++ b/doc/forum/Manual_mode_option_in_assistant_auto-syncs.mdwn
@@ -0,0 +1,11 @@
+Hi,
+
+I've recently set-up a server which uses Southpaw's Tactic DAM system and I've initialised a git-annex directory using the assistant which will manage any files which Tactic puts into the git-annex. I plan to make some remote repositories to Amazon S3, friends and some local machines on my home network. The server is running Ubuntu 64-bit and so I've written an upstart job which runs 'git-annex assistant --autostart' as the user 'git-annex' as this user doesn't log-in and run the xdg autostart .desktop at all.
+
+I saw that you can set the purpose of each repository which it will sync to and noticed 'Manual Mode.' From the description, it seems it will only work if I do explicit git-annex commands to it which would be perfect for me as I'd like to write tools which run git-annex add/get/drop/etc. manually on some remotes like ones to friends as I don't want them to sync to everything or any files that they produce, only files which they request with a special tool that I'll write and have Tactic marshal the file changes/names/etc.
+
+I've set those remotes to manual-mode via the assistant and tried copying a file to the remote's directory, but it auto-synced the file anyway. Maybe I'm getting confused at how manual mode works but I'd like to only explicitly set which files to add to the repo by a command and not just 'any' file which gets placed into that directory. If this is more of a wishlist request I guess just move this post into there and I'll reword it as a wish request.
+
+I don't need to use the assistant if that makes more sense, but I would like to be able to still monitor things as the webapp makes for a great GUI to check for that stuff. I can't wait for the https version of webapp too, I currently run git-annex webapp --listen=<ip>:<port> and then run the link it outputs on my desktop machine to manage it from the server.
+
+Thanks, and this is such a great bit of software, especially as my Internet connection is really bad for 2013 standards, and having the option for friends/remote servers to sync up via an encrypted S3 or box.com account is great!
diff --git a/doc/forum/Manual_mode_option_in_assistant_auto-syncs/comment_1_4a0468b6ca2ffff8ef8f19800597567d._comment b/doc/forum/Manual_mode_option_in_assistant_auto-syncs/comment_1_4a0468b6ca2ffff8ef8f19800597567d._comment
new file mode 100644
index 000000000..56e68f779
--- /dev/null
+++ b/doc/forum/Manual_mode_option_in_assistant_auto-syncs/comment_1_4a0468b6ca2ffff8ef8f19800597567d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T16:20:29Z"
+ content="""
+In the assistant, putting a repository in manual mode prevents the assistant from automatically downloading every file that is added to other clones of the repository. As you've noticed, it does not prevent the assistant from automatically adding new files that are put into the local repository, or from uploading those files to other clients that want them (ie, clients not themselves set to use manual mode).
+
+You can prevent the assistant from noticing when you add new files to a repository by clicking on \"syncing enabled\" in the first repository in the list. (The repository labeled as \"here\".) You can then `git annex add` the files you want to add by hand, and manually `copy annex copy` them to other repositories, and manually `git annex sync`.
+"""]]
diff --git a/doc/forum/Manual_webapp_behaviour_on_ARM.mdwn b/doc/forum/Manual_webapp_behaviour_on_ARM.mdwn
new file mode 100644
index 000000000..8b7b8fe27
--- /dev/null
+++ b/doc/forum/Manual_webapp_behaviour_on_ARM.mdwn
@@ -0,0 +1,15 @@
+Hello,
+
+I have a Samsung ARM Chromebook running Ubuntu with crouton (chroot in chromeos). I want to use git-annex, and add the chromebook as a second "device" to my already set up git-annex repo on my main pc. That repo is one folder set up with the assistant, and it has one encrypted ssh(rsync) remote.
+
+I've read that the webapp is not available on ARM, and I've also found a topic with a simple script to replicate git-annex-assistant steps: http://git-annex.branchable.com/forum/Running_assistant_steps_manually/. So, I've used the `cabal` steps to install git-annex manually, which is working.
+
+I want to use git-annex in a dropbox-like fashion, folder and file sync between these two devices (and maybe later on another encrypted ssh remote). However I'm in need of some guidance regarding the command line usage and such.
+
+My questions are:
+
+- How do I "add" the chromebook repo to the existing git-annex setup?
+- The machines are not on at the same time. One is my main workstation and the chromebook is my "mobile friend". The encrypted ssh remote is on a VPS, that is always on.
+ - How do I configure the syncing between the main machine, the chromebook and the encrypted ssh remote on the vps? If possible, bi-directional.
+
+If it is possible, both explanation and command line examples would help a lot.
diff --git a/doc/forum/Missing_git-annex.linux__47__runshell.mdwn b/doc/forum/Missing_git-annex.linux__47__runshell.mdwn
new file mode 100644
index 000000000..3ad7e85c1
--- /dev/null
+++ b/doc/forum/Missing_git-annex.linux__47__runshell.mdwn
@@ -0,0 +1,44 @@
+Hi,
+
+I've said up two clients to sync locally as well as over ssh-rsync.
+
+However, locally one client is complaining about missing `runshell` at a location where `git annex` is not installed. The log is below. On the assistent overview it just says "unfinished repository". Note that I am able to ssh into the other machine and from the other machine I'm also able to ssh into this machine.
+
+
+I'm using the latest prebuild binary package (git-annex-bin at Archlinux AUR). So my `git annex` setup contains
+
+ $> pacman -Ql git-annex-bin
+ git-annex-bin /usr/
+ git-annex-bin /usr/bin/
+ git-annex-bin /usr/bin/git-annex
+ git-annex-bin /usr/bin/git-annex-shell
+
+ $> pacman -Qi git-annex-bin # with chops
+ Name : git-annex-bin
+ Version : 4.20130909-1
+ Description : Precompiled version of git-annex, webapp and assistant
+ included.
+ Architecture : x86_64
+
+Here is a log of one event where it fails to transfer.
+
+ [2013-09-28 18:06:38 CEST] TransferScanner: queued Upload NoUUID config/emacs.d/ac-l-dict/amsmath-c-a-* Nothing : expensive scan found missing object
+ [2013-09-28 18:06:38 CEST] Transferrer: Transferring: Upload NoUUID config/dotfiles/stardict/dic/stardict-oxford-2.4.2/oxford.ifo Nothing
+ [2013-09-28 18:06:38 CEST] call: git-annex ["transferkeys","--readfd","96","--writefd","94"]
+ [2013-09-28 18:06:38 CEST] read: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex","show-ref","git-annex"]
+ [2013-09-28 18:06:38 CEST] read: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex","show-ref","--hash","refs/heads/git-annex"]
+ [2013-09-28 18:06:38 CEST] read: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex[","log2","0r1e3f-s/0h9e-ad2s8/ g1i8t-annex..90df78a0910a6f2998655e6:06:38 CEST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 Aurora/26.0a2
+ ea47d478ea0589b54","--oneline","-n1"]
+ [2013-09-28 18:06:38 CEST] read: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex","log","refs/heads/git-annex..5f6870ed24e5ded1764765bbfef2b85aff046569","--oneline","-n1"]
+ [2013-09-28 18:06:38 CEST] chat: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex","cat-file","--batch"]
+ [2013-09-28 18:06:38 CEST] read: ssh ["-S","/home/rasmus/annex/.git/annex/ssh/00b8ef4cb08290718ba625d9bd86ca0b","-o","ControlMaster=auto","-o","ControlPersist=yes","-T","rasmus@git-annex-192.168.1.107-rasmus_annex","git-annex-shell 'configlist' '/~/annex/'"]
+ /home/rasmus/.ssh/git-annex-shell: line 4: /opt/git-annex.linux/runshell: No such file or directory
+ [2013-09-28 18:06:38 CEST] call: git ["--git-dir=/home/rasmus/annex/.git","--work-tree=/home/rasmus/annex","fetch","--quiet","192.168.1.107_annex"]
+ [2013-09-28 18:06:38 CEST] 127.0.0.1 GET /transfers/NotificationId%201 Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 Aurora/26.0a2
+ [2013-09-28 18:06:38 CEST] 127.0.0.1 GET /log Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 Aurora/26.0a2
+ /home/rasmus/.ssh/git-annex-shell: line 4: /opt/git-annex.linux/runshell: No such file or directory
+ fatal: Could not read from remote repository.
+
+ Please make sure you have the correct access rights
+ and the repository exists.
+ git-annex: Unknown UUID
diff --git a/doc/forum/Missing_git-annex.linux__47__runshell/comment_1_f29a5105649579ef15e79d983c4e1f8e._comment b/doc/forum/Missing_git-annex.linux__47__runshell/comment_1_f29a5105649579ef15e79d983c4e1f8e._comment
new file mode 100644
index 000000000..a10c4aaf0
--- /dev/null
+++ b/doc/forum/Missing_git-annex.linux__47__runshell/comment_1_f29a5105649579ef15e79d983c4e1f8e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.80"
+ subject="comment 1"
+ date="2013-09-30T16:08:40Z"
+ content="""
+You apparently at one point installed git-annex from the prebuilt tarball, in `/opt/git-annex.linux/`. It set up a ~/.ssh/git-annex-shell that points to this location. If you no longer have it installed that way, you can remove that file.
+"""]]
diff --git a/doc/forum/My_first_impressions_after_some_weeks_with_git-annex_assistant/comment_2_109534a45881ce94a4586c8a83945f9f._comment b/doc/forum/My_first_impressions_after_some_weeks_with_git-annex_assistant/comment_2_109534a45881ce94a4586c8a83945f9f._comment
new file mode 100644
index 000000000..33b2aa393
--- /dev/null
+++ b/doc/forum/My_first_impressions_after_some_weeks_with_git-annex_assistant/comment_2_109534a45881ce94a4586c8a83945f9f._comment
@@ -0,0 +1,85 @@
+[[!comment format=mdwn
+ username="EmanueleAina"
+ ip="93.38.211.231"
+ subject="comment 2"
+ date="2013-09-11T17:55:14Z"
+ content="""
+I seem to hit the same issue (`ResponseTimeout`) on box.com, but I don't have any log file under .git/annex.
+
+The timeout is quite unpredictable, sometimes I'm able to transfer less than 20% of the file while sometimes it fails after reaching 51%. The file is quite big, 6.2G.
+
+Unfortunately, after the first upload fails, `git-annex` seems to think that the file has been uploaded successfully and will refuse to copy it again. Even `whereis` will list the box.com location.
+
+I think there are really two bugs: the one triggering the timeouts, and the fact that `git-annex` thinks that the failing upload succeeded and is unable to recover the interrupted upload.
+
+Here's the log I got on the shell. Let me know how I can provide any additional information needed. Thanks!
+
+ $ git annex copy --verbose --debug home.tar.gz --to box.com
+ [2013-09-11 17:42:52 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"git-annex\"]
+ [2013-09-11 17:42:52 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-11 17:42:52 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1e029f92c5c82b094cbe70b55927996c31579e2e\",\"--oneline\",\"-n1\"]
+ [2013-09-11 17:42:52 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1090c21b121fd8b6e2ab49a772c8eab5235a3930\",\"--oneline\",\"-n1\"]
+ [2013-09-11 17:42:52 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"cat-file\",\"--batch\"]
+ [2013-09-11 17:42:52 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"ls-files\",\"--cached\",\"-z\",\"--\",\"home.tar.gz\"]
+ copy home.tar.gz (gpg) [2013-09-11 17:42:52 CEST] chat: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--decrypt\"]
+ (checking box.com...) (to box.com...)
+ [2013-09-11 17:42:57 CEST] chat: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--batch\",\"--passphrase-fd\",\"11\",\"--symmetric\",\"--force-mdc\",\"--no-textmode\"]
+ 35% 660.8KB/s 1h44mResponseTimeout
+ gpg: [stdout]: write error: Broken pipe
+ gpg: DBG: deflate: iobuf_write failed
+ gpg: build_packet failed: file write error
+ gpg: [stdout]: write error: Broken pipe
+ gpg: iobuf_flush failed on close: file write error
+ gpg: [stdout]: write error: Broken pipe
+ gpg: iobuf_flush failed on close: file write error
+ gpg: symmetric encryption of `[stdin]' failed: file write error
+ git-annex: fd:13: hPutBuf: resource vanished (Broken pipe)
+ failed
+ git-annex: copy: 1 failed
+ $ git annex copy --verbose --debug home.tar.gz --to box.com
+ [2013-09-11 19:38:26 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"git-annex\"]
+ [2013-09-11 19:38:26 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-11 19:38:26 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1e029f92c5c82b094cbe70b55927996c31579e2e\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:38:26 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1090c21b121fd8b6e2ab49a772c8eab5235a3930\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:38:26 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"cat-file\",\"--batch\"]
+ [2013-09-11 19:38:26 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"ls-files\",\"--cached\",\"-z\",\"--\",\"home.tar.gz\"]
+ copy home.tar.gz (gpg) [2013-09-11 19:38:26 CEST] chat: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--decrypt\"]
+ (checking box.com...) ok
+ $ git annex whereis --verbose --debug home.tar.gz
+ [2013-09-11 19:38:57 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"git-annex\"]
+ [2013-09-11 19:38:57 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-11 19:38:57 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1e029f92c5c82b094cbe70b55927996c31579e2e\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:38:57 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1090c21b121fd8b6e2ab49a772c8eab5235a3930\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:38:57 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"cat-file\",\"--batch\"]
+ [2013-09-11 19:38:57 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"ls-files\",\"--cached\",\"-z\",\"--\",\"home.tar.gz\"]
+ whereis home.tar.gz (2 copies)
+ d7db543e-5463-11e2-b7dd-9f423f798cc4 -- here (em@ocracy:/data/backup)
+ e71fa45e-5463-11e2-a14e-93ca09c272da -- box.com
+ ok
+ $ git annex fsck --verbose --debug home.tar.gz
+ [2013-09-11 19:39:05 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"ls-files\",\"--cached\",\"-z\",\"--\",\"home.tar.gz\"]
+ [2013-09-11 19:39:05 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"check-attr\",\"-z\",\"--stdin\",\"annex.backend\",\"annex.numcopies\",\"--\"]
+ fsck home.tar.gz [2013-09-11 19:39:05 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"git-annex\"]
+ [2013-09-11 19:39:05 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-11 19:39:05 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1e029f92c5c82b094cbe70b55927996c31579e2e\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:39:05 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1090c21b121fd8b6e2ab49a772c8eab5235a3930\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:39:05 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"cat-file\",\"--batch\"]
+ (checksum...) [2013-09-11 19:39:05 CEST] read: sha256sum [\"/data/backup/.git/annex/objects/mG/kp/SHA256E-s6640317400--dcf0a535728f3f3f787db6339b740a4a6f6529e5ce1d238f28574499a8172670.tar.gz/SHA256E-s6640317400--dcf0a535728f3f3f787db6339b740a4a6f6529e5ce1d238f28574499a8172670.tar.gz\"]
+ ok
+ $ git annex fsck --verbose --debug home.tar.gz --from box.com
+ [2013-09-11 19:42:15 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"git-annex\"]
+ [2013-09-11 19:42:15 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-11 19:42:15 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1e029f92c5c82b094cbe70b55927996c31579e2e\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:42:15 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"log\",\"refs/heads/git-annex..1090c21b121fd8b6e2ab49a772c8eab5235a3930\",\"--oneline\",\"-n1\"]
+ [2013-09-11 19:42:15 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"cat-file\",\"--batch\"]
+ [2013-09-11 19:42:15 CEST] read: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"ls-files\",\"--cached\",\"-z\",\"--\",\"home.tar.gz\"]
+ [2013-09-11 19:42:15 CEST] chat: git [\"--git-dir=/data/backup/.git\",\"--work-tree=/data/backup\",\"check-attr\",\"-z\",\"--stdin\",\"annex.backend\",\"annex.numcopies\",\"--\"]
+ fsck home.tar.gz (gpg) [2013-09-11 19:42:15 CEST] chat: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--decrypt\"]
+ (checking box.com...)
+ [2013-09-11 19:42:28 CEST] chat: gpg [\"--quiet\",\"--trust-model\",\"always\",\"--batch\",\"--passphrase-fd\",\"10\",\"--decrypt\"]
+ gpg: decrypt_message failed: eof
+ ok
+
+
+
+"""]]
diff --git a/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_3_92a52b523ed4c68b70ddcabc2a050b76._comment b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_3_92a52b523ed4c68b70ddcabc2a050b76._comment
new file mode 100644
index 000000000..9b1d95e78
--- /dev/null
+++ b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_3_92a52b523ed4c68b70ddcabc2a050b76._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmKKg3Vmzk7KwRGRKjHVdtyoj1JfxLX6NM"
+ nickname="Tom"
+ subject="comment 3"
+ date="2013-10-01T18:33:05Z"
+ content="""
+I've got the same issue on Xubuntu 13.04. I installed using this script: https://github.com/zerodogg/scriptbucket/blob/master/gitannex-install
+
+`git-annex version` makes no mention of DNS or ADNS
+
+`host` command is installed on my machine. any suggestions on how best to fix for this setup?
+"""]]
diff --git a/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_4_c52a75761ea107f6d69c09bac64f0f0a._comment b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_4_c52a75761ea107f6d69c09bac64f0f0a._comment
new file mode 100644
index 000000000..b15edfa5a
--- /dev/null
+++ b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_4_c52a75761ea107f6d69c09bac64f0f0a._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmKKg3Vmzk7KwRGRKjHVdtyoj1JfxLX6NM"
+ nickname="Tom"
+ subject="comment 4"
+ date="2013-10-02T21:27:36Z"
+ content="""
+Update to my comment above - it seems my problem is related to ejabberd as discussed here: <http://git-annex.branchable.com/forum/XMPP_authentication_failure/>
+
+Think I might change my server to [Prosody](https://prosody.im/) and see what happens then.
+
+
+"""]]
diff --git a/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_5_2685e3a87464ccd37d593516d94ba5cf._comment b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_5_2685e3a87464ccd37d593516d94ba5cf._comment
new file mode 100644
index 000000000..84d6832ff
--- /dev/null
+++ b/doc/forum/Newbie_stuck_at___34__Unable_to_connect_to_the_Jabber_server__34__/comment_5_2685e3a87464ccd37d593516d94ba5cf._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkr_EUIHZ8CTtOGm-j-guMBzaYuOzrXJwg"
+ nickname="Christoph"
+ subject="be aware of the 2-step verification"
+ date="2013-10-15T20:03:12Z"
+ content="""
+if you enabled the \"2-step verification\" in our google account (Account -> Security -> 2-step verification: Status: ON) you have to make a \"Application-specific passwords\" for your Jabber login.
+
+NoXorius
+"""]]
diff --git a/doc/forum/OSX_Mavericks_anyone__63__.mdwn b/doc/forum/OSX_Mavericks_anyone__63__.mdwn
new file mode 100644
index 000000000..b19133680
--- /dev/null
+++ b/doc/forum/OSX_Mavericks_anyone__63__.mdwn
@@ -0,0 +1,3 @@
+Was anyone able to run git annex on Mavericks?
+
+Didn't have time for qualified troubleshooting, sorry
diff --git a/doc/forum/OSX_Mavericks_anyone__63__/comment_1_3075b02aeb57adcbf4addf9fb4c123ba._comment b/doc/forum/OSX_Mavericks_anyone__63__/comment_1_3075b02aeb57adcbf4addf9fb4c123ba._comment
new file mode 100644
index 000000000..1657d676d
--- /dev/null
+++ b/doc/forum/OSX_Mavericks_anyone__63__/comment_1_3075b02aeb57adcbf4addf9fb4c123ba._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://mike.magin.org/"
+ nickname="mmagin"
+ subject="a little"
+ date="2013-10-24T17:02:18Z"
+ content="""
+Some syncing and copying, nothing other than normal remotes and one S3 remote.
+Haven't even done an \"add\" yet.
+
+Not an assistant user. Still running 4.20130422-gb9341fd on this computer.
+"""]]
diff --git a/doc/forum/OSX_Mavericks_anyone__63__/comment_2_c2b6110fc4a3d3481ed8a4b48efb9635._comment b/doc/forum/OSX_Mavericks_anyone__63__/comment_2_c2b6110fc4a3d3481ed8a4b48efb9635._comment
new file mode 100644
index 000000000..bfc43d682
--- /dev/null
+++ b/doc/forum/OSX_Mavericks_anyone__63__/comment_2_c2b6110fc4a3d3481ed8a4b48efb9635._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="Alex"
+ ip="217.8.62.35"
+ subject="not at all"
+ date="2013-10-24T19:50:11Z"
+ content="""
+I'd love to see an updated OS X build for Mavericks.
+
+Currently I'm getting this error:
+
+ dyld: Symbol not found: _objc_debug_taggedpointer_mask
+ Referenced from: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+ Expected in: /Applications/git-annex.app/Contents/MacOS/bundle/I
+ in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+ Trace/BPT trap: 5
+
+"""]]
diff --git a/doc/forum/OSX_Mavericks_anyone__63__/comment_3_7df9ba63cb1f385681242b4b58d6a87c._comment b/doc/forum/OSX_Mavericks_anyone__63__/comment_3_7df9ba63cb1f385681242b4b58d6a87c._comment
new file mode 100644
index 000000000..691fd9064
--- /dev/null
+++ b/doc/forum/OSX_Mavericks_anyone__63__/comment_3_7df9ba63cb1f385681242b4b58d6a87c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="67.223.19.96"
+ subject="comment 3"
+ date="2013-10-24T19:53:08Z"
+ content="""
+Mavericks is being discussed [[here|bugs/git annex doesn't work in Max OS X 10.9]]
+"""]]
diff --git a/doc/forum/OSX_Mavericks_anyone__63__/comment_4_740fee31c4ca9d84428f97f63ffc075a._comment b/doc/forum/OSX_Mavericks_anyone__63__/comment_4_740fee31c4ca9d84428f97f63ffc075a._comment
new file mode 100644
index 000000000..3ad5c2344
--- /dev/null
+++ b/doc/forum/OSX_Mavericks_anyone__63__/comment_4_740fee31c4ca9d84428f97f63ffc075a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Alex"
+ ip="217.8.62.35"
+ subject="comment 4"
+ date="2013-10-24T19:55:56Z"
+ content="""
+Thanks, Joey!
+"""]]
diff --git a/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__.mdwn b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__.mdwn
new file mode 100644
index 000000000..caa9fc85a
--- /dev/null
+++ b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__.mdwn
@@ -0,0 +1,36 @@
+Hello,
+
+I've a strange (for me ;-)) problem.
+<br>I'm trying to use git-annex with 2 debian wheezy (packages from backports)
+<br>I've put my ssh pub key on the server in the autorized_keys for my username account (and for the root account to be sure)
+my username account is member of the sudo group (not sure it's required)
+
+I can create an ssh session directly to the server with :
+
+ ssh username@remoteserver.lan -p 62322
+
+and work inside this session.
+
+ Sep 14 03:42:35 file sshd[8849]: Accepted publickey for username from 80.201.25.4 port 32969 ssh2
+ Sep 14 03:42:35 file sshd[8849]: pam_unix(sshd:session): session opened for user username by (uid=0)
+ ...
+ Sep 14 05:13:14 file sshd[8851]: Received disconnect from 80.201.25.4: 11: disconnected by user
+ Sep 14 05:13:14 file sshd[8849]: pam_unix(sshd:session): session closed for user username
+
+But when I use the git-annex assistant on the same workstation with the same remote server and port,
+<br>the 1st step is OK,
+<br>but when I've to choose between git or rsync encrypted, I'm choosing git and receive :
+
+ "Permission denied (publickey)."
+
+On the server I can only see that the ssh session is immediately closed after opened and before the choice git or rsync is made.
+
+ Sep 14 05:13:42 file sshd[8882]: Accepted publickey for username from 80.201.25.4 port 32984 ssh2
+ Sep 14 05:13:42 file sshd[8882]: pam_unix(sshd:session): session opened for user username by (uid=0)
+ Sep 14 05:13:42 file sshd[8886]: Received disconnect from 80.201.25.4: 11: disconnected by user
+ Sep 14 05:13:42 file sshd[8882]: pam_unix(sshd:session): session closed for user username
+
+Do you think it's the problem ? or whatelse ...
+<br>and could you guide me to a possible solution ?
+
+Best regards
diff --git a/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_1_6c74f0b43c457fe97b2d8630ca4fde29._comment b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_1_6c74f0b43c457fe97b2d8630ca4fde29._comment
new file mode 100644
index 000000000..8d2215772
--- /dev/null
+++ b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_1_6c74f0b43c457fe97b2d8630ca4fde29._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 1"
+ date="2013-11-08T18:24:27Z"
+ content="""
+The webapp sets up a dedicated ssh public key when you add a ssh repository in there.
+
+You might see some useful debugging info your your problem in ~/annex/.git/annex/daemon.log
+"""]]
diff --git a/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_2_b7a384e853e1756a684774348fad29e6._comment b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_2_b7a384e853e1756a684774348fad29e6._comment
new file mode 100644
index 000000000..ecf26daa1
--- /dev/null
+++ b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_2_b7a384e853e1756a684774348fad29e6._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="Auroch"
+ ip="87.65.174.80"
+ subject="OK,thanx for this"
+ date="2013-11-09T09:10:42Z"
+ content="""
+The problem is not solve, but with your informations, I think i've found somehting.
+
+Is it possible that the problem is linked to my situation of port-forwarding ?
+The remoteserver is a host (proxmox) with iptable port forwarding 62322 to the real port 22 of the VM hosting the git where I try to connect.
+
+So could the problem seems to be that some actions are taken on the host and not the VM ... correct ?
+
+ [2013-11-09 09:51:33 CET] read: ssh-keygen [\"-F\",\"bla.remote.tld\"]
+ [2013-11-09 09:51:33 CET] read: ssh [\"-oNumberOfPasswordPrompts=0\",\"-n\",\"-p\",\"62322\",\"user@bla.remote.tld\",\"sh -c 'echo git-annex-probe loggedin;if which git-annex-shell; then echo git-annex-probe git-annex-shell; fi;if which rsync; then echo git-annex-probe rsync; fi;if which ~/.ssh/git-annex-shell; then echo git-annex-probe ~/.ssh/git-annex-shell; fi'\"]
+ [2013-11-09 09:51:35 CET] chat: ssh [\"user@bla.remote.tld\",\"sh -c 'mkdir -p '\\"'\\"'annex'\\"'\\"'&&cd '\\"'\\"'annex'\\"'\\"'&&if [ ! -d .git ]; then git init --bare --shared; fi&&git annex init'\"]
+
+If it's correct, have you an idea for solving this ?
+
+best regards
+
+"""]]
diff --git a/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_3_3a8a7f51cb04a92c576549d379b57248._comment b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_3_3a8a7f51cb04a92c576549d379b57248._comment
new file mode 100644
index 000000000..546f647ed
--- /dev/null
+++ b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_3_3a8a7f51cb04a92c576549d379b57248._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 3"
+ date="2013-11-09T18:07:56Z"
+ content="""
+Well, it does look like your git-annex did not pass the port to the second command.
+
+What version are you using? I've just tested with a ssh server only listening on 2222 and it used the port throughout.
+
+You might try upgrading to a recent version. I know that version 4.20130627, at least, had a bug with the ssh port.
+"""]]
diff --git a/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_4_582ad3ba0c62a77b08a10b37a780c670._comment b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_4_582ad3ba0c62a77b08a10b37a780c670._comment
new file mode 100644
index 000000000..c8d8c8b52
--- /dev/null
+++ b/doc/forum/Permission_denied___40__publickey__41___On_second_Step_...___63__/comment_4_582ad3ba0c62a77b08a10b37a780c670._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="Auroch"
+ ip="87.65.174.80"
+ subject="comment 4"
+ date="2013-11-09T19:24:54Z"
+ content="""
+I've the wheezy-backports version
+
+ i 4.20131002~bpo70+1 wheezy-backports 100
+
+I'll have to wait an update and I'll come back to you.
+
+Thanx this amazing work !
+
+"""]]
diff --git a/doc/forum/Please_publish_new_releases_not_shorter_than_11_days.mdwn b/doc/forum/Please_publish_new_releases_not_shorter_than_11_days.mdwn
new file mode 100644
index 000000000..f67d2d797
--- /dev/null
+++ b/doc/forum/Please_publish_new_releases_not_shorter_than_11_days.mdwn
@@ -0,0 +1,6 @@
+Hi,
+i am following debian testing. The latest git-annex publication has manged to replace the former version on the last possible moment. Now another 10 days waiting.
+Would be nice if you can coordinate with testing.
+
+Thank you for git-annex.
+Jürgen
diff --git a/doc/forum/Please_publish_new_releases_not_shorter_than_11_days/comment_1_da3d39de5be47ebe8b25a42ed1f36510._comment b/doc/forum/Please_publish_new_releases_not_shorter_than_11_days/comment_1_da3d39de5be47ebe8b25a42ed1f36510._comment
new file mode 100644
index 000000000..1fb259c98
--- /dev/null
+++ b/doc/forum/Please_publish_new_releases_not_shorter_than_11_days/comment_1_da3d39de5be47ebe8b25a42ed1f36510._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-03T19:57:24Z"
+ content="""
+I do coordinate with testing. That version had no possibility of ever reaching testing, since it failed to build on several architectures.
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP.mdwn b/doc/forum/Poor_man__39__s_IMAP.mdwn
new file mode 100644
index 000000000..af53ddc19
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP.mdwn
@@ -0,0 +1,6 @@
+I have an e-mail server configured to save my mail in ~/Maildir on an account that is available over ssh. I'd like to keep emailserver:~/Maildir in a two-way sync with laptop:~/Mail/private essentially creating a poor man's IMAP — without setting up and maintaining an actual IMAP server. **Is it an appropriate use of git-annex or would another tool be more fitting? And how do I go about doing it?** I'd like to sync the files, the content, not just information about the files or other meta-data.
+
+I tried setting it up with the webUI to the assistant but it only offers encrypted storage[1] on the remote server. I looked into setting it up manually but "git-annex does not notice when files are added to remote rsync repositories."[2]
+
+[1] http://git-annex.branchable.com/bugs/Remote_repositories_have_to_be_setup_encrypted/
+[2] from comments on http://git-annex.branchable.com/special_remotes/rsync/
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_1_258ff23c462dc88b88ced405c4f5040f._comment b/doc/forum/Poor_man__39__s_IMAP/comment_1_258ff23c462dc88b88ced405c4f5040f._comment
new file mode 100644
index 000000000..8965f18be
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_1_258ff23c462dc88b88ced405c4f5040f._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="220.244.41.108"
+ subject="comment 1"
+ date="2013-08-14T06:45:56Z"
+ content="""
+I'd say that git-annex is the wrong tool.
+
+OfflineIMAP ([[http://offlineimap.org]]) is simple to set up, is easy to secure over ssh and does exactly what you want.
+
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_2_c88d1abdda4cb526a6ee45a710c75bc4._comment b/doc/forum/Poor_man__39__s_IMAP/comment_2_c88d1abdda4cb526a6ee45a710c75bc4._comment
new file mode 100644
index 000000000..4ab7af46b
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_2_c88d1abdda4cb526a6ee45a710c75bc4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="220.244.41.108"
+ subject="comment 2"
+ date="2013-08-14T06:53:04Z"
+ content="""
+From my massive amount of googling, i.e. 2min, apparently mbsync ([[http://isync.sourceforge.net/mbsync.html]]) is good too.
+
+I've never used it, so YMMV.
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_3_3847e371db1c2788c075e7dca1fbd33e._comment b/doc/forum/Poor_man__39__s_IMAP/comment_3_3847e371db1c2788c075e7dca1fbd33e._comment
new file mode 100644
index 000000000..a8ed31475
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_3_3847e371db1c2788c075e7dca1fbd33e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://spindritf.myopenid.com/"
+ nickname="spindritf"
+ subject="comment 3"
+ date="2013-08-14T07:30:30Z"
+ content="""
+Offlineimap connects to an IMAP server and I was hoping to avoid running one. Thanks though.
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_4_cf6cc21f2cf2aa5c949844e24a7b4075._comment b/doc/forum/Poor_man__39__s_IMAP/comment_4_cf6cc21f2cf2aa5c949844e24a7b4075._comment
new file mode 100644
index 000000000..bcb698216
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_4_cf6cc21f2cf2aa5c949844e24a7b4075._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 4"
+ date="2013-08-14T11:11:59Z"
+ content="""
+IMHO It is not the wrong tool for the job, after all the whole point of assistant is to sync folder across machines. I have a similar setup. I have two folders on two machines plus an encrypted repo on an ssh server. On both folders (local/server) i keep webapp running they sync using the encrypted repo/xmpp. The only downside to this approach is that VPS has two copies of every file one in the folder on in the encrypted git repo.
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_5_d861fa69475ce526841b3195be8ee356._comment b/doc/forum/Poor_man__39__s_IMAP/comment_5_d861fa69475ce526841b3195be8ee356._comment
new file mode 100644
index 000000000..d5621bb4a
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_5_d861fa69475ce526841b3195be8ee356._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://spindritf.myopenid.com/"
+ nickname="spindritf"
+ subject="comment 5"
+ date="2013-08-14T18:08:22Z"
+ content="""
+> IMHO It is not the wrong tool for the job, after all the whole point of assistant is to sync folder across machines.
+
+That's what I thought. OK, so how do I do it? Should I set up this rsync special remote and run sync every once in a while. When starting the e-mail client for example?
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_6_1e81bd4bb62652bc674cdcd7ed57ac5c._comment b/doc/forum/Poor_man__39__s_IMAP/comment_6_1e81bd4bb62652bc674cdcd7ed57ac5c._comment
new file mode 100644
index 000000000..7e0720456
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_6_1e81bd4bb62652bc674cdcd7ed57ac5c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 6"
+ date="2013-08-16T09:14:52Z"
+ content="""
+You can either keep running 2 webapps paired using xmpp running all the time that gives you push like notifications or if you are ok with syncing every once in a while you can have a check mail script that adds files on the server commits them then calls git annex sync locally,
+
+ ssh $1 \"cd /path/to/annex/;git add .;git commit 'Update'\";git annex sync
+
+should do the trick. The latter method you just need to annex repos no encrypted third repo. Just init your git annex repo on the server and clone on the laptop thats it.
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_7_b3929281dff6078d77f1b9ae42e25bb6._comment b/doc/forum/Poor_man__39__s_IMAP/comment_7_b3929281dff6078d77f1b9ae42e25bb6._comment
new file mode 100644
index 000000000..aba4cd0de
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_7_b3929281dff6078d77f1b9ae42e25bb6._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 7"
+ date="2013-08-23T18:30:04Z"
+ content="""
+I don't feel that git-annex is the best thing to use for this. Maildir has some specific semantics for the filenames used in it that let imap clients resolve inconsistencies, such as a message that was read on machine A, and deleted on machine B. git-annex is unlikely to work as well.
+
+However, I have to say that the very beginning of this thread has a wrong statement in it.
+
+> I tried setting it up with the webUI to the assistant but it only offers encrypted storage[1] on the remote server.
+
+If you install git and git-annex on your remote server, the git-annex assistant will detect this, and offer the choice between a regular git repository, and encrypted storage. If you don't have them installed, it tells you you don't, offers to let you retry once you do install them, and offers encrypted storage as the only option that works given what's installed on the server.
+
+(Also, the bug you linked to in [1] has nothing at all to do with what you were talking about.)
+"""]]
diff --git a/doc/forum/Poor_man__39__s_IMAP/comment_8_69506e8c519196f44b9ed15b32f00106._comment b/doc/forum/Poor_man__39__s_IMAP/comment_8_69506e8c519196f44b9ed15b32f00106._comment
new file mode 100644
index 000000000..18b99a880
--- /dev/null
+++ b/doc/forum/Poor_man__39__s_IMAP/comment_8_69506e8c519196f44b9ed15b32f00106._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="konubinix"
+ ip="82.243.233.186"
+ subject="And with a lots of mails?"
+ date="2013-08-27T06:44:56Z"
+ content="""
+Hi,
+
+I have a question quite similar, but for a different purpose. I use OfflineImap for imap synchronisation, but in my current situation, I travel a lot between two places: one connected to the Internet and the other not connected.
+
+When I am connected to the Internet, I may synchronize mails, then I rsync my ~/Mail directory to a usb key so that I have access to them in the place without connection. The mails filenames may be changed as Joeyh mentioned while I read or delete them. I rsync them back to the usb key before going back to the place with Internet connection, where the OfflineImap synchronization may occur.
+
+This solution, with rsynced key, works well. But I would love a history of what was done with file names and may be able to retrieve an old mail.
+
+I figured out that that the git annex was a really good solution for that.
+
+The main drawback from my point of view is that I have around 100 000 mails (some would say that's \"[Not much mail](http://notmuchmail.org/)\"), and I am afraid that git will be quite slow with that amount of files.
+
+Did anyone experience an annexed repository with so many items it in?
+
+Best
+"""]]
diff --git a/doc/forum/Problem_with_bup:_cannot_lock_refs.mdwn b/doc/forum/Problem_with_bup:_cannot_lock_refs.mdwn
deleted file mode 100644
index 897d3b409..000000000
--- a/doc/forum/Problem_with_bup:_cannot_lock_refs.mdwn
+++ /dev/null
@@ -1,5 +0,0 @@
-Hi!
-
-> Hi.. Please file bug reports in [[bugs]], not in the forum.
-> Moved this post to [[bugs/Problem_with_bup:_cannot_lock_refs]]
---[[Joey]]
diff --git a/doc/forum/Pruning_out_unwanted_Git_objects.mdwn b/doc/forum/Pruning_out_unwanted_Git_objects.mdwn
new file mode 100644
index 000000000..36397b267
--- /dev/null
+++ b/doc/forum/Pruning_out_unwanted_Git_objects.mdwn
@@ -0,0 +1,3 @@
+I have a backups repository with a few files in it, that at one point had some huge filesets erroneously added to it. As a result, even though there are only 23,334 annexed files, the number of non-dangling Git objects in the repository comes to 593,584.
+
+Normally I would use `git filter-branch` to clear out the deadwood in situations like this, since it is a completely private repository. What I'm wondering is, is any such thing possible with git-annex, or is the best option just to start over, copy all the files into the new repository, and then `git-add` them all?
diff --git a/doc/forum/Pruning_out_unwanted_Git_objects/comment_1_0cf7a12bfa2957260f4b2f79b0cadf2f._comment b/doc/forum/Pruning_out_unwanted_Git_objects/comment_1_0cf7a12bfa2957260f4b2f79b0cadf2f._comment
new file mode 100644
index 000000000..fbf538afa
--- /dev/null
+++ b/doc/forum/Pruning_out_unwanted_Git_objects/comment_1_0cf7a12bfa2957260f4b2f79b0cadf2f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 1"
+ date="2013-08-29T07:23:13Z"
+ content="""
+Maybe one way to solve this that would be general is to have some kind of `prune-history` command, which keeps only the HEAD and drops everything else. Because there are some repositories that I want to manage with `git-annex` for many reasons, but I don't care about keep history around at all.
+"""]]
diff --git a/doc/forum/Pruning_out_unwanted_Git_objects/comment_2_7472943c02cfe2808b0d566e06caa1a5._comment b/doc/forum/Pruning_out_unwanted_Git_objects/comment_2_7472943c02cfe2808b0d566e06caa1a5._comment
new file mode 100644
index 000000000..0c2646351
--- /dev/null
+++ b/doc/forum/Pruning_out_unwanted_Git_objects/comment_2_7472943c02cfe2808b0d566e06caa1a5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 2"
+ date="2013-08-30T06:18:42Z"
+ content="""
+This was answered quite thoroughly in:http://git-annex.branchable.com/forum/safely_dropping_git-annex_history/
+"""]]
diff --git a/doc/forum/Pruning_out_unwanted_Git_objects/comment_3_6a1e7a83d94394454fc085f6d2728cd7._comment b/doc/forum/Pruning_out_unwanted_Git_objects/comment_3_6a1e7a83d94394454fc085f6d2728cd7._comment
new file mode 100644
index 000000000..90951961f
--- /dev/null
+++ b/doc/forum/Pruning_out_unwanted_Git_objects/comment_3_6a1e7a83d94394454fc085f6d2728cd7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 3"
+ date="2013-09-04T06:36:15Z"
+ content="""
+`git annex forget` automates this now. Needs a version of git-annex supporting it installed on *all* the computers you use the repo on.
+"""]]
diff --git a/doc/forum/Purge_a_remote.txt b/doc/forum/Purge_a_remote.txt
new file mode 100644
index 000000000..f1b04ead2
--- /dev/null
+++ b/doc/forum/Purge_a_remote.txt
@@ -0,0 +1,2 @@
+How could I delete and purge a remote? I want to remove all traces of it
+but I can't find out how to achieve this.
diff --git a/doc/forum/Purge_a_remote/comment_1_78b3b77f457c65d31fd8a5abf714905d._comment b/doc/forum/Purge_a_remote/comment_1_78b3b77f457c65d31fd8a5abf714905d._comment
new file mode 100644
index 000000000..a7eff3a99
--- /dev/null
+++ b/doc/forum/Purge_a_remote/comment_1_78b3b77f457c65d31fd8a5abf714905d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-05T16:17:22Z"
+ content="""
+In the git-annex webapp, each repository has a settings menu with \"delete repository\".
+"""]]
diff --git a/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment b/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment
new file mode 100644
index 000000000..ddcab44dd
--- /dev/null
+++ b/doc/forum/Purge_a_remote/comment_2_dc65719157dee63b3979563ed57ee0ce._comment
@@ -0,0 +1,10 @@
+[[!comment format=txt
+ username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
+ nickname="dxtrish"
+ subject="comment 2"
+ date="2013-11-05T17:46:02Z"
+ content="""
+When I use that Delete button it seems to still have records of it
+because when I delete the repo on the other end and create a new bare
+one it complains about some UUID mismatch.
+"""]]
diff --git a/doc/forum/Purge_a_remote/comment_3_63e0280273b816fa4b837724e102f813._comment b/doc/forum/Purge_a_remote/comment_3_63e0280273b816fa4b837724e102f813._comment
new file mode 100644
index 000000000..621bda508
--- /dev/null
+++ b/doc/forum/Purge_a_remote/comment_3_63e0280273b816fa4b837724e102f813._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-05T18:03:26Z"
+ content="""
+Hmm well, it's true that deleting a repository does not clean out any git remotes that other repositories might have configured using it, and the uuid of the old remote is cached in there. This is only a problem if you put back another repository in the same location as the old one. `git remote remove` should clean that up for you.
+"""]]
diff --git a/doc/forum/Purge_a_remote/comment_4_7fad1c4798ca03a4095ac3241c279f6d._comment b/doc/forum/Purge_a_remote/comment_4_7fad1c4798ca03a4095ac3241c279f6d._comment
new file mode 100644
index 000000000..afb4dc92e
--- /dev/null
+++ b/doc/forum/Purge_a_remote/comment_4_7fad1c4798ca03a4095ac3241c279f6d._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkzwmw_zyMpZC9_J7ey--woeYPoZkAOgGw"
+ nickname="dxtrish"
+ subject="comment 4"
+ date="2013-11-06T14:24:21Z"
+ content="""
+That is exactly what I have wanted to do a couple of times now and 'git remote remove' does not seem to remove it all either.
+When I try to create a new repository in the same place it still complains about that darn UUID :)
+
+What is working is to manually add the new UUID to .git/config
+"""]]
diff --git a/doc/forum/Relocating_annex_directory.mdwn b/doc/forum/Relocating_annex_directory.mdwn
new file mode 100644
index 000000000..f2e271333
--- /dev/null
+++ b/doc/forum/Relocating_annex_directory.mdwn
@@ -0,0 +1 @@
+I have around 70 GBs of data spread around 4 repositories on a Linux (Ubuntu) box. My problem is I need to reformat the drive they are on. I would like to move them to an external usb drive temporarily during reinstall then move them back to their original location. When I started with annex I did try to mv annexFolder/ toNewLoc/ which failed leaving behind a corrupt repo. What is a safe way to move an annex folder? My primary connection is a 3G modem so I am trying to avoid re downloading everything. Another thing I am trying to avoid is cloning the repos to the external drive, reinstall, clone it back to the internal drive and mark original and external repos as dead, but AFAIK those dead repos will show up in the output of whereis, so everytime I reformat I gonna have two extra dead repos.
diff --git a/doc/forum/Relocating_annex_directory/comment_1_13ff5438baa1db110beb6aab3a783def._comment b/doc/forum/Relocating_annex_directory/comment_1_13ff5438baa1db110beb6aab3a783def._comment
new file mode 100644
index 000000000..5136941c5
--- /dev/null
+++ b/doc/forum/Relocating_annex_directory/comment_1_13ff5438baa1db110beb6aab3a783def._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmBUR4O9mofxVbpb8JV9mEbVfIYv670uJo"
+ nickname="Justin"
+ subject="comment 1"
+ date="2013-08-16T03:42:00Z"
+ content="""
+moving the annex should work fine, provided:
+
+* You are moving it to a proper unix filesystem - NOT fat32
+* The assistant is shutdown. If it is running, bad things will happen.
+"""]]
diff --git a/doc/forum/Relocating_annex_directory/comment_2_6d88ff03fcf00ae872442e8a86c968ed._comment b/doc/forum/Relocating_annex_directory/comment_2_6d88ff03fcf00ae872442e8a86c968ed._comment
new file mode 100644
index 000000000..e7b361675
--- /dev/null
+++ b/doc/forum/Relocating_annex_directory/comment_2_6d88ff03fcf00ae872442e8a86c968ed._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-24T18:56:11Z"
+ content="""
+`git annex whereis` does not show dead repositories.
+
+Anyway Justin is of course right: Provided the assistant is not running in a repository, the repository is just a collection of files in a directory, and can be moved around, tarred up, untarred, etc just like any other repository. If the assistant is running it may become unhappy if its repository vanishes out from underneath it.
+"""]]
diff --git a/doc/forum/Retrieve_previous_version_in_direct_mode.mdwn b/doc/forum/Retrieve_previous_version_in_direct_mode.mdwn
new file mode 100644
index 000000000..c74b55b36
--- /dev/null
+++ b/doc/forum/Retrieve_previous_version_in_direct_mode.mdwn
@@ -0,0 +1,5 @@
+I use the assistant with a local directory in direct mode. I have read in different places that direct mode does not ensure that past versions of files are preserved.
+
+What precisely happens to past versions? Under which conditions are past versions kept?
+
+How would I go about retrieving the past version of a file in direct mode?
diff --git a/doc/forum/Retrieve_previous_version_in_direct_mode/comment_1_ca3a999ed64c42b8df810115de205d2f._comment b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_1_ca3a999ed64c42b8df810115de205d2f._comment
new file mode 100644
index 000000000..dce26832b
--- /dev/null
+++ b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_1_ca3a999ed64c42b8df810115de205d2f._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-21T22:16:16Z"
+ content="""
+If you change a direct mode file and that file has not yet been transferred to some other repository, you've changed the only copy of the file, and so you cannot get back the old version.
+
+Other than that, git-annex always preserves old versions of direct mode files, the same as it preserves old versions of indirect mode files.
+
+To get back an old version of a file, use `git annex indirect` to get out of direct mode, use regular git commands to check out the version of the repository that has the file you need, and use `git annex get` to retrieve the file if it's not available in the local repository.
+"""]]
diff --git a/doc/forum/Retrieve_previous_version_in_direct_mode/comment_2_1292b34ff6d9976b2bd08748e1ba4e7a._comment b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_2_1292b34ff6d9976b2bd08748e1ba4e7a._comment
new file mode 100644
index 000000000..47ab2b742
--- /dev/null
+++ b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_2_1292b34ff6d9976b2bd08748e1ba4e7a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Disk space?"
+ date="2013-11-02T01:33:10Z"
+ content="""
+Sorry, I'm confused: does using regular client repositories in direct mode still store old versions of files? If so, for how long? I don't have unlimited disk space, and if it stored in git every copy of every file forever, especially large ones, I'd run out of space...and then what?
+"""]]
diff --git a/doc/forum/Retrieve_previous_version_in_direct_mode/comment_3_699e816c0397f6db924feeab906f1151._comment b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_3_699e816c0397f6db924feeab906f1151._comment
new file mode 100644
index 000000000..77fa9b0e7
--- /dev/null
+++ b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_3_699e816c0397f6db924feeab906f1151._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T17:36:23Z"
+ content="""
+You can use `git annex unused` and `git annex dropunused` to remove old versions of files.
+"""]]
diff --git a/doc/forum/Retrieve_previous_version_in_direct_mode/comment_4_d900388753de5870b7b9c0e8b8c06ed7._comment b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_4_d900388753de5870b7b9c0e8b8c06ed7._comment
new file mode 100644
index 000000000..deb26163e
--- /dev/null
+++ b/doc/forum/Retrieve_previous_version_in_direct_mode/comment_4_d900388753de5870b7b9c0e8b8c06ed7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 4"
+ date="2013-11-02T22:30:07Z"
+ content="""
+Thank you. Just curious, are there plans to put that in the webapp?
+"""]]
diff --git a/doc/forum/Revert_file_linkage_to_original_files.mdwn b/doc/forum/Revert_file_linkage_to_original_files.mdwn
new file mode 100644
index 000000000..ba83cfd15
--- /dev/null
+++ b/doc/forum/Revert_file_linkage_to_original_files.mdwn
@@ -0,0 +1,9 @@
+I've recently found the following problem:
+
+I really really want to get back my original folder structure - which includes the real files, not the symlinks. I've searched for quite a while, but I simply could not find an acceptable solution...
+
+So I thought I would like to ask you guys here, if anybody experienced similar problems (or at least knows a solution for my problem)?
+
+Greetings
+
+Pethor
diff --git a/doc/forum/Revert_file_linkage_to_original_files/comment_1_898ca2c9976e92d22470c7404aa9813f._comment b/doc/forum/Revert_file_linkage_to_original_files/comment_1_898ca2c9976e92d22470c7404aa9813f._comment
new file mode 100644
index 000000000..a72a2cfdd
--- /dev/null
+++ b/doc/forum/Revert_file_linkage_to_original_files/comment_1_898ca2c9976e92d22470c7404aa9813f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-15T09:02:38Z"
+ content="""
+Sounds like you want to switch to [[direct mode]].
+
+(Or possibly to run `git annex unannex`, if you don't want to use git-annex for these files.)
+"""]]
diff --git a/doc/forum/Running_assistant_steps_manually/comment_2_3192f614c929b8060d4fbde56a7adec1._comment b/doc/forum/Running_assistant_steps_manually/comment_2_3192f614c929b8060d4fbde56a7adec1._comment
new file mode 100644
index 000000000..b6c10ee88
--- /dev/null
+++ b/doc/forum/Running_assistant_steps_manually/comment_2_3192f614c929b8060d4fbde56a7adec1._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnRai_qFYPVvEgC6i1nlM1bh-C__jbhqS0"
+ nickname="Matthew"
+ subject="Looks great"
+ date="2013-08-29T12:45:10Z"
+ content="""
+This looks great as I have:
+
+ * A preference for multiple small repositories.
+ * Old versions for `git-annex` due to being on Ubuntu LTS for my server.
+ * A Samsung Galaxy Nexus which somehow seems too slow to run the assistant.
+
+So these steps combined with some locking and maybe `inotify` seem perfect
+"""]]
diff --git a/doc/forum/Running_out_of__inodes.mdwn b/doc/forum/Running_out_of__inodes.mdwn
new file mode 100644
index 000000000..417de18de
--- /dev/null
+++ b/doc/forum/Running_out_of__inodes.mdwn
@@ -0,0 +1,17 @@
+When syncing with a huge git annex repository on usb disk, my small laptop partition runs out of inodes.
+
+Any workaround for this?
+
+- Use bare repository?
+
+ Some git annex command are not supported.
+ This makes managing (particularly adding) files difficult.
+
+- Use a loop file partition with tiny block size and large inode numbers?
+
+ Operations on a huge git repository are slow.
+ On a loop file partition will be slower.
+
+- Maybe shrink the partition and make room for a specific partition for git annex repository?
+
+Any opinions?
diff --git a/doc/forum/Running_out_of__inodes/comment_1_abc73d9ad662ef642337b683bf0a0253._comment b/doc/forum/Running_out_of__inodes/comment_1_abc73d9ad662ef642337b683bf0a0253._comment
new file mode 100644
index 000000000..11f2f7b7e
--- /dev/null
+++ b/doc/forum/Running_out_of__inodes/comment_1_abc73d9ad662ef642337b683bf0a0253._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T20:37:05Z"
+ content="""
+Define \"huge\"? Checking out a git repository necessarily requires one inode per file in the repository, plus a smaller quantity for the things in .git. A git-annex repository is much the same as any other git repository.
+
+Even when I make a really tiny 100 mb ext4 filesystem, it defaults to 25000 inodes, which would be enough to contain a checkout of my second largest git-annex repository.
+
+Anyway, using git branches seems like a reasonable workaround, to the extent I understand your problem. Make a branch with the files in it you want to have available on the small drive, or check out an empty branch on the small drive and `git annex add` files in there. You can merge the branch back into your master branch on the large drive.
+"""]]
diff --git a/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__.mdwn b/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__.mdwn
new file mode 100644
index 000000000..53d0e0165
--- /dev/null
+++ b/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__.mdwn
@@ -0,0 +1,6 @@
+Hi,
+
+When using git-annex assistant, is there a possibility to share only certain files or directories from a repository (similar to what Dropbox can do), or do we have to share whole repositories so far?
+Could this be a nice wishlist item, or is there a strong reason against adding this feature to git-annex?
+
+Thanks a lot!
diff --git a/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__/comment_1_ec0d56cb31b918023a9184cee168b406._comment b/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__/comment_1_ec0d56cb31b918023a9184cee168b406._comment
new file mode 100644
index 000000000..8fa6f7b40
--- /dev/null
+++ b/doc/forum/Share_only_certain_files_of_a_repo___40__Assistant__41__/comment_1_ec0d56cb31b918023a9184cee168b406._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.255.110"
+ subject="comment 1"
+ date="2013-09-09T19:44:57Z"
+ content="""
+Everyone can see the names of every file that is put into the git repository. Whether the contents of those files is transferred from the machine where they were created to other clones of the repository is configurable using [[preferred_content]], but it's not really intended as an access control mechanism.
+"""]]
diff --git a/doc/forum/Share_with_friend_copies_only_sym_links.mdwn b/doc/forum/Share_with_friend_copies_only_sym_links.mdwn
new file mode 100644
index 000000000..8f31b6337
--- /dev/null
+++ b/doc/forum/Share_with_friend_copies_only_sym_links.mdwn
@@ -0,0 +1,38 @@
+I just setup git-annex across three macs, using git-annex assistant. I have one repository working fine, which successfully syncs between two of my own accounts on two different machines, via S3.
+
+Now I'm trying to get the "share with a friend" feature to work. The problem is that only Mac Alias's / sym links are created, for example:
+
+Machine 1:
+- Copy file into ~/annex/
+
+Machine 2:
+- The file is synced as a sym-link, with a link into a file in .git that doesn't exist.
+
+The config is:
+- Version: 4.20130909-ga29f960 - Build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS Feeds Quvi
+- Two macs
+- Share with friend over Jabber
+- Use Box as the cloud sync service with encryption enabled. Box is setup as a transfer repository.
+
+I've looked through the logs in .git/annex/daemon.log* and there doesn't look to be any problems.
+
+This is what the log looks like:
+
+ [2013-09-14 19:55:47 PDT] Committer: Adding 20120101-..084-1.jpg
+ failed
+ add /Users/nick/Shared/20120101-GOPR0084-1.jpg (checksum...) ok
+ add /Users/nick/Shared/20120101-GOPR0084-1.jpg (checksum...) ok
+ add /Users/nick/Shared/20120101-GOPR0084-1.jpg (checksum...) ok
+ add /Users/nick/Shared/20120101-GOPR0084-1.jpg (checksum...) ok
+ add /Users/nick/Shared/20120101-GOPR0084-1.jpg (checksum...) [2013-09-14 19:55:47 PDT] Committer: Committing changes to git
+ [2013-09-14 19:55:48 PDT] XMPPSendPack: Syncing with USER2
+ Already up-to-date.
+ To xmpp::USER2@gmail.com
+ 7b65b15..183b91c git-annex -> refs/synced/6163ef8e-c36a-4b09-919b-9c18ade55234/bmlja2JsYWNrMUBnbWFpbC5jb20=/git-annex
+ 3104275..96afa09 master -> refs/synced/6163ef8e-c36a-4b09-919b-9c18ade55234/bmlja2JsYWNrMUBnbWFpbC5jb20=/master
+ [2013-09-14 19:55:49 PDT] XMPPSendPack: Syncing with USER2
+ Everything up-to-date
+ recv: resource vanished (Connection reset by peer)
+
+
+Any ideas what I should look at next? Thanks in advance :-)
diff --git a/doc/forum/Share_with_friend_copies_only_sym_links/comment_1_a8d22dfefb219f0c9130cc294364b198._comment b/doc/forum/Share_with_friend_copies_only_sym_links/comment_1_a8d22dfefb219f0c9130cc294364b198._comment
new file mode 100644
index 000000000..84217711a
--- /dev/null
+++ b/doc/forum/Share_with_friend_copies_only_sym_links/comment_1_a8d22dfefb219f0c9130cc294364b198._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 1"
+ date="2013-09-19T17:41:47Z"
+ content="""
+git-annex can only share the contents of files with a friend when you both have access to a transfer repository. Your friend's git-annex webapp should detect that it does not have such a repository, and should be displaying an alert like this:
+
+[[assistant/cloudnudge.png]]
+(But in this case it should say \"Unable to download files from YourName\")
+
+So, you need to give your friend access to the S3 repository that you're already using to keep your 2 computers in sync. Or, set up some other transfer repository that you both can access.
+
+There is a way in S3 to create another key that can read and write to a S3 bucket. You can then give that key to your friend.
+
+Or, you could set up a shared git repository on a ssh server you both have access to. Or, set up a box.com remote -- the webapp will offer to store the box.com credentials and share them with your friend.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts.mdwn b/doc/forum/Slightly_finer_control_over_file_whereabouts.mdwn
new file mode 100644
index 000000000..2caf332af
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts.mdwn
@@ -0,0 +1,18 @@
+I have previously been confused by how to have a bit more manual control over where files are (as in [[bugs/git-annex_immediately_re-gets_dropped_files/]]).
+
+I thought perhaps something like an archive directory would work, but as I might want different computers to have different content, perhaps a per-computer archive repository.
+
+To that end, I have
+
+<pre>walter@dionysus:~/annex$ git annex content .
+(exclude=archive/dionysus/* or (not (copies=archive:1 or copies=smallarchive:1))) or (not copies=semitrusted+:1)
+ok</pre>
+
+which is a modified version of the archive [[preferred_content]], but with the intention that I change the part after `exclude` to be different for each client.
+I also set the group to client for this client (dionysus).
+
+However, it does not seem to drop files when I move them into `archive/dionysus/`, and I cannot see anything in the logs to suggest why.
+
+What am I doing wrong here? Or, is this the wrong approach?
+
+--Walter
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_10_bcb883d46a637dd1a8ef9a92733d202a._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_10_bcb883d46a637dd1a8ef9a92733d202a._comment
new file mode 100644
index 000000000..5064de49d
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_10_bcb883d46a637dd1a8ef9a92733d202a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 10"
+ date="2013-11-08T18:32:12Z"
+ content="""
+If I could comprehensively fix that bug I would.
+
+But, it's supposed to already be fixed when using direct mode. Were you using indirect mode when you saw the problem?
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_11_b7a8b9eaf114f883866fbf2be51b622f._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_11_b7a8b9eaf114f883866fbf2be51b622f._comment
new file mode 100644
index 000000000..7155b560f
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_11_b7a8b9eaf114f883866fbf2be51b622f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 11"
+ date="2013-11-09T06:02:36Z"
+ content="""
+No, this was using direct mode.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_1_6236bcfa9beba705ead3ec2141c5d835._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_1_6236bcfa9beba705ead3ec2141c5d835._comment
new file mode 100644
index 000000000..b9f598a1f
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_1_6236bcfa9beba705ead3ec2141c5d835._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 1"
+ date="2013-09-19T17:57:22Z"
+ content="""
+That sound like it should work. I suggest you play around with `git annex drop --auto` at the command line. It will probably tell you why it is unable to drop a file if the problem is something like not enough copies located elsewhere. Or, if it doesn't try to drop the file at all, you'll know your preferred content expression makes it want to keep the file.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_2_ea935b37ca93e73c85d04df7c9bf6057._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_2_ea935b37ca93e73c85d04df7c9bf6057._comment
new file mode 100644
index 000000000..50f113aa3
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_2_ea935b37ca93e73c85d04df7c9bf6057._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 2"
+ date="2013-09-19T22:22:03Z"
+ content="""
+So, it sort of works...
+
+I realised that I don't have `archive` repository but instead `backup` ones, so adding that makes `git annex drop --auto` want to drop files in archive/dionysus.
+
+However, the webapp then gets them. This I don't understand.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_3_f89a8e38283ac4c8c4a3b74c413d67a1._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_3_f89a8e38283ac4c8c4a3b74c413d67a1._comment
new file mode 100644
index 000000000..41bb0cb58
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_3_f89a8e38283ac4c8c4a3b74c413d67a1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 3"
+ date="2013-09-20T00:15:07Z"
+ content="""
+does `git annex get --auto` also get them?
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_4_07a0a754a089c46ff69dc97ea7ba9384._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_4_07a0a754a089c46ff69dc97ea7ba9384._comment
new file mode 100644
index 000000000..30e3965af
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_4_07a0a754a089c46ff69dc97ea7ba9384._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 4"
+ date="2013-09-20T02:41:22Z"
+ content="""
+I am testing on my laptop, and the content expression there is
+`(exclude=archive/kronos/* ) or (not copies=semitrusted+:1)`
+to simplify things; I interpret this to mean it wants everything not in archive/kronos, and it wants things there where that's the only copy.
+
+The problem is that `git annex drop --auto` does indeed drop things, but `git annex get --auto` gets them; surely it should not be possible for that to happen?
+
+I also tried the preferred content expression of `(exclude=archive/kronos/* )`, and the same thing happens.
+
+The version of git-annex that I am using is
+<pre>git-annex version: 4.20130919-g9be7762
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS Feeds Quvi
+local repository version: 4
+default repository version: 3
+supported repository versions: 3 4
+upgrade supported from repository versions: 0 1 2</pre>
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_5_e884c001a556a0c693d1cc9a97c068ac._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_5_e884c001a556a0c693d1cc9a97c068ac._comment
new file mode 100644
index 000000000..50e5cf9af
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_5_e884c001a556a0c693d1cc9a97c068ac._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 5"
+ date="2013-09-20T15:31:18Z"
+ content="""
+Ok. This seems to be a bug in git-annex then. While it's surprisingly difficult to do so, it tries to interpet preferred content expressions in a stable way -- that is, they should not want to get a file when it's missing and then want to drop it when it's present.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_6_3e8674b5857e4994dfbc26be4f4b2855._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_6_3e8674b5857e4994dfbc26be4f4b2855._comment
new file mode 100644
index 000000000..eff5d9339
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_6_3e8674b5857e4994dfbc26be4f4b2855._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 6"
+ date="2013-09-20T15:36:25Z"
+ content="""
+I tried to reproduce this behavior, but failed. My configuration was 2 repos, A and B, with B the origin of A. A was configured with \"exclude=archive/kronos/*\"
+(also tried \"(exclude=archive/kronos/* ) or (not copies=semitrusted+:1)\")
+
+<pre>
+joey@darkstar:~/tmp/A>git annex get --auto
+joey@darkstar:~/tmp/A>git annex get
+get archive/kronos/foo (from origin...) ok
+(Recording state in git...)
+joey@darkstar:~/tmp/A>git annex drop --auto
+drop archive/kronos/foo ok
+(Recording state in git...)
+joey@darkstar:~/tmp/A>git annex get --auto
+joey@darkstar:~/tmp/A>
+</pre>
+
+... Which is how you want it to behave.
+
+So I wonder if it's something else in your configuration. The best thing to do would be if you can come up with a series of commands I can follow to build repositories that exhibit the problem.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_7_7aeabc2e52a39423e83fbd04560e8f91._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_7_7aeabc2e52a39423e83fbd04560e8f91._comment
new file mode 100644
index 000000000..145a913e9
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_7_7aeabc2e52a39423e83fbd04560e8f91._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 7"
+ date="2013-09-20T15:37:48Z"
+ content="""
+Also, please check if you're running into [[bugs/Handling_of_files_inside_and_outside_archive_directory_at_the_same_time]]
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_8_53b95449cfad2fe0f72d2ad642822c03._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_8_53b95449cfad2fe0f72d2ad642822c03._comment
new file mode 100644
index 000000000..d866380f2
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_8_53b95449cfad2fe0f72d2ad642822c03._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 8"
+ date="2013-09-20T20:30:52Z"
+ content="""
+Hmm, that could be it; the same content is both inside and outside the archive directory.
+
+What I really want to do (because maybe I'm not going about this the best way) is to use the assistant not in manual mode, but allow for some repos not having some files.
+I thought by placing them in an archive directory, then they would be dropped, and to get them again, I can just delete from the archive dir, and they will be got (as the file is also outside the archive dir.
+
+But, if that is not going to work, is there a better way to manage that?
+
+By the way, I really appreciate all the work you put into this awesome project.
+"""]]
diff --git a/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_9_a17c102a45e4fc3f101a79acb8eb4081._comment b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_9_a17c102a45e4fc3f101a79acb8eb4081._comment
new file mode 100644
index 000000000..56d22c7fd
--- /dev/null
+++ b/doc/forum/Slightly_finer_control_over_file_whereabouts/comment_9_a17c102a45e4fc3f101a79acb8eb4081._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnSenxKyE_2Z6Wb-EBMO8FciyRywjx1ZiQ"
+ nickname="Walter"
+ subject="comment 9"
+ date="2013-09-23T21:58:42Z"
+ content="""
+Thinking about this further, I'm not entirely sure what I want. I think the confusion arises from git-annex sometimes (mostly) caring about file *contents* (ie dependent on the hash of the file), but sometimes (preferred content, not sure of anywhere else) caring about file *location*.
+
+What I think I actually want is a way of specifying locations that are not synced, such that if the file is changed somewhere (on another computer), the new version should not be downloaded. But, if the same content is in another location as well, the behaviour should be stable, I don't know how that should work though.
+
+So, perhaps the best strategy is to have an explicit list of locations that I don't want, in the preferred content expression, if it could cope with files being in and out of some location at the same time. I think this would be easiest if I could avoid manually editing the expression all the time, maybe make a file with a list of file locations, if it would be possible for git-annex to handle that? I think it isn't at the moment, and my haskell is non-existent. That way, I could write some helper to add and remove files from this list. For example `dont-want file1 file2 dir1` would add these locations to a file, and `want file1 file2 dir1` would remove them from this list. Actually, I suppose I could make it just create an appropriate preferred-content expression, and then it doesn't need to support some file of locations.
+
+So, after that ramble, I guess I'm envisaging a preferred content expression like `content=(exclude=path/to/file1 and exclude=path/to/file1 and exclude=path/to/dir1/*) or (some statement about numcopies)`, which I imagine updating whenever I decide I do/don't want some file. The only obstacle to this working is [[bugs/Handling of files inside and outside archive directory at the same time]] (as I understand that bug, could be wrong on the implications of it), meaning (of course) if there are two files with the same content, and I exclude one of them, and not the other, then it both wants and doesn't want the file, and it (and I) get really confused.
+
+I suppose a short-term (well, slow) solution is to find duplicates of files I don't want, and if that exists either add the duplicate to my content expression (to say I don't want it), or remove the one I don't want from the expression (to say I do). This doesn't work well for when the content of one of the files changes (and so they are no longer duplicates), but I think I would search for them each time I generate the expression, so at that time it would no longer find the duplicate.
+
+So, @joey, I guess my question is, what are the chances of that bug being resolved somehow? Or if that is not likely to happen soon, I might try to implement my solution outline from the previous two paragraphs.
+"""]]
diff --git a/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version.mdwn b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version.mdwn
new file mode 100644
index 000000000..1f8730514
--- /dev/null
+++ b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version.mdwn
@@ -0,0 +1,9 @@
+Hi!
+
+Just tried various android ssh servers which do work, but have no access to the command line tools shipped with git annex.
+
+From what I gather from the planning docs, sshd was stripped from the android tools to save space. If this were the case, it (naively) seems to me it would have to be simple to re-enable.
+
+Rationale: It would make it super convenient to use command line git annex on my phone alongside the assistant, through letting me type on my desktop. Not to mention that the command line tools shipped with git annex are by far the best around for android work.
+
+Carlo
diff --git a/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_1_5c2f376a82458c6387560355940419d3._comment b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_1_5c2f376a82458c6387560355940419d3._comment
new file mode 100644
index 000000000..9a39a2e4c
--- /dev/null
+++ b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_1_5c2f376a82458c6387560355940419d3._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-02T19:42:13Z"
+ content="""
+sshd was removed from the bundle because it's not needed for git-annex to be used on Android, and it would be very complicated to get it to work. (And would require rooting the device at least for port 22 and probably also since sshd needs to run as root generally.)
+
+If there are android ssh servers that let you choose which user to log in as, you could log in as the app_NN user corresponding to the git-annex android app, and have all the tools available, once you ran runshell. I belive there's also an equivilant to su on android that lets you change to an app_NN user, although you probably already need root.
+
+I think it's more usual to use adb in these situations.
+"""]]
diff --git a/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_2_6321dec0b2f22f841f3cb986e063113f._comment b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_2_6321dec0b2f22f841f3cb986e063113f._comment
new file mode 100644
index 000000000..b1ce5a1a5
--- /dev/null
+++ b/doc/forum/Suggestion:_Put_ssh_server_back_into_android_version/comment_2_6321dec0b2f22f841f3cb986e063113f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 2"
+ date="2013-11-03T09:48:53Z"
+ content="""
+Ah, the \"very complicated to get it to work\" part is what I didn't know, thanks for explaining and or the tips.
+"""]]
diff --git a/doc/forum/Sync_with_one_offline_peer.txt b/doc/forum/Sync_with_one_offline_peer.txt
new file mode 100644
index 000000000..6ee05c6e6
--- /dev/null
+++ b/doc/forum/Sync_with_one_offline_peer.txt
@@ -0,0 +1,11 @@
+Hello,
+
+I use the assistant to set up two repositories A and B synced using jabber. A third repository C on my server is used as rsync transfer. Syncing works fine between both repos when both are online.
+
+But when either A or B is offline the sync does not happen when it comes online again, though the file was synced to C.
+
+Is this because C is only a rsync repository and can't hold metadata? How can I achieve that the sync happens also when one of the repositories is offline?
+
+I also tried using the static build of git annex on my server. It seemed to run fine but during the setup the assistant got an error about too many command line arguments. On A und B I use the ArchLinux AUR build (https://aur.archlinux.org/packages/git-annex-standalone/), on C I use the static build. Could it be a version mismatch?
+
+Thanks!
diff --git a/doc/forum/Sync_with_one_offline_peer/comment_1_3859d842d4f7e2ef44877b05ebe881fb._comment b/doc/forum/Sync_with_one_offline_peer/comment_1_3859d842d4f7e2ef44877b05ebe881fb._comment
new file mode 100644
index 000000000..5fe670d35
--- /dev/null
+++ b/doc/forum/Sync_with_one_offline_peer/comment_1_3859d842d4f7e2ef44877b05ebe881fb._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 1"
+ date="2013-09-09T21:49:17Z"
+ content="""
+Another try on the layout:
+
+Hello,
+
+I use the assistant to set up two repositories A and B synced using jabber. A third repository C on my server is used as rsync transfer. Syncing works fine between both repos when both are online.
+
+But when either A or B is offline the sync does not happen when it comes online again, though the file was synced to C.
+
+Is this because C is only a rsync repository and can't hold metadata? How can I achieve that the sync happens also when one of the repositories is offline?
+
+I also tried using the static build of git annex on my server. It seemed to run fine but during the setup the assistant got an error about too many command line arguments. On A und B I use the ArchLinux AUR build (https://aur.archlinux.org/packages/git-annex-standalone/), on C I use the static build. Could it be a version mismatch?
+
+Thanks!
+"""]]
diff --git a/doc/forum/Sync_with_one_offline_peer/comment_2_c9ba3983b37b0c1868269616fd81e518._comment b/doc/forum/Sync_with_one_offline_peer/comment_2_c9ba3983b37b0c1868269616fd81e518._comment
new file mode 100644
index 000000000..20b82dd3e
--- /dev/null
+++ b/doc/forum/Sync_with_one_offline_peer/comment_2_c9ba3983b37b0c1868269616fd81e518._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 2"
+ date="2013-09-12T21:13:36Z"
+ content="""
+Yes, the rsync repository is not a git repository and so does not hold metadata. If you can install git-annex on your server, you can add a regular git repository there, and then the clients can sync to it even when the other is offline.
+
+This is also why I an working on adding support for [[special_remotes/gcrypt]] repositories, so you can have a fully encrypted git repository on the server and sync through that.
+
+> during the setup the assistant got an error about too many command line arguments
+
+I have never heard about such a problem. You should file a bug report with the details.
+"""]]
diff --git a/doc/forum/Sync_with_one_offline_peer/comment_3_28b9c003b4560c3ce90c9ebf808b091b._comment b/doc/forum/Sync_with_one_offline_peer/comment_3_28b9c003b4560c3ce90c9ebf808b091b._comment
new file mode 100644
index 000000000..332cd83c3
--- /dev/null
+++ b/doc/forum/Sync_with_one_offline_peer/comment_3_28b9c003b4560c3ce90c9ebf808b091b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnsuhFUIfWNT-Q-C02FDaSQqceFDge5M9w"
+ nickname="Florian"
+ subject="comment 3"
+ date="2013-09-13T10:52:33Z"
+ content="""
+Thanks for your reply. The bug report is at <http://git-annex.branchable.com/bugs/git-annex:_Argument_list_too_long/>
+
+I'll be happy to provide any more help if I can!
+"""]]
diff --git a/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__.mdwn b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__.mdwn
new file mode 100644
index 000000000..9315d9218
--- /dev/null
+++ b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__.mdwn
@@ -0,0 +1,4 @@
+I created an "full archive" repo on my local pc and an encrypted "full backup" repo on Box.com. I 'm copying files on the local repo and they are getting encrypted and uploaded to Box. Superb so far :)
+
+What I am wondering though is, suppose my local pc dies. How do I get the data out of Box unencrypted from a new pc?
+
diff --git a/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_1_cd55d06a4065b9d3f14d50674c3fcaf7._comment b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_1_cd55d06a4065b9d3f14d50674c3fcaf7._comment
new file mode 100644
index 000000000..5a5ec3589
--- /dev/null
+++ b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_1_cd55d06a4065b9d3f14d50674c3fcaf7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 1"
+ date="2013-09-22T21:18:17Z"
+ content="""
+Just clone the repository on another computer or usb drive and enable box.com remote as long as you have the clone of the repo you can download your files back.
+"""]]
diff --git a/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_2_25cbdf478091af9923090e049c432a7d._comment b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_2_25cbdf478091af9923090e049c432a7d._comment
new file mode 100644
index 000000000..69db183e2
--- /dev/null
+++ b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_2_25cbdf478091af9923090e049c432a7d._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="John"
+ ip="109.242.130.160"
+ subject="comment 2"
+ date="2013-09-22T22:20:22Z"
+ content="""
+Thank you Hamza!
+
+I 'm new on git, so please excuse my trivial questions:
+
+a) I am using the git-annex assistant, is it something I can do from there or is it command line only?
+I googled a bit and from what I can tell, I should make a directory on the usb drive, go there and do
+> $ git clone /path/to/fullArchiveRepo
+
+Would that be correct?
+
+b) Assuming I 've done it correctly, then I put the USB on a drawer and leave it there for a month. In the meantime, I 've been using the repo on my pc and more files have been archived encrypted on Box.com. Then my local pc dies. When I plug the usb on the new pc, will I be able to recover all the encrypted files, or only those up to 1 month ago?
+
+c) What is the proper process to use the cloned repo on a new pc? Plug the usb drive, open the git-annex assistant and go through the \"create new repo\" but use the path for the existing repo on the usb? Then add another repo from Box (with the same account and the same directory there? Would that work?
+
+Thank you for your time & knowledge! :)
+"""]]
diff --git a/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_3_7e71d355457d6b1a0391d4cdae6895e6._comment b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_3_7e71d355457d6b1a0391d4cdae6895e6._comment
new file mode 100644
index 000000000..81de3fc45
--- /dev/null
+++ b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_3_7e71d355457d6b1a0391d4cdae6895e6._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 3"
+ date="2013-09-23T00:34:24Z"
+ content="""
+I do not use the assistant I prefer command line but try adding an USB drive (last I used it it had the option) It should do the clone and init it check the resulting folder if it contains a .git/ folder you have a clone of your git repo.
+
+a) For manual cloning follow http://git-annex.branchable.com/walkthrough/adding_a_remote/
+
+b) you need to keep syncing to the clone too. asistant should automatically sync to that repo. AFAIK asisstant detects when the usb repo is plugged and automatically syncs to it (again I do not use it but I seem to remember one of joey's talks showing that. YMMV)
+
+If you lose all your repos then you lose the keys to un encrypt files they are gone!, if you have a outdated repo you can get the files back using the key stored in it but without the directory structure.
+
+Correct workflow depends on how you use annex. I sync 3 computers with annex so if one dies I can clone the repo from another one. But if you are only using it on a single computer I would use a clone on an external usb drive that is always connected, so you have two clones one on the internal disk and one on the external disk so you can survive one of the drives crashing.
+"""]]
diff --git a/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_4_a73f67f2fcf0762fbd7c8366b3844af6._comment b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_4_a73f67f2fcf0762fbd7c8366b3844af6._comment
new file mode 100644
index 000000000..7e649f858
--- /dev/null
+++ b/doc/forum/Syncing_with_an_encrypted_remote_from_a_different_computer__63__/comment_4_a73f67f2fcf0762fbd7c8366b3844af6._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 4"
+ date="2013-09-23T20:18:38Z"
+ content="""
+Other good options to supplement an offline backup drive:
+
+* A clone of the repository on another computer of yours, or on an Adroid tablet or phone.
+* An encrypted git repository stored on a remote ssh server. (Supported by recent git-annex releases, although the assistant does not yet have a UI to set this up it's not very hard to do it manually at the command line and then the assistant will use it.)
+"""]]
diff --git a/doc/forum/Truly_purging_dead_repositories/comment_4_477e3c213c5a5d4a33afd42a5b94c718._comment b/doc/forum/Truly_purging_dead_repositories/comment_4_477e3c213c5a5d4a33afd42a5b94c718._comment
new file mode 100644
index 000000000..3f39803b2
--- /dev/null
+++ b/doc/forum/Truly_purging_dead_repositories/comment_4_477e3c213c5a5d4a33afd42a5b94c718._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 4"
+ date="2013-09-04T06:44:42Z"
+ content="""
+Status no longer shows dead repositories.
+
+See also, answer here: <http://git-annex.branchable.com/forum/How_to_delete_a_remote__63__/#comment-7ebf3804709a5aa64f1ca057a7df74f9>
+"""]]
diff --git a/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__.mdwn b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__.mdwn
new file mode 100644
index 000000000..5495e2649
--- /dev/null
+++ b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__.mdwn
@@ -0,0 +1,18 @@
+Hi,
+
+Here is my setup:
+
+* I have a locally networked server Server-A with a large storage hard drive auto-mounted.
+* I have two personal client computers: Client-A and Client-B.
+* Client-A is my primary (desktop) computer.
+* Client-B is my secondary (laptop) computer that I use less often.
+* Git-annex is installed on all 3 computers and I use git-annex assistant on both Client-A and Client-B.
+* Both Client-A and Client-B need to share the same repository/files.
+
+
+What is the best or recommended git-annex assistant repository configuration for this setup? Ideally I want Server-A to have a full backup of the shared repository. I currently have a client repository for both Client-A and Client-B. Also, both Client-A and Client-B have a "full backup" repository pointing to the same repository hosted on Server-A. Is this OK? Should only one of the the client's have this repository as a "full backup"? Will this current setup also have git annex assistant auto-sync the repositories between the clients? I have both clients setup right now and they have both successfully cloned the shared repository, but I have noticed that they have yet to sync up modifications made on the other client. An alternative setup I can think of would be to have Client-A keep its current configuration and have Client-B switch the "full backup" repository to be just a "transfer" repository.
+
+I hope my intentions are clear. Please give me your recommendations.
+
+Regards,
+Blake
diff --git a/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_1_b8702892280447193e6e80be22a580a0._comment b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_1_b8702892280447193e6e80be22a580a0._comment
new file mode 100644
index 000000000..915e7209b
--- /dev/null
+++ b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_1_b8702892280447193e6e80be22a580a0._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlkA6XinbeOdnEDxEGQUWyjqPGh0kdMXr4"
+ nickname="Blake"
+ subject="update"
+ date="2013-10-30T07:19:56Z"
+ content="""
+It seems both Client-A and Client-B ARE actually syncing with this current setup. I think Client-B was just delayed due to the initial startup scan. So I guess at this point I am more or less asking if having both Client-A and Client-B have the remote repository being a \"full backup\" type is appropriate or if there is a better configuration that achieves what I am hoping to have.
+
+Regards,
+Blake
+"""]]
diff --git a/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_2_50cafde7e30b928480d1f142ddd763d2._comment b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_2_50cafde7e30b928480d1f142ddd763d2._comment
new file mode 100644
index 000000000..4495401b2
--- /dev/null
+++ b/doc/forum/Two_computer_setup:___34__transfer__34___or___34__full_backup__34___repository_groups__63__/comment_2_50cafde7e30b928480d1f142ddd763d2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 2"
+ date="2013-11-01T16:47:18Z"
+ content="""
+git-annex keeps track of the repository group on a per repository basis. That is, if the repository on Server-A is a full backup, both Client-A and Client-B will consider it to be one, and use it appropriately. You can't have just Client-A think it's a full backup; this setting will be automatically synced to Client-B.
+
+Your setup sounds ok, although you might need to set up a XMPP account in order for Client-A and Client-B to immediately message one-another when they have new changes to sync. Otherwise, they might only poll Server-A occasionally for changes.
+"""]]
diff --git a/doc/forum/USB_backup_with_files_visible/comment_6_add048a16837f7940a859f21426cdbe9._comment b/doc/forum/USB_backup_with_files_visible/comment_6_add048a16837f7940a859f21426cdbe9._comment
new file mode 100644
index 000000000..95f749574
--- /dev/null
+++ b/doc/forum/USB_backup_with_files_visible/comment_6_add048a16837f7940a859f21426cdbe9._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Confused"
+ date="2013-11-03T00:13:47Z"
+ content="""
+Sorry, I'm confused. I set up a Full Backup repo on a second hard drive, but the files are visible in its directory just like in my Client repos' directories. Are the files not supposed to be visible? Is something wrong?
+"""]]
diff --git a/doc/forum/USB_backup_with_files_visible/comment_7_de227ca9911fe57d7a6d3e037f574fe9._comment b/doc/forum/USB_backup_with_files_visible/comment_7_de227ca9911fe57d7a6d3e037f574fe9._comment
new file mode 100644
index 000000000..0f74efac0
--- /dev/null
+++ b/doc/forum/USB_backup_with_files_visible/comment_7_de227ca9911fe57d7a6d3e037f574fe9._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 7"
+ date="2013-11-03T01:09:16Z"
+ content="""
+You can set it up that way, but the often confusing behavior (including not being able to umount a drive that has the git-annex assistant deamon running in it!) is why the webapp attempt to steer users toward making bare reposotories on USB drives.
+
+If you click on \"Add another repository\" -> \"Removable drive\", you get a bare repository.
+
+If you click on upper-right menu -> \"Add another local repository\" and enter a path, and tell it to combine the repositories, you get a synced non-bare repository, and potentially problems unmounting the drive since you now have 2 assistant daemons running.
+
+I have now added a further link to the nice removable drive path to that second UI path.
+"""]]
diff --git a/doc/forum/USB_backup_with_files_visible/comment_8_0c0ed0e038f7f0e2d2d4ed69b7b29fbc._comment b/doc/forum/USB_backup_with_files_visible/comment_8_0c0ed0e038f7f0e2d2d4ed69b7b29fbc._comment
new file mode 100644
index 000000000..6511343e8
--- /dev/null
+++ b/doc/forum/USB_backup_with_files_visible/comment_8_0c0ed0e038f7f0e2d2d4ed69b7b29fbc._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 8"
+ date="2013-11-03T01:13:26Z"
+ content="""
+Thanks for the explanation, Joey. I just posted a [comment](http://git-annex.branchable.com/bugs/Unnecessary_remote_transfers/#comment-f7110e694a9951d8ab546b8dec568bfa) about this on the bug report too. Maybe the problem is simply that the Removable Drive option doesn't allow using internal, non-removable drives.
+
+BTW, I don't know if this is relevant, but I only see one \"git-annex assistant\" process running.
+"""]]
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.txt
new file mode 100644
index 000000000..6b1c03d9a
--- /dev/null
+++ b/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant.txt
@@ -0,0 +1,22 @@
+1. Set up two computers with a client repository.
+2. Add a removable drive repository and set it to transfer group.
+3. Start adding files to computer #1 repository. See how the files get synced to the usb drive.
+4. Connect the usb drive to computer #2 and see the files getting transferred to computer #2. Everything is looking good.
+
+
+5. Connect the usb drive to computer #1 again.
+6. Add a file that is larger than the remaining size of the usb drive, BUT smaller than the original size of the usb drive.
+7. The file does not get transferred to the usb drive due to lack of disk space.
+
+I would expect the assistant to make some space on the usb drive. Removing the files it knows has been transferred to computer #2, and then transfer the new file to the usb drive. But this does not seem to happen.
+
+Have I missed something about how the transfer group is supposed to work?
+
+
+Using version:
+git-annex version: 4.20130802-g0a52f02
+build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+
+Pre built tar file.
+
+
diff --git a/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant/comment_1_0a6f6054d70009979f4a036e24b7c500._comment b/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant/comment_1_0a6f6054d70009979f4a036e24b7c500._comment
new file mode 100644
index 000000000..f298b56cd
--- /dev/null
+++ b/doc/forum/USB_drive_in_transfer_group_keeps_growing_-_assistant/comment_1_0a6f6054d70009979f4a036e24b7c500._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T19:22:05Z"
+ content="""
+The assistant is supposed to remove files from transfer repositories once the file has been transferred to all known clients. This generally seems to work, with all the transfer repositories I've tested it with. Nothing is special about USB drives compared with other transfer repositories.
+
+Perhaps you have not configured the USB drive as a transfer repository? Or perhaps you have another client repository (even a client repository you had once but have now deleted).
+"""]]
diff --git a/doc/forum/Un-git-annex__63__.mdwn b/doc/forum/Un-git-annex__63__.mdwn
new file mode 100644
index 000000000..68e8068fc
--- /dev/null
+++ b/doc/forum/Un-git-annex__63__.mdwn
@@ -0,0 +1,6 @@
+Hi,
+
+I am using git-annex assistant on my Fedora Linux computer. Everything seems to be working perfectly, however I have noticed that almost all of my files are now symbolic links to cryptic file names located in the .git/ directory. Oddly though it seems files inside git-annex assistant does not move/symbolic link files within git repositories inside my git-annex assist directories. My question is: how can I safely uninstall git-annex from my machine and restore all files to their non-symbolic link states? When I click on the settings drop-down for a repository inside git-annex assistant and choose disable it goes to the same page as the delete option. Any ideas?
+
+Regards,
+Blake
diff --git a/doc/forum/Un-git-annex__63__/comment_1_6059265afb66190d325083e0f28bcf33._comment b/doc/forum/Un-git-annex__63__/comment_1_6059265afb66190d325083e0f28bcf33._comment
new file mode 100644
index 000000000..907293f99
--- /dev/null
+++ b/doc/forum/Un-git-annex__63__/comment_1_6059265afb66190d325083e0f28bcf33._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://edheil.wordpress.com/"
+ ip="99.54.57.201"
+ subject="comment 1"
+ date="2013-10-06T06:45:14Z"
+ content="""
+\"git annex uninit\" is the command which will revert an entire git annex repository back to a bunch of ordinary files, untracked by git annex (or git). I'm not sure whether there is a way to issue that command from the assistant though.
+
+
+"""]]
diff --git a/doc/forum/Un-git-annex__63__/comment_2_fac4bfb81dbbf0dc82059aace261eb51._comment b/doc/forum/Un-git-annex__63__/comment_2_fac4bfb81dbbf0dc82059aace261eb51._comment
new file mode 100644
index 000000000..2b1a7381a
--- /dev/null
+++ b/doc/forum/Un-git-annex__63__/comment_2_fac4bfb81dbbf0dc82059aace261eb51._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlOc-EOD5ZyggsAp6lOnU7x5MxizwLtUXA"
+ nickname="Hendrik"
+ subject="comment 2"
+ date="2013-10-06T18:35:14Z"
+ content="""
+I had uninit'd my annex several time for testing git-annex. What I discovered was that is worked reliably but for all files that are duplicates. For duplicates only 1 of the files got restored properly. All that was 1 year ago - so your results my differ. I had found a piece of script in the forum / tips sections that will show all duplicates.
+
+Hope this helps...
+"""]]
diff --git a/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__.mdwn b/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__.mdwn
new file mode 100644
index 000000000..0d102b0d4
--- /dev/null
+++ b/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__.mdwn
@@ -0,0 +1,13 @@
+I'm trying to figure out if git-annex can be used for the following use case:
+
+- 2 repos in direct mode A and B
+- A is on a local filesystem, B could be a NFS mountpoint or ssh
+- B contains a number of toplevel directories, A contains a subset of those
+- For the subset in A all changes in those directories that happen on A or B should be synced automatically between both repos, including file removals.
+- A can decide to not carry a toplevel dir any more, but it must still exist in B.
+- A can copy new toplevel dirs from B and those should be synced from then on.
+
+I've been looking at the docs and played with two test repos, but I cannot seem to make the above work. To me it looks like I would need a possibility include/exclude paths from syncing via a regex.
+
+Thanks,
+Felix
diff --git a/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__/comment_1_a0a272a0931b27e5c94b93e42656b62c._comment b/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__/comment_1_a0a272a0931b27e5c94b93e42656b62c._comment
new file mode 100644
index 000000000..3e930b542
--- /dev/null
+++ b/doc/forum/Use_case_with_syncing_only_a_subset_possible__63__/comment_1_a0a272a0931b27e5c94b93e42656b62c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T20:39:51Z"
+ content="""
+I guess you might be using the git-annex assistant. If you were just using git-annex at the command line, you could simply only run `git annex get` on the files or directories you wanted to get.
+
+You can control which directories the git-annex assistant downloads/uploads files for using [[preferred_content]] expressions. Or the easy solution is to use the webapp to put the repository into \"manual mode\" and then manually run `git annex get` as described above to get just the files you want. (And `git annex copy --to remote` to share new files you make.)
+"""]]
diff --git a/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_1_85806316ed28d7a891f04fab4027141b._comment b/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_1_85806316ed28d7a891f04fab4027141b._comment
new file mode 100644
index 000000000..b175204e5
--- /dev/null
+++ b/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_1_85806316ed28d7a891f04fab4027141b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://thkoch2001.myopenid.com/"
+ nickname="thkoch"
+ subject="It would also be nice, if git-annex would use btrfs reflinks on unlock"
+ date="2013-08-24T12:46:40Z"
+ content="""
+I don't know whether git-annex already does use btrfs reflinks, but I suspect, that I double the size of my git-annex repo folder on disk when I unlink all files.
+"""]]
diff --git a/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_2_ecb411a2c4d67917b734a90bd460d44b._comment b/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_2_ecb411a2c4d67917b734a90bd460d44b._comment
new file mode 100644
index 000000000..a4ade5792
--- /dev/null
+++ b/doc/forum/Use_reflinks_on_BTRFS_instead_of_symlinks___63__/comment_2_ecb411a2c4d67917b734a90bd460d44b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-24T15:54:02Z"
+ content="""
+git-annex has always used cp --reflink=auto, including when it cp's the file in `git annex unlock`.
+
+You can verify this with --debug.
+"""]]
diff --git a/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__.mdwn b/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__.mdwn
new file mode 100644
index 000000000..985bff87c
--- /dev/null
+++ b/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__.mdwn
@@ -0,0 +1,36 @@
+I don't know if this is an "unusual setup" or something that should be supported, but it seems like a reasonable use case to me, so here goes:
+
+I have three systems: a desktop, a laptop, and a little netbook. I have one main annex that is currently synced between the desktop and the laptop at ~/annex on both, and to a secondary, Full Backup repo on the desktop, under /mnt.
+
+I have some music on my laptop, and I like to sync ~/Music between the laptop and the netbook. So I thought I'd make a new git-annex repo at ~/Music on both and sync them. I want this to be kept separate from ~/annex.
+
+I also thought it would be good to backup the music, so I thought I'd connect laptop:~/Music to the Full Backup repo at desktop:/mnt. So I paired the repo at laptop:~/Music to the repo at desktop:/mnt.
+
+So I had set up these repos:
+
+* desktop:
+ * /mnt (Full Backup)
+ * ~/annex (Client)
+* laptop:
+ * ~/annex (Client)
+ * ~/Music (Client)
+* netbook:
+ * ~/Music (Client)
+
+As I feared--but I wasn't sure, since I'm new to git-annex--since the desktop:/mnt repo was connected to laptop:~/Music, and desktop:~/mnt was also connected to desktop:~/annex, this caused everything in laptop:~/Music to be synced to desktop:~/annex, because they were part of the same "set" of repos; they were all in the same .git/config files.
+
+So now I have a few problems:
+
+1. How do I get all these music files out of my ~/annex repos? I tried removing the remote repos from ~/annex/.git/config and then running 'git-annex unused', but that didn't result in it thinking all the music files were unused. Do I have to delete them all manually? (There are a *lot* of directories from ~/Music now in ~/annex).
+
+2. It seems that desktop:~/annex/.git is...now over 600 MB, even though few of the actual music files have synced over. Is it possible to clean out ~/annex/.git and restore it to the pre-mess state without starting from scratch?
+
+3. Is it possible--or reasonable--to use a single Full Backup repo for multiple independent client repos? That is, is it possible to do that without the independent client repos "cross-pollinating"? Or do I need to use separate Full Backup repos for each "set" of client repos?
+
+4. I'm not sure if this is a separate problem, but I just want to make sure I understand the best way to handle things like this. I wanted to disconnect desktop:~/annex from laptop:~/Music, but I thought that if I used the webapp to "Delete" the laptop:~/Music repo, it would actually start deleting the music files in laptop:~/Music, after moving them to desktop:~/annex. Am I correct that that would have happened? If so, "Deleting" a repo seems like a dangerous operation that should warn and prompt the user. Maybe an "unlink repo" option needs to be available to simply disconnect two repos and leave their respective contents intact.
+
+I apologize if these are newbie problems. Despite reading every dev blog entry--both before and after the switchover--I'm still new to actually using git-annex. I'm not sure if it's supposed to work this way or if I'm using it wrong.
+
+If I am using it wrong...well, I can imagine other git-annex newbies doing similar things and ending up with similar messes, so maybe this needs to...be considered or something. :) Since I'm still experimenting with git-annex, I haven't put any "live" data in it, so I can blow away all the annexes and start over, but I would like to learn how to properly fix a situation like this in case I goof up in the future.
+
+Thanks for your help.
diff --git a/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__/comment_1_c61c28600f1079fb03ddabc950307f27._comment b/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__/comment_1_c61c28600f1079fb03ddabc950307f27._comment
new file mode 100644
index 000000000..b7119aa2d
--- /dev/null
+++ b/doc/forum/Using_a_single_backup_repo_for_multiple_independent_client_repos__63__/comment_1_c61c28600f1079fb03ddabc950307f27._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-05T16:14:34Z"
+ content="""
+1. Turn off the assistant, switch to indirect mode (`git annex indirect`), use `git log --stat` to find the commit(s) that added the music files, and `git revert` the commits, in reverse chronological order. Or delete the files manually.
+2. You have merged two git repositories. Without some serious git repository surgery (ie, resetting to an old version and deleting the reflog), the full history of both is going to remain stored in git going forward. However, a simple `git gc` might pack that down to a much smaller amount of disk space.
+3. Combining two repositories merges their git histories. You then have two clones of one repository containing the full contents and git history of both. Don't do that if that's not what you want. The webapp is always careful to tell you when an action will combine two repositories.
+4. Once you have combined two repositories, you have two synced repositories that contain the same data. Deleting one of them will just delete one copy of the data. It won't result in data loss, but neither will it untangle the two git trees that were previously combined.
+"""]]
diff --git a/doc/forum/Using_git-annex_via_command_line_in_OS_X.mdwn b/doc/forum/Using_git-annex_via_command_line_in_OS_X.mdwn
new file mode 100644
index 000000000..5eba701bd
--- /dev/null
+++ b/doc/forum/Using_git-annex_via_command_line_in_OS_X.mdwn
@@ -0,0 +1,3 @@
+After installing the binary for Mac OS X and including some larger directories, my computer now seems quite busy (for the last days) with the import process. I see a process called git-annex causing the load, so it seems OK. As the git-annex assistant seems to hang quite a bit, I would like to see the progress using a command line interface. However, I cannot use the "git annex" command as I get the message "git: 'annex' is not a git command. See 'git --help'."
+
+I guess this is my normal git version, installed by homebrew (the OS X version for apt-get) that does not know anything about the installed binary. Can I still use the CLI with this version? Or better, is there or will there be a way to install git-annex from source, or even better using "brew install git-annex"?
diff --git a/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_1_1c9e121f60fb6868c07f1a53b03c4ed0._comment b/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_1_1c9e121f60fb6868c07f1a53b03c4ed0._comment
new file mode 100644
index 000000000..1f51e6c97
--- /dev/null
+++ b/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_1_1c9e121f60fb6868c07f1a53b03c4ed0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnaZYaspvzx1lQiM56UQo-X82BnPiAaiEY"
+ nickname="Martin"
+ subject="comment 1"
+ date="2013-08-19T18:07:04Z"
+ content="""
+One more question. When running the git-annex binary the webapp opens. After closing the window I cannot access the webapp anymore. Using the IP + port number (http://127.0.0.1:53027/) does not work. Would be handy to have a bookmark for the webapp that works as long as the assistant is running.
+"""]]
diff --git a/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_2_52d8ffba82e29ac2722a8e43e469cc47._comment b/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_2_52d8ffba82e29ac2722a8e43e469cc47._comment
new file mode 100644
index 000000000..b30773cd2
--- /dev/null
+++ b/doc/forum/Using_git-annex_via_command_line_in_OS_X/comment_2_52d8ffba82e29ac2722a8e43e469cc47._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnaZYaspvzx1lQiM56UQo-X82BnPiAaiEY"
+ nickname="Martin"
+ subject="git-annex via comand line"
+ date="2013-08-19T21:53:11Z"
+ content="""
+Just found the page how to install the CLI on OS X: http://git-annex.branchable.com/install/OSX/
+That solved all my questions for now.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks.mdwn b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks.mdwn
new file mode 100644
index 000000000..3420c129f
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks.mdwn
@@ -0,0 +1,8 @@
+Hallo,
+
+I have got a Samsung Galaxy Note 10.1 I want to sync with a remote ssh-Server, but the tablet only supports exFAT and FAT file Systems, so I cannot use symlinks.
+
+Does any solution exist for this?
+
+Mebus
+
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_1_b9f202a30ba7e3bc264064d24454c099._comment b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_1_b9f202a30ba7e3bc264064d24454c099._comment
new file mode 100644
index 000000000..f5d4b3cdd
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_1_b9f202a30ba7e3bc264064d24454c099._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-22T17:37:44Z"
+ content="""
+The sad state of affairs that in the supposedly modern 21st century, popular operating systems are regressing in functionality?
+
+Yes, git-annex can deal with this. `git annex init` will detect when it's run on a crippled filesystem and enable various workarounds, including [[direct_mode]].
+
+The git-annex android app deals with all this automatically when creating a repository.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_2_1334a8d9f4bb60f3bf3ebabc656d98d9._comment b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_2_1334a8d9f4bb60f3bf3ebabc656d98d9._comment
new file mode 100644
index 000000000..493aaf65e
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_2_1334a8d9f4bb60f3bf3ebabc656d98d9._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="Mebus"
+ ip="2001:4dd0:ff00:29::2"
+ subject="comment 2"
+ date="2013-10-31T23:39:42Z"
+ content="""
+Hallo,
+
+I tried it again.
+
+On the Android tablet I get many files, which have got a size of 200 Bytes. And they should at least be a view kB.
+
+Why?
+
+Mebus
+
+
+"""]]
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_3_076f22d05fad140068a540e4d835106f._comment b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_3_076f22d05fad140068a540e4d835106f._comment
new file mode 100644
index 000000000..0fb4f61e2
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_3_076f22d05fad140068a540e4d835106f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-01T16:42:33Z"
+ content="""
+Files in the git repository whose content has not yet been downloaded will appear as these short placeholder files when using a filesystem that does not support symlinks. Once the files have been downloaded, that is replaced with their actual content. You may need to set up a way to your android tablet to download the files from the place they're being created.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_4_c8446ee1b817f1824fa0df07e742015c._comment b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_4_c8446ee1b817f1824fa0df07e742015c._comment
new file mode 100644
index 000000000..cd42b6c15
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_4_c8446ee1b817f1824fa0df07e742015c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Mebus"
+ ip="2001:4dd0:ff00:29::2"
+ subject="comment 4"
+ date="2013-11-11T20:24:11Z"
+ content="""
+Does it have to be the place, where they were created or can this also be a central server, I pushed everything to?
+
+Mebus
+
+
+"""]]
diff --git a/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_5_f746c1b85ee8e4b57b6819ccceabd28b._comment b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_5_f746c1b85ee8e4b57b6819ccceabd28b._comment
new file mode 100644
index 000000000..676e7b6f1
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_Android_tablet_which_only_has_exFAT_and_no_symlinks/comment_5_f746c1b85ee8e4b57b6819ccceabd28b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 5"
+ date="2013-11-13T16:37:46Z"
+ content="""
+The git-annex app will download the files from any remote you set up that has a copy of the file. A transfer remote in the cloud would work well.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs.mdwn b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs.mdwn
new file mode 100644
index 000000000..1e6443038
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs.mdwn
@@ -0,0 +1,5 @@
+I've got a Freebox Revolution set-top box / TV NAS at home, with some preconfigured layou for videos, photos and music.
+
+I'd like to use it as a git-annex remote, but am afraid there's no support for FTP (authenticated) or SMB shares exported by the NAS (I don't think it supports other protocols even though runs Linux internally, AFAIK).
+
+Is there any option to store much on that NAS and sync it with git-annex ?
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_1_bd73c8d10028e1b45da9ea8f657e5064._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_1_bd73c8d10028e1b45da9ea8f657e5064._comment
new file mode 100644
index 000000000..d5e8d5404
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_1_bd73c8d10028e1b45da9ea8f657e5064._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="Similar to &quot;direct special remotes&quot;"
+ date="2013-08-16T17:57:26Z"
+ content="""
+You have a very similar problem as I do.
+
+See my post where I called this [direct special remotes](http://git-annex.branchable.com/forum/Direct_special_remotes/).
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_2_16c3c994ee8fcb466e52ca0e812e5915._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_2_16c3c994ee8fcb466e52ca0e812e5915._comment
new file mode 100644
index 000000000..93eef7322
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_2_16c3c994ee8fcb466e52ca0e812e5915._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="Except I don't have rsync/sftp on the NAS AFAICT"
+ date="2013-08-17T08:56:37Z"
+ content="""
+There seemed to be some hope with rsync in your case, but not mine. Thanks anyway for the pointer.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_3_ac60f6edb76bdd541711e472eec9591a._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_3_ac60f6edb76bdd541711e472eec9591a._comment
new file mode 100644
index 000000000..8729a8481
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_3_ac60f6edb76bdd541711e472eec9591a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="Experimenting with a CIFS mount point of the NAS and direct mode"
+ date="2013-08-17T22:11:19Z"
+ content="""
+I've been experimenting with a direct mode repo on a CIFS mount of the SMB share of the NAS.
+
+Unfortunately, it seems I can't propagate changes made on the laptop to the mount point by issueing a git pull or merge, as it is part of the unsafe commands that don't support direct mode (see details in <http://git-annex.branchable.com/direct_mode/#comment-fca93776b9526341e6aae4fe2c53038c>)... direct mode wouldn't be very useful then : I intend to mirror on the NAS the files I've been managing locally. For instance I will sort my photos in subdirs, on the laptop, and intend to mirror that on the NAS.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_4_2194f0600d9a90f0d9c947ea9cc213a3._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_4_2194f0600d9a90f0d9c947ea9cc213a3._comment
new file mode 100644
index 000000000..4a59acdeb
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_4_2194f0600d9a90f0d9c947ea9cc213a3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 4"
+ date="2013-08-23T17:55:39Z"
+ content="""
+Just run `git annex sync` to update the direct mode repository on your NAS.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_5_eb7d13f6b6fa674a2536bde51bfc3fd1._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_5_eb7d13f6b6fa674a2536bde51bfc3fd1._comment
new file mode 100644
index 000000000..e014efb86
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_5_eb7d13f6b6fa674a2536bde51bfc3fd1._comment
@@ -0,0 +1,48 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="So it seems I have found a sequence that seems to be operating fine"
+ date="2013-08-23T20:28:45Z"
+ content="""
+Here's a script, which I think makes it work, using git clone, git annex copy and git annex sync :
+ # The \"master\" remote which is with default indirect mode, on a Linux FS
+ BASE1=~/tmp
+ REPO1=$BASE1/annex-test
+
+ # The \"slave\" remote on the NAS (a Samba server), which has been mounted with cifs, and thus will be in direct mode
+ BASE2=/mnt/freebox-server/
+ REPO2=$BASE2/annex-test
+
+ cd $BASE1
+ mkdir $REPO1
+ cd $REPO1
+ git init
+ git annex init \"my laptop\"
+
+ cd $REPO1
+ cp -Lr ~/some_large_files ./
+ git annex add some_large_files
+ git commit -m \"added\"
+
+ cd $BASE2
+ git clone $REPO1 $REPO2
+ cd $REPO2
+
+ git annex init \"freebox server\"
+ # This is not really needed, but if you want to replicate on a non cifs mount
+ git annex direct
+
+ cd $REPO1
+ git remote add freebox-server $REPO2
+
+ git annex copy --to freebox-server
+ git annex sync
+
+ cd $REPO2
+ git remote add laptop $REPO1
+ #git annex sync
+
+After this, you should have your .git and plain \"direct\" files on the NAS, mirrored from what's on the laptop.
+
+Hope this helps.
+"""]]
diff --git a/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_6_ae323b16ddb9342e91be955408eca3b1._comment b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_6_ae323b16ddb9342e91be955408eca3b1._comment
new file mode 100644
index 000000000..44d3f5a85
--- /dev/null
+++ b/doc/forum/Using_git_annex_with_a_SMB__47__FTP_TV_NAS_with_preconfigured_dirs/comment_6_ae323b16ddb9342e91be955408eca3b1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 6"
+ date="2013-08-24T15:58:28Z"
+ content="""
+You can run any of these operations in any order and it will work. Ie, this is far more complicated and detailed than it needs to be. Just run git-annex commands in any order to do what you want to do. If they don't, file a (detailed) bug report.
+"""]]
diff --git a/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__.mdwn b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__.mdwn
new file mode 100644
index 000000000..c6cb35912
--- /dev/null
+++ b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__.mdwn
@@ -0,0 +1,16 @@
+I'm trying to use git-annex as a dropbox-replacement, but I'm hitting unexpected things although I'm doing exactly what I see in the walkthrough screencast and/or the walkthrough commands. I'm using Ubuntu 13.10, installed git-annex with apt-get. It is version 4.20130815.
+
+1) I launch the webapp and create an ~/annex folder as my initial repo. I copy some small text files in it, I see in webapp that they are added.
+2) I add a new "Removable Storage" repo, in my usb drive. I do not touch any other settings, leave it as is. (ie in transfer group for example). It is successfully added to the repo list and I see sync complete and files synced on the webapp.
+3) When I check the contents of the usb disk annex folder, I see the following, while I was expecting to see the files I synced instead.
+
+emre@emrenb:~$ ls /media/emre/348B-78F0/annex/
+annex branches config description HEAD hooks info objects refs
+
+However, I expect the below which is the content of my ~/annex folder:
+emre@emrenb:~$ ls annex/
+unison-sync.log unison-1.log unison-2.log unison.log
+
+In the walkthrough video, when Joey adds a USB storage, the filenames & thir contents sync to the usb drive. Why doesn't it work for me?
+
+Note that I tried also android app and also the zipped tarball build. Same result, I never see actual files.
diff --git a/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_1_cdac15fec6fc41d5487b7f653fa718a4._comment b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_1_cdac15fec6fc41d5487b7f653fa718a4._comment
new file mode 100644
index 000000000..437e2ecdc
--- /dev/null
+++ b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_1_cdac15fec6fc41d5487b7f653fa718a4._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk3HGoDpnOPob5jOjvIootmkve1-nCpRiI"
+ nickname="Kalle"
+ subject="Default removable storage repo not readable without git annex"
+ date="2013-10-21T08:50:50Z"
+ content="""
+Hi,
+
+Sounds to me you are expecting the files to be readable by a filemanager? By default a removable drive repo is only readable by git-annex.
+
+The standard use case is to move files between computers with git-annex installed. I agree this is not what you´d expect.
+
+Read <http://git-annex.branchable.com/forum/USB_backup_with_files_visible/> and the last post of <http://git-annex.branchable.com/forum/Can__39__t_get_git-annex_merge_to_work_from_git_hook/> for more info.
+"""]]
diff --git a/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_2_82050b7dc367ca5968ab0306db9bd7e3._comment b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_2_82050b7dc367ca5968ab0306db9bd7e3._comment
new file mode 100644
index 000000000..edcc49a35
--- /dev/null
+++ b/doc/forum/Walkthrough_does_not_work_for_me__44___what_am_i_doing_wrong__63__/comment_2_82050b7dc367ca5968ab0306db9bd7e3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 2"
+ date="2013-10-21T22:29:14Z"
+ content="""
+Kalle is right (I seem to keep saying that, Kalle!)
+
+Following the walkthrough commands will get you a non-bare git repository on a removable drive, and you can run \"git annex sync\" in there periodically and see all the files in your repository on the removable drive. The webapp does not make that kind of repository though, and in the screencast I'm showing the normal behavior of the webapp.
+"""]]
diff --git a/doc/forum/Wishlist:_Bittorrent-like_transfers.mdwn b/doc/forum/Wishlist:_Bittorrent-like_transfers.mdwn
index 8352a4eda..7ec663216 100644
--- a/doc/forum/Wishlist:_Bittorrent-like_transfers.mdwn
+++ b/doc/forum/Wishlist:_Bittorrent-like_transfers.mdwn
@@ -1,4 +1,4 @@
-**EDIT: Mistakenly posted this thread in the forum. I created a new post in todo. Link: http://git-annex.branchable.com/todo/Bittorrent-like_features/?updated**
+**EDIT: Mistakenly posted this thread in the forum. I created a new post in [[todo|todo/Bittorrent-like_features]]
Do you think it would be possible to have bittorrent-like transfers between remotes, so that no one remote gets pegged too hard with transfers? It would be great if you distribute your files between multiple bandwidth-capped remotes, and want fast down speed. Obviously, this isn't a simple task, but the protocol is already there, it just needs to be adapted for the purpose (and re-written in Haskell...). Maybe some day in the future after the more important stuff gets taken care of? It could be an enticing stretch goal.
diff --git a/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__.mdwn b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__.mdwn
new file mode 100644
index 000000000..a9db915da
--- /dev/null
+++ b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__.mdwn
@@ -0,0 +1,45 @@
+Hi,
+
+Some time ago I asked [[here|git_annex_copy_--fast_--to_blah_much_slower_than_--from_blah]]
+about possible improvements in git `copy --fast --to`, since it was painfully slow
+on moderately large repos.
+
+Now I found a way to make it much faster for my particular use case, by
+accessing some annex internals. And I realized that maybe commands like `git
+annex find --in=repo` do not batch queries to the location log. This is based on
+the following timings, on a new repo (only a few commits) and about 30k files.
+
+ > time git annex find --in=skynet > /dev/null
+
+ real 0m55.838s
+ user 0m30.000s
+ sys 0m1.583s
+
+
+ > time git ls-tree -r git-annex | cut -d ' ' -f 3 | cut -f 1 | git cat-file --batch > /dev/null
+
+ real 0m0.334s
+ user 0m0.517s
+ sys 0m0.030s
+
+Those numbers are on linux (with an already warm file cache) and an ext4 filesystem on a SSD.
+
+The second command above is feeding a list of objects to a single `git cat-file`
+process that cats them all to stdout, preceeding every file dump by the object
+being cat-ed. It is a trivial matter to parse this output and use it for
+whatever annex needs.
+
+Above I wrote a `git ls-tree` on the git-annex branch for simplicity, but we could
+just as well do a `ls-tree | ... | git cat-file` on HEAD to get the keys for the
+annexed files matching some path and then feed those keys to a cat-file on
+the git-annex branch. And this still would be an order of magnitude faster than
+what currently annex seems to do.
+
+I'm assuming the bottleneck is in that annex does not batch the `cat-file`, as the rest of logic needed for a find will be fast. Is that right?
+
+Now, if the queries to the location log for `copy --to` and `find` could be batched this way, the
+performance of several useful things to do, like checking how many annexed files
+we are missing, would be bastly improved. Hell, I could even put that number on
+the command line prompt!
+
+I'm not yet very fluent in Haskell, but I'm willing to help if this is something that makes sense and can be done.
diff --git a/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_1_01cbfc513c790faef3a3ede5315d3589._comment b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_1_01cbfc513c790faef3a3ede5315d3589._comment
new file mode 100644
index 000000000..6b4a6b2a0
--- /dev/null
+++ b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_1_01cbfc513c790faef3a3ede5315d3589._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-06T22:21:33Z"
+ content="""
+git-annex uses cat-file --batch, yes. You can verify this with --debug. Or you can read Annex/CatFile.hs and Git/CatFile.hs
+
+git-annex has to ensure that the git-annex branch is up-to-date and that any info synced into the repository is merged into it. This can require several calls to git log. Your command does not do that. git-annex find also runs `git ls-files --cached`, which has to examine the state of the index and of files on disk, in order to only show files that are in the working tree. Your command also omits that.
+"""]]
diff --git a/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_2_fe28dfb360caa12d5d5bc186def3eb45._comment b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_2_fe28dfb360caa12d5d5bc186def3eb45._comment
new file mode 100644
index 000000000..4ba4c8264
--- /dev/null
+++ b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_2_fe28dfb360caa12d5d5bc186def3eb45._comment
@@ -0,0 +1,35 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkkyBDsfOB7JZvPZ4a8F3rwv0wk6Nb9n48"
+ nickname="Abdó"
+ subject="comment 2"
+ date="2013-11-06T23:14:03Z"
+ content="""
+Ok, then I don't understand where annex spends its time. git annex takes 55
+seconds! vs less than a second for a batched query on all the keys in the
+location log. Checking that branches are in sync, or traversing the working dir
+shouldn't amount the extra 54 seconds! At least not on a recently synced repo
+with up to date index and clean working dir.
+
+> git-annex has to ensure that the git-annex branch is up-to-date and that any info synced into the repository is merged into it. This can require several calls to git log
+
+Ok, I understand that. Checking that should be typically fast though, isn't it? On a repo that has just been synced, it doesn't need to go very far on the log.
+
+> git-annex find also runs git ls-files --cached, which has to examine the state of the index and of files on disk, in order to only show files that are in the working tree
+
+I understand that too. For my particular use case, I know I do the `git copy` when the
+repo is in sync and the working dir has no uncommited changes. So I use HEAD to retrieve the keys for
+the files in the working tree. I do something like that:
+
+ time git ls-tree -r HEAD | grep -e '^120000' | cut -d ' ' -f 3 | cut -f 1 | git cat-file --batch > /dev/null
+
+ real 0m0.178s
+ user 0m0.277s
+ sys 0m0.037s
+
+That plus some fast parsing of the output gets the list of keys for the files in HEAD in less than a second. Where do the 54 extra seconds hide, then?
+
+Mm... how does annex retrieve the keys for files in the working tree? Does it follow
+the actual symlinks on the filesystem? I can believe that following 30k symlinks may be slow (although not 55 second slow).
+
+Sorry for being so insistent on this... It is just that I do think the same can be done much faster, and such an improvement in performance would be very interesting, not only for me.
+"""]]
diff --git a/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_3_9bb30ab62febe4ef63bed49f831a473a._comment b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_3_9bb30ab62febe4ef63bed49f831a473a._comment
new file mode 100644
index 000000000..c92be8ad5
--- /dev/null
+++ b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_3_9bb30ab62febe4ef63bed49f831a473a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-07T18:12:09Z"
+ content="""
+It's hard to say until some profiling has actually been done. Comparing apples and oranges, or perhaps better to say, orange blossoms and oranges, is not very useful.
+"""]]
diff --git a/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_4_7832f0347a41b8204538c01b72487803._comment b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_4_7832f0347a41b8204538c01b72487803._comment
new file mode 100644
index 000000000..3e7eb01db
--- /dev/null
+++ b/doc/forum/_Does_git_annex_find___40____38___friends__41___batch_queries_to_the_location_log__63__/comment_4_7832f0347a41b8204538c01b72487803._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkkyBDsfOB7JZvPZ4a8F3rwv0wk6Nb9n48"
+ nickname="Abdó"
+ subject="comment 4"
+ date="2013-11-07T18:40:27Z"
+ content="""
+Ok, thanks.
+
+I understand that annex is more sophisticated than what I'm proposing. I'm also
+not comparing apples to oranges, what I'm saying is this: All the
+logic and checking and git calls that I thought annex needs to do, take
+much much less time than those 55 seconds. So either I'm missing something big (about 98% of it in execution time), or
+annex is doing something very inefficient. That's all I'm saying, and I was
+hoping that you could clarify that, since you already know the code.
+
+Also I'm sorry for being so annoying. If annex were writen in C, I would either have understood those 55 seconds or sent you a patch making annex faster. Being in
+haskell means that it will take me considerably more time and effort. But if I manage to
+improve things and if it is ok with you I'll send you patches... eventually.
+"""]]
diff --git a/doc/forum/__34__Pairing__34___more_than_two_computers.mdwn b/doc/forum/__34__Pairing__34___more_than_two_computers.mdwn
new file mode 100644
index 000000000..099c7a663
--- /dev/null
+++ b/doc/forum/__34__Pairing__34___more_than_two_computers.mdwn
@@ -0,0 +1,11 @@
+I need some help understanding here.
+
+We use AeroFS at work to sync the normal user files across computers. I'll quite likely be replacing that with git annex as soon as Windows port is stable enough.
+
+How it works is that you create a repo, and share it with one or more users. Then AeroFS discovers what other repos are online and if they're on the local network, and syncs from wherever is most convenient.
+
+This sounds a little like pairing, but with pairing you need to arrange more than 2 devices in a "star" or "chain". This is fine for my own devices, but it becomes brittle if you have lots of devices syncing from each other, which may or may not be online at any given time. The only way around it seems to be to pair each device with each other device, with the labor rising exponentially.
+
+Is this correct? Best compromise for my use case seems to be to just do a star setup and pair everything with an always-on machine. Do you agree?
+
+Thanks! Carlo
diff --git a/doc/forum/__34__Pairing__34___more_than_two_computers/comment_1_80f7a4bb3c66b11e566043407b611bbf._comment b/doc/forum/__34__Pairing__34___more_than_two_computers/comment_1_80f7a4bb3c66b11e566043407b611bbf._comment
new file mode 100644
index 000000000..026681f79
--- /dev/null
+++ b/doc/forum/__34__Pairing__34___more_than_two_computers/comment_1_80f7a4bb3c66b11e566043407b611bbf._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-22T17:41:58Z"
+ content="""
+You're basically correct. Typically if you have a central machine, it's a server, so at that point you're not pairing, but are just adding a ssh server, or some other type of remote.
+
+I think that systems like AeroFS are pretty neat, but my goal is not really to build another one of those. I'd rather make git-annex be able to use such things as [[special_remotes]].
+"""]]
diff --git a/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__.mdwn b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__.mdwn
new file mode 100644
index 000000000..e48bf4cf6
--- /dev/null
+++ b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__.mdwn
@@ -0,0 +1,10 @@
+Hi,
+
+I am trying to understand git-annex, and the walkthroughs on the page did help a lot. I *feel* that git-annex is the solution for my use case: having a large archive, several computers, NAS both at work and at home, being offline during commuting, …
+
+Everything seems to be clear for me when using the command line version. Using annex assistant looks promising, and it is easy to create repositories that match my usage. But now I see that these repositories are in direct mode by default; and I am not sure how this impacts my ability to work with large files. I do not want to end up with git (without annex) handling huge files.
+
+So - can somebody explain how direct mode affects this? Can I switch to indirect mode with the assistant? Am I asking the wrong questions?
+
+thanks,
+Ulli
diff --git a/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_1_d90d1d599ce557af03c6f0f2ea188212._comment b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_1_d90d1d599ce557af03c6f0f2ea188212._comment
new file mode 100644
index 000000000..d762791da
--- /dev/null
+++ b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_1_d90d1d599ce557af03c6f0f2ea188212._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-09T17:36:01Z"
+ content="""
+Files in direct mode are stored in the git annex the same way as when using indirect mode. But you're perhaps right to be wary of using direct mode, it's been quite easy to mess up while using it at the command line until very recently when the [[todo/direct_mode_guard]] was implemented.
+
+You can switch repositories created using the assistant from direct to indirect mode if you like. The assistant works in either mode.
+"""]]
diff --git a/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_2_58b1af497cab132acb28cb5f9283ec2a._comment b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_2_58b1af497cab132acb28cb5f9283ec2a._comment
new file mode 100644
index 000000000..45cec4db5
--- /dev/null
+++ b/doc/forum/assistant__44___direct_mode__44___large_files__44___command_line_-_how_do_these_play_together__63__/comment_2_58b1af497cab132acb28cb5f9283ec2a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkXtBdMgE1d9nCz2iBc4f85xh4izZ_auU"
+ nickname="Ulrich"
+ subject="Thanks"
+ date="2013-11-12T08:57:36Z"
+ content="""
+Ok, thanks for the explanation. I still have to figure out what happens when I annex drop files on a direct repository, and how well all this plays with the Finder on Mac…
+"""]]
diff --git a/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__.mdwn b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__.mdwn
new file mode 100644
index 000000000..c18dfb6ca
--- /dev/null
+++ b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__.mdwn
@@ -0,0 +1,38 @@
+Hi,
+
+I have a question about encryption keys.
+Basically I do not know how to use the data which was copied in case my local
+machine dies?
+
+
+## I have done the following:
+---
+1. copied my ssh public key to a remote server
+1. created a directory and started git annex assistant
+
+ mkdir ~/test_annex
+
+ cd ~/test_annex
+
+ git annex webapp
+
+1. clicked Repository->Add another local repository
+1. Assistant: Where do you want to put this new repository? Me: ~/test_annex "Make Repository"
+1. Assistant "Combine repositories?" Me: "Keep repositories separate"
+1. clicked "Add another repository" clicked "remote server"
+1. filled out "Adding a remote server using ssh" form and clicked "Check this server"
+1. choose "Use an encrypted rsync repository on the server"
+1. Assistant "Repository created" I select "Full backup" as repository group.
+
+So far so good. If I now add a file on my local machine into ~/test_annex something not human readable is created on the remote machine.
+
+What I do not understand is how I use this backup later. I am expecting something along the "hybrid encryption keys" scheme
+explained in this wiki. However I was not able to determine which of my gpg keys was used or how the data was encrypted.
+
+So my question is: "How do I use the encrypted backup remote on a second machine?"
+
+
+
+
+
+
diff --git a/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_1_70200f871b9df49261f32752a6bb0e67._comment b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_1_70200f871b9df49261f32752a6bb0e67._comment
new file mode 100644
index 000000000..9d457a9d2
--- /dev/null
+++ b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_1_70200f871b9df49261f32752a6bb0e67._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-27T21:19:45Z"
+ content="""
+When you create an encrypted rsync repository using the webapp like that, its encryption key is stored in your git repository, using the [[shared encryption scheme|encryption#index2h2]]. No gpg key needs to be used to decrypt files from the rsync repository; anyone with a clone of your git repository can do so. This has its plusses and its minuses; the webapp picks that type of encryption because it's easy to use.
+
+So, the answer is to just make a clone of your repository on the other machine, and then you can use it. There are lots of ways to do that; if you stay in the webapp, go to Add Another Repisitory and any of the \"Share with your other devices\", \"Share with a friend\", or \"Local computer\" options are easy ways to do it.
+
+----
+
+Now, if you had, manually, set up a rsync repository encrypted with the [[hybrid encryption key scheme|encryption#index1h2]], to access it from another computer with clone of the repository you would need to have a gpg key that has been given access to the repository. So you would either copy your gpg secret key to the other computer, or if you don't want to trust that other computer with the your main gpg key, you could make another gpg secret key for that computer, and add that key as one of the keys that can access the encrypted repository. (Or, if the computer belonged to a friend, you could just get their gpg key, and add it.)
+"""]]
diff --git a/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_2_173da510b45f0320ae8aa2df9f14ae7b._comment b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_2_173da510b45f0320ae8aa2df9f14ae7b._comment
new file mode 100644
index 000000000..dbf2178f5
--- /dev/null
+++ b/doc/forum/assistant_created_encrypted__backup_remote:_Howto_restore__63__/comment_2_173da510b45f0320ae8aa2df9f14ae7b._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="Frank"
+ ip="31.19.114.93"
+ subject="Comment 2"
+ date="2013-11-07T19:45:16Z"
+ content="""
+Thank you very much for the explanation! Have fun!
+
+
+
+"""]]
diff --git a/doc/forum/bash_completion.mdwn b/doc/forum/bash_completion.mdwn
new file mode 100644
index 000000000..649ad0457
--- /dev/null
+++ b/doc/forum/bash_completion.mdwn
@@ -0,0 +1 @@
+I wrote more than 2 years ago a bash completion file for git-annex (did I miss an official version?) I just updated it today to match current version of git-annex, it is far from perfect, still incomplete, and probably buggy, but works for me. I tried to attach the file in case it could be useful to someone, but it seems that I can't; is it ok to paste the code directly?
diff --git a/doc/forum/bash_completion/comment_1_5c42c0c8e7fc3224bf5406880f9fd0c4._comment b/doc/forum/bash_completion/comment_1_5c42c0c8e7fc3224bf5406880f9fd0c4._comment
new file mode 100644
index 000000000..7f2f0afd0
--- /dev/null
+++ b/doc/forum/bash_completion/comment_1_5c42c0c8e7fc3224bf5406880f9fd0c4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 1"
+ date="2013-10-10T07:08:21Z"
+ content="""
+I hope it is. I'd love to use it.
+"""]]
diff --git a/doc/forum/bash_completion/comment_2_6cbe3c825db99bf9188a0de8bb937d5b._comment b/doc/forum/bash_completion/comment_2_6cbe3c825db99bf9188a0de8bb937d5b._comment
new file mode 100644
index 000000000..72d5e3fc4
--- /dev/null
+++ b/doc/forum/bash_completion/comment_2_6cbe3c825db99bf9188a0de8bb937d5b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="comment 2"
+ date="2013-10-10T09:22:00Z"
+ content="""
+it is, please publish.
+"""]]
diff --git a/doc/forum/bash_completion/comment_3_948c40f1e46ca220d61365aebcd4f6d7._comment b/doc/forum/bash_completion/comment_3_948c40f1e46ca220d61365aebcd4f6d7._comment
new file mode 100644
index 000000000..fbe659164
--- /dev/null
+++ b/doc/forum/bash_completion/comment_3_948c40f1e46ca220d61365aebcd4f6d7._comment
@@ -0,0 +1,136 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkUwqII7LhbatqAQY1T5ZZOdPEFcQJKG6I"
+ nickname="Rafael"
+ subject="comment 3"
+ date="2013-10-13T16:14:34Z"
+ content="""
+This code needs the bash-completion file for git by Shawn O. Pearce, I think it is distributed by default on debian. Any feed-back or improvement is welcome! I'm far from expert, use at your own risks.
+
+
+ #!bash
+ #
+ # bash completion support for git-annex
+
+ # depends on git completion file (by Shawn O. Pearce):
+ [ -n \"$__git_whitespacelist\" ] || . $BASH_COMPLETION_DIR/git
+
+
+ # almost copy of __git_aliased_command
+ # requires 2 arguments: alias and main command (after git)
+ __git_aliased_subcommand ()
+ {
+ local word cmdline=$(git --git-dir=\"$(__gitdir)\" \
+ config --get \"alias.$1\")
+ for word in $cmdline; do
+ case \"$word\" in
+ \!*) : shell command alias ;;
+ -*) : option ;;
+ *=*) : setting env ;;
+ git) : git itself ;;
+ \"$2\") : main command
+ local found=1 ;;
+ *)
+ [ -n \"${found-}\" ] && echo \"$word\"
+ return
+ esac
+ done
+ }
+
+
+ _git_annex ()
+ {
+ _get_comp_words_by_ref -n =: cur words
+ # $ git annex 2>&1 |sed '1,6d '|grep -v '^$'|grep -v 'commands:$'|cut -c1-12
+ local subcommands=\"
+ add addurl assistant copy drop edit get import importfeed lock
+ mirror move rmurl sync unlock watch webapp content dead describe
+ direct enableremote group indirect init initremote semitrust
+ trust ungroup untrust vicfg addunused dropunused fix forget fsck
+ merge unused upgrade find help list log map status version
+ whereis migrate reinject unannex uninit dropkey
+ \"
+ # plumbing (to complete?): fromkey fuzztest pre-commit rekey test
+ # transferkey transferkeys xmppgit
+ local subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"
+ if [ -z \"$subcommand\" ]; then
+ ## search for aliased subcommand
+ ## works only if the alias is invoked just after git
+ ## (simpler, cf _git function)
+ local maybesubcom maybealias=${words[1]}
+ [ -n \"$maybealias\" ] && # false with a bash alias='git annex'
+ [ \"${maybealias:0:1}\" != '-' ] &&
+ maybesubcom=$(__git_aliased_subcommand \"$maybealias\" annex)
+ for subcommand in $subcommands \"\"; do
+ [ \"$maybesubcom\" = \"$subcommand\" ] && break
+ done
+ [ -z \"$subcommand\" ] &&
+ __gitcomp \"$subcommands\" &&
+ return
+ fi
+ case \"$cur\" in
+ --from=*|--to=*|--trust=*|--semitrust=*|--untrust=*|--in=*)
+ __gitcomp \"here $(__git_remotes)\" \"\" \"${cur##*=}\"
+ ;;
+ --*)
+ __gitcomp \"
+ --force --fast --auto --all --unused --quiet --verbose --json --debug
+ --no-debug --from= --to= --numcopies= --time-limit= --trust= --semitrust=
+ --untrust= --trust-glacier-inventory --backend= --format= --user-agent=
+ --exclude= --include= --in= --copies= --inbackend= --inallgroup=
+ --smallerthan= --largerthan= --not --and --or
+ \"
+ ;;
+ # -*)
+ # __gitcomp \"-( -) -c\"
+ # ;;
+ *)
+ case \"$subcommand\" in
+ # subcommands with PATH (currently outputs wrongly \"uninit\",
+ # and not \"reinject\")
+ # $ tr ' ' '|' <<< $(git annex 2>&1 |sed '1,6d '|grep -v '^$' | \
+ # grep -v 'commands:$'|grep PATH |cut -c1-12)
+ add|copy|drop|edit|get|import|lock|mirror|move|unlock|fix| \
+ fsck|find|list|log|status|whereis|migrate|unannex| \
+ fromkey|pre-commit|rekey|reinject)
+ COMPREPLY=() # complete with paths
+ ;;
+ addurl|importfeed|rmurl) # URL commands
+ COMPREPLY=() # at least works with file://...
+ ;;
+ init|uninit|unused|merge|status|map|upgrade|version|assistant| \
+ watch|webapp|direct|indirect|vicfg|forget|help) # | plumbing...
+ COMPREPLY= # no more args expected
+ # is 'COMPREPLY=' correct? (seems not standard practice...)
+ ;;
+ describe|trust|untrust|semitrust|sync|content|dead|group|ungroup)
+ __gitcomp \"here $(__git_remotes)\"
+ # TODO: handle git-annex special remotes
+ ;;
+ initremote|enableremote)
+ case \"$cur\" in
+ type=*)
+ __gitcomp \"S3 bup directory rsync gcrypt webdav\" \"\" \"${cur##type=}\"
+ ;;
+ encryption=*)
+ __gitcomp \"none hybrid shared pubkey\" \"\" \"${cur##encryption=}\"
+ ;;
+
+ buprepo=|directory=|rsyncurl=)
+ COMPREPLY=()
+ # use COMPREPLY (and compgen below) directly because
+ # __gitcomp does not handle '*=*' pattern, only '--*=*'
+ # Writing a __gitannexcomp function may be worth it.
+ ;;
+ *)
+ local initremoteopts=\"
+ type= encryption= buprepo= directory= rsyncurl= \"
+ COMPREPLY=($(compgen -W \"$initremoteopts \" -- \"$cur\"))
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ }
+
+"""]]
diff --git a/doc/forum/bash_completion/comment_4_dbae348b230b780cda91ed8576b8f9fa._comment b/doc/forum/bash_completion/comment_4_dbae348b230b780cda91ed8576b8f9fa._comment
new file mode 100644
index 000000000..525a613b0
--- /dev/null
+++ b/doc/forum/bash_completion/comment_4_dbae348b230b780cda91ed8576b8f9fa._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 4"
+ date="2013-10-15T17:53:21Z"
+ content="""
+@Rafael, you should put a license on that code..
+"""]]
diff --git a/doc/forum/cabal_install_fails_on_uuid.mdwn b/doc/forum/cabal_install_fails_on_uuid.mdwn
new file mode 100644
index 000000000..606f7954d
--- /dev/null
+++ b/doc/forum/cabal_install_fails_on_uuid.mdwn
@@ -0,0 +1,23 @@
+Hey, so I am trying to compile git-annex through cabal but it fails on building uuid. It gives me this strange error:
+
+ Resolving dependencies...
+ Configuring uuid-1.3.1...
+ Building uuid-1.3.1...
+ Preprocessing library uuid-1.3.1...
+ [ 1 of 10] Compiling Data.UUID.Builder ( Data/UUID/Builder.hs, dist/build/Data/UUID/Builder.o )
+ [ 2 of 10] Compiling Data.Word.Util ( Data/Word/Util.hs, dist/build/Data/Word/Util.o )
+ [ 3 of 10] Compiling Data.UUID.Internal ( Data/UUID/Internal.hs, dist/build/Data/UUID/Internal.o )
+ Data/UUID/Internal.hs:394:20: Not in scope: `BL.fromStrict'
+ Data/UUID/Internal.hs:399:48: Not in scope: `BL.toStrict'
+ cabal: Error: some packages failed to install:
+ git-annex-4.20131002 depends on uuid-1.3.1 which failed to install.
+ uuid-1.3.1 failed during the building phase. The exception was:
+ ExitFailure 1
+
+Any advice on how to proceed?
+
+System is: Debian Wheezy (CrunchBang Waldorf) 64bit
+
+versions are:
+ uuid-dev: 2.20.1-5.3
+ cabal: 1.14.0
diff --git a/doc/forum/cabal_install_fails_on_uuid/comment_1_2a3963e21bc7ff526124b902cb0b6ad2._comment b/doc/forum/cabal_install_fails_on_uuid/comment_1_2a3963e21bc7ff526124b902cb0b6ad2._comment
new file mode 100644
index 000000000..47fe7e5ff
--- /dev/null
+++ b/doc/forum/cabal_install_fails_on_uuid/comment_1_2a3963e21bc7ff526124b902cb0b6ad2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-22T17:52:10Z"
+ content="""
+That version of the haskell uuid library installs ok on my Debian sid system. Seems to me you have a too old version of the haskell bytestring library, which added `fromStrict` in version 0.10.0.0. Probably `cabal install bytestring` will fix it up for you, but building git-annex from source using cabal is a complicated thing that can go wrong in many ways. Have you considered one of the prebuilt binaries?
+"""]]
diff --git a/doc/forum/cabal_install_fails_on_uuid/comment_2_1609525998e2b36c04d67f4d988139c0._comment b/doc/forum/cabal_install_fails_on_uuid/comment_2_1609525998e2b36c04d67f4d988139c0._comment
new file mode 100644
index 000000000..0f308df0b
--- /dev/null
+++ b/doc/forum/cabal_install_fails_on_uuid/comment_2_1609525998e2b36c04d67f4d988139c0._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkj7tMEJKcZpNXIFkHAAcNi5qJFSFyjn6o"
+ nickname="thissideup"
+ subject="comment 2"
+ date="2013-10-23T11:15:20Z"
+ content="""
+I contacted the maintainer of the uuid-package and he fixed the issue in the current release, so everythings fine now. and: everything compiled beautifully.
+
+But to answer your question: I tend to rather compile things myself if I don't find them (or a current enough version) in the repos - but that's purely personal. ;)
+"""]]
diff --git a/doc/forum/can_I_only_add_my_own_files__63__.mdwn b/doc/forum/can_I_only_add_my_own_files__63__.mdwn
new file mode 100644
index 000000000..555429582
--- /dev/null
+++ b/doc/forum/can_I_only_add_my_own_files__63__.mdwn
@@ -0,0 +1,27 @@
+Hi,
+
+[ sorry for the wrong bugreport in the last version of this entry ]
+
+It seems as if I can only add my own file to the annex, even if I have group write permissions. Is that correct? Can that be circumvented other than copying/deleting the large file?
+
+Here is some demonstration:
+
+ > git init
+ > git config user.name dtr
+ > git config user.email dtrn@dtrn.com
+
+ > dd if/dev/zero of=test2.bin count=1000
+
+ > ll
+ -rw-rw-r-- 1 dtr dtr 512000 Sep 16 2013 test2.bin
+
+ > sudo chown someone test2.bin
+ > ll
+ -rw-rw-r-- 1 someone dtr 512000 Sep 16 2013 test2.bin
+
+ > git annex init
+ > git annex add test2.bin
+ add test2.bin (checksum...)
+ git-annex: /test-git-annex/.git/annex/objects/Fq/f6/SHA256-s512000--2d4da04b861bb9dbe77c871415931785a18138d6db035f1bbcd0cf8277c6fc23/SHA256-s512000--2d4da04b861bb9dbe77c871415931785a18138d6db035f1bbcd0cf8277c6fc23: setFileMode: permission denied (Operation not permitted)
+ failed
+ git-annex: add: 1 failed
diff --git a/doc/forum/can_I_only_add_my_own_files__63__/comment_1_767d647af9d0345f337338d6319071fa._comment b/doc/forum/can_I_only_add_my_own_files__63__/comment_1_767d647af9d0345f337338d6319071fa._comment
new file mode 100644
index 000000000..80efaf04b
--- /dev/null
+++ b/doc/forum/can_I_only_add_my_own_files__63__/comment_1_767d647af9d0345f337338d6319071fa._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:42:00Z"
+ content="""
+git-annex needs to be able to lock down files to ensure that nobody can write to them, and to do this it needs to remove the write bit, and you can't remove the write bit from a file you don't own.
+
+Note that if you configure git's core.sharedRepository when making a repository (git init --shared), then all files in both git and git-annex will be group writable. Put you and the other person you wanted to be able to write to the file in a group, and you can both access the repository. So that's the right way to do it.
+"""]]
diff --git a/doc/forum/can_I_only_add_my_own_files__63__/comment_2_0c3306ffb38b97b54e1e0436d12c1876._comment b/doc/forum/can_I_only_add_my_own_files__63__/comment_2_0c3306ffb38b97b54e1e0436d12c1876._comment
new file mode 100644
index 000000000..5a63a7176
--- /dev/null
+++ b/doc/forum/can_I_only_add_my_own_files__63__/comment_2_0c3306ffb38b97b54e1e0436d12c1876._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 2"
+ date="2013-09-26T06:32:48Z"
+ content="""
+Thanks a lot. The solution with --shared was really helpful.
+"""]]
diff --git a/doc/forum/correct_way_to_add_two_preexisting_datasets.mdwn b/doc/forum/correct_way_to_add_two_preexisting_datasets.mdwn
new file mode 100644
index 000000000..bfc1a6272
--- /dev/null
+++ b/doc/forum/correct_way_to_add_two_preexisting_datasets.mdwn
@@ -0,0 +1,25 @@
+I've been syncronizing my data since long time, mainly using rsync or unison. Thus I had two 3.5Gb datasets set1 (usb drive, hfs+ partition) and set2 (hdd, ext4 ubuntu 13.04 box) which differed only in 50Mb (new on set1 ). This was double checked using diff -r before doing anything.
+
+I created a git annex repo in direct mode for set2 from command line, and after that I let the assistant scan it.
+After that created the repo for set1 and added it to the assistant. I think here comes my mistake (I think).
+
+Instead of keeping them apart, at told assistant to sync with set2.
+Why I think this was a mistake? Because set2 was indexed and set1 no, and I'm seeing a lot of file moving a copying, which in my humble opinion should not happen.
+What I expected it only the difference to be transferred from set1 to set2.
+What it seems to be doing is moving away all content in set1, and copying it back from set2. I think it will end correctly, but with a lot of unnecessary and risky operations.
+
+I think I should have independently added both datasets, let them be scanned and then connect to each other.
+So, now the questions:
+
+1. Is that the correct way to proceed?
+2. What if I have to identical files with different modifying times, I hope they are not synced, right?
+3. Is it posssible to achieve this behaviour of copying only the 50Mb?
+
+Thanks in advance and keep up the good work.
+Best regards,
+ Juan
+
+EDIT: a couple of questions more:
+
+4. after finishing, set2 ended with a lot of symlinks but only in one subfolder. To prevent this should I put numcopies in 2?
+5. This data is composed of input datasets and output simulations. Thus, I need to change them often, but not as often as code and in a very partial way (chunks of 50Mb). For me direct mode is the best (or plain git). However, I was wondering, it is possible to drop some files (even in direct mode) and use simlinks instead?
diff --git a/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_1_c5c3ff25c9f5e34db222b5f4ae58b093._comment b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_1_c5c3ff25c9f5e34db222b5f4ae58b093._comment
new file mode 100644
index 000000000..13e2a58d2
--- /dev/null
+++ b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_1_c5c3ff25c9f5e34db222b5f4ae58b093._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 1"
+ date="2013-08-23T16:17:58Z"
+ content="""
+I did something similar for my videos, I've created the repo on one machine add the video files then cloned it on the other machine then reinjected the files in to the cloned repo.
+
+http://joeyh.name/blog/entry/moving_my_email_archives_and_packages_to_git-annex/
+"""]]
diff --git a/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_2_ee3ecc86990ac5a8d0c4fdfb482a7594._comment b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_2_ee3ecc86990ac5a8d0c4fdfb482a7594._comment
new file mode 100644
index 000000000..d1e259afd
--- /dev/null
+++ b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_2_ee3ecc86990ac5a8d0c4fdfb482a7594._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 2"
+ date="2013-08-23T18:23:52Z"
+ content="""
+If you need to preserve mtimes, or differentiate between files with identical content but different mtimes, neither git nor git-annex is going to do what you want, since git doesn't care about preserving much file metadata.
+
+As far as importing two sets of files on two computers, the best thing to do is import each, and then let the two sync up. Otherwise, when you're running the assistant it will start downloading the first set you import to the second computer, before the second set is added there, and do extra work. Although once the duplicate files from the second set land in the second git repository, the assistant will avoid any additional redundant transfers.
+
+(The assistant never *moves* files, if both repositories are configured to be in the default client repository group. It only copies.)
+
+I don't understand question #1. \"set2 ended with a lot of symlinks but only in one subfolder\" doesn't make sense to me, or rather I could interpret it to mean any of dozen things (none of which seem likely)
+
+You can `git annex drop` files in direct mode. However, if you're running the assistant, it will try to get them back. You can configure your repository to be in manual mode to prevent the assistant doing that, or not use the assistant, or configure a [[preferred_content]] expression to make the assistant do something more custom like not try to get files located in a \"olddata\" directory.
+"""]]
diff --git a/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_3_e29bf8b848da04c761dc601ac979ac14._comment b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_3_e29bf8b848da04c761dc601ac979ac14._comment
new file mode 100644
index 000000000..d750e9581
--- /dev/null
+++ b/doc/forum/correct_way_to_add_two_preexisting_datasets/comment_3_e29bf8b848da04c761dc601ac979ac14._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmTNrhkVQ26GBLaLD5-zNuEiR8syTj4mI8"
+ nickname="Juan"
+ subject="comment 3"
+ date="2013-08-25T13:00:04Z"
+ content="""
+Thanks. It is very clear now. I think I got it running. I have 2 direct mode copies in my ubuntu box and in the USB drive and one indirect in my ultrabook (small SSD).
+What I meant is that even in direct mode, after sync ended, the set I indexed first ended with the contents of a folder in the .git dir using symlinks. But it might have been a leftover of previous attempts.
+I think I got confused by the great amount of flexibility it provides.
+Thanks.
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment.mdwn b/doc/forum/git-annex___38___ikiwiki_experiment.mdwn
new file mode 100644
index 000000000..5b426a180
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment.mdwn
@@ -0,0 +1,28 @@
+Hi,
+
+I've been experimenting with combining [ikiwiki](http://ikiwiki.info) with git-annex and it seems to work. Thought I'd post my process. I've [commented](http://ikiwiki.info/todo/git-annex_support/discussion/) on the ikiwiki website as well but perhaps it'd be of interest to git-annex folks.
+
+I have very little understanding of any of the tools involved and have just attempted to make it work using my limited knowledge. I don't use the web interface for ikiwiki which simplifies things.
+
+The [website in question](http://stockholm.kalleswork.net) just went online and is currently an archive of architectural photographs and the site relies heavily on the ikiwiki osm and album plugins.
+
+### Setting things up
+
+To start with I set up the wiki on the server and git clone to into `$wrkdir` on my laptop. I then initialize a git-annex repo in the `$srcdir` on the server. Leaving the `$gitdir` untouched. The `$scrdir` git-annex repo has to be in `direct` mode. Before doing any syncing I add `annex-ignore = true` and `annex-sync = false` to `.git/config` in the origin repo (`$gitdir`): this is to prevent polluting `$gitdir` with git-annex data. The same process is repeated in the `$wrkdir` on the laptop.
+
+### Pushing and syncing
+
+With this setup I can then `git add remote $srcdir`, `git add $file` and `git-push` mdwn files and other lightweight data from the laptop. While `git annex-add`, `git-annex sync` and `git-annex copy --to $srcdir` jpg's and other heavy files. All pure git commands work as expected with ikiwiki and the website recompiles etc.
+
+### Snags
+
+I'm frequently left with (non-dangling) symlinks in the `$srcdir` despite the annex repo being in direct mode. When this happens `git-annex fsck` sorts things out.
+
+Uploading image files does require a bit of manual work. But as this is done less frequently it's not much of an issue for me. I'm guessing that by doing things it the correct order (whatever that might be) I could avoid some of the manual work.
+
+The thing to keep in mind is to never `git-add` the typechanged annexed files in the $srcdir. In general I never use git commands in the $srcdir.
+
+The main problem is the symlinks though as they demand a manual `git-annex fsck`. I have no idea what causes the symlinks in a direct mode repo.
+
+Any comments?
+
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_1_9f74449ec91577dbf6095f4beafac293._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_1_9f74449ec91577dbf6095f4beafac293._comment
new file mode 100644
index 000000000..332f77bcc
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_1_9f74449ec91577dbf6095f4beafac293._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="how about the web interface?"
+ date="2013-09-25T11:09:58Z"
+ content="""
+I understand you do not use the web interface - but what if you did? would it commit all those files into git?
+
+Could we add the git-annex files to a .gitignore file?
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_2_e034585c8b51cc30b35c1f7ae68205bf._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_2_e034585c8b51cc30b35c1f7ae68205bf._comment
new file mode 100644
index 000000000..2201813fe
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_2_e034585c8b51cc30b35c1f7ae68205bf._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk3HGoDpnOPob5jOjvIootmkve1-nCpRiI"
+ nickname="Kalle"
+ subject="comment 2"
+ date="2013-09-25T11:58:42Z"
+ content="""
+I have very poor understanding of what ikiwiki actually does behind the scenes including how it uses the $srcdir and $gitdir.
+
+The only way I could see the web interface working would be to use the git-annex content expressions and having the assistant running on the server. That still doesn't prevent large files from being checked into git though? That all depends on which order ikiwiki can be made to do things.
+
+I might be able to test on a local wiki but that would have to wait a while.
+
+
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_3_fbbd47c3dbe8de24b0df664e4afd5cb8._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_3_fbbd47c3dbe8de24b0df664e4afd5cb8._comment
new file mode 100644
index 000000000..63919bd22
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_3_fbbd47c3dbe8de24b0df664e4afd5cb8._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 3"
+ date="2013-09-25T17:03:29Z"
+ content="""
+Interesting experiment.
+
+I don't know why you don't want to let git-annex sync its data to $gitdir.
+
+The symlinks could be occuring because of a bug in direct mode. (I have fixed many past bugs that caused that.) But just as likely it's because ikiwiki will run `git pull` in the srcdir.
+
+I think it would make more sense to use the underlay plugin and keep your annexed repository in a separate underlay. This would guarantee ikiwiki doesn't run git commands in there, and would ensure that nothing done with the web interface could mess with the annex.
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_4_55da5c3c41c13b08590ce1ff8117cef6._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_4_55da5c3c41c13b08590ce1ff8117cef6._comment
new file mode 100644
index 000000000..6299326a8
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_4_55da5c3c41c13b08590ce1ff8117cef6._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk3HGoDpnOPob5jOjvIootmkve1-nCpRiI"
+ nickname="Kalle"
+ subject="comment 4"
+ date="2013-09-25T18:28:40Z"
+ content="""
+@Joey
+
+ > I don't know why you don't want to let git-annex sync its data to $gitdir.
+
+Well neither do I! :) It seemed to be the way to avoid duplicating data while still having the images picked up by the ikiwiki album plugin. Wouldn't the files in the $gitdir end up duplicated in $srcdir?
+
+ > The symlinks could be occuring because of a bug in direct mode.
+ > (I have fixed many past bugs that caused that.) But just as likely
+ > it's because ikiwiki will run git pull in the srcdir.
+
+When you mention it I've had similar problems with my vfat usb annex repos. Using the post-receive merge hook to make files visible for non git-annex devices about town. Nothing I can reliably recreate but I will keep my eye out for bugs.
+
+ > I think it would make more sense to use the underlay plugin and keep
+ > your annexed repository in a separate underlay.
+
+Yep that would be ideal. For my usecase the album plugin is vital and I can't understand how album would pick up and deal with images in an underlay dir. This is a bit OT for this site though most of my questions are ikiwiki related.
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_5_f67823351164ddfe7d595685c3679652._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_5_f67823351164ddfe7d595685c3679652._comment
new file mode 100644
index 000000000..2701bd4af
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_5_f67823351164ddfe7d595685c3679652._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk3HGoDpnOPob5jOjvIootmkve1-nCpRiI"
+ nickname="Kalle"
+ subject="comment 5"
+ date="2013-09-26T06:56:49Z"
+ content="""
+Turns out using the underlay was a piece of cake! Just mirror the folder structure of the repo in your underlaydir put your jpegs there and off you go. Images are picked up by the album plugin and it all just works. No need to coax git-annex into doing odd stuff.
+
+Thought I'd post this for other ikiwikers.
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_6_d5cc91164772849d027fed5f962d9000._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_6_d5cc91164772849d027fed5f962d9000._comment
new file mode 100644
index 000000000..1d3abdf5d
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_6_d5cc91164772849d027fed5f962d9000._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="step by step?"
+ date="2013-09-26T09:40:57Z"
+ content="""
+So how does this actually work in practice? Is the underlay directory a completely disconnected repository?
+
+Can we have step by step instructions on how to set this up?
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_7_cb4ec7ed3c39d0649133191a85ea6ab3._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_7_cb4ec7ed3c39d0649133191a85ea6ab3._comment
new file mode 100644
index 000000000..8e387d89a
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_7_cb4ec7ed3c39d0649133191a85ea6ab3._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk3HGoDpnOPob5jOjvIootmkve1-nCpRiI"
+ nickname="Kalle"
+ subject="comment 7"
+ date="2013-09-26T13:05:53Z"
+ content="""
+@anarcat
+
+ > Can we have step by step instructions on how to set this up?
+
+[I described the ikiwiki album setup](http://ikiwiki.info/forum/ikiwiki_with_album___38___underlay_plugins/) on the ikiwiki website as there are no git-annex tricks anymore. Just standard behaviour.
+
+ > So how does this actually work in practice? Is the underlay directory a
+ > completely disconnected repository?
+
+Yes they are completely separate repos. Really the underlay dir could be managed in any way you like svn, rsync, ftp etc. I didn't expect the album plugin to pick everything up but apparently it does! Perhaps underlays are completely integrated and appear as 'normal' to all of ikiwiki?
+"""]]
diff --git a/doc/forum/git-annex___38___ikiwiki_experiment/comment_8_86565e5e1508ff1862f88975446650a2._comment b/doc/forum/git-annex___38___ikiwiki_experiment/comment_8_86565e5e1508ff1862f88975446650a2._comment
new file mode 100644
index 000000000..473551f65
--- /dev/null
+++ b/doc/forum/git-annex___38___ikiwiki_experiment/comment_8_86565e5e1508ff1862f88975446650a2._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="comment 8"
+ date="2013-09-26T13:10:25Z"
+ content="""
+Yes, I believe that is the way the underlay works - the files are just picked up.
+
+As for the ikiwiki forum post - maybe you should move it to the \"tips\" section? :)
+
+Thanks for the documentation!!
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working.mdwn b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working.mdwn
new file mode 100644
index 000000000..1a00326d7
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working.mdwn
@@ -0,0 +1,12 @@
+I am trying to get git-annex working on Ubuntu, specifically 13.04 and now 13.10 (I thought upgrading to a new distro. would fix the issue).
+
+I have tried:
+
+ * installing via apt-get install git-annex
+ * installing via cabal (full-build)
+
+Both times git-annex install successfully with no errors. I then start the webapp and create a repository (which git-annex creates successfully), I then add the folders and files I want it to sync. Git-annex finds the files and says it has began syncing them, but it never moves past the first batch of files it 'says' it had started syncing. I have waited 5+ hours at one point and nothing has changed. Also, the webapp is incredibly slow, it takes 15+ seconds to perform ANY action (such as saving options or viewing the logs). The issue definitely isn't my computer as I am using an high-end SSD, core i7, DDR3 RAM, etc...
+
+Also the logs produce no errors of any kind and actually show git-annex adding files, most of the log entries say add 'filedirectory/filename.txt' as an example.
+
+I have gotten this to successfully work on Fedora, but Ubuntu (13.04/13.10) is having serious problems.
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_1_209956f3812450a43986d4ca5e647da6._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_1_209956f3812450a43986d4ca5e647da6._comment
new file mode 100644
index 000000000..2c4cbd291
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_1_209956f3812450a43986d4ca5e647da6._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-22T17:57:27Z"
+ content="""
+I don't really understand the problem you're describing. Is the problem with it uploading the files it's added to another remote? Does it sit there saying \"syncing with $remote\" forever? Or what?
+
+As to the webapp speed problem, it seems likely to me this is not related to CPU speed or load. It sounds rather like a DNS timeout problem, or an ipv6 to ipv4 fallback problem. Although since the URL to the webapp is http://127.0.0.1, it can't really be either of those..
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_12a58b8efe545e09b64760c87849839b._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_12a58b8efe545e09b64760c87849839b._comment
new file mode 100644
index 000000000..6e2d780ec
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_12a58b8efe545e09b64760c87849839b._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEeLtIxQCU0qe4q5lbrZp8AcUSUUcRrkg"
+ nickname="Zach"
+ subject="comment 3"
+ date="2013-10-23T02:01:09Z"
+ content="""
+The problem is not with a remote annex. The issue I am having is git-annex never finishes syncing.
+
+Maybe a screenshot will help. http://i.imgur.com/9HSr8bl.png
+
+It never gets passed the Startup scan.
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_e0f7328603256f25c3be3706ecc9c76c._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_e0f7328603256f25c3be3706ecc9c76c._comment
new file mode 100644
index 000000000..413a807ad
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_3_e0f7328603256f25c3be3706ecc9c76c._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 3"
+ date="2013-10-23T15:27:40Z"
+ content="""
+Your screenshot shows git-annex is in the process of adding 6244 files. Depending on the size of those files, it could take some time to read their contents in order to calculate a checksum and add them to the repository. This would not normally take hours, unless your disk is very slow or the files are extremely big.
+
+You might get some useful information if you enable debugging (Configuration -> Preferences -> Enable debug logging) and look at the log.
+
+(This is not \"syncing\" btw. You have not set up any other repository for it to sync data with.)
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_4_6bb8e4522241556fb82784d9b834cbfe._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_4_6bb8e4522241556fb82784d9b834cbfe._comment
new file mode 100644
index 000000000..314d01e89
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_4_6bb8e4522241556fb82784d9b834cbfe._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEeLtIxQCU0qe4q5lbrZp8AcUSUUcRrkg"
+ nickname="Zach"
+ subject="comment 4"
+ date="2013-10-25T20:40:26Z"
+ content="""
+Everything works, it was just taking a while on one the folders; let it run overnight, and it was done.
+
+Thanks for the help!
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_5_89a5296b461d400b51006074a13a4560._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_5_89a5296b461d400b51006074a13a4560._comment
new file mode 100644
index 000000000..e6508fe54
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_5_89a5296b461d400b51006074a13a4560._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 5"
+ date="2013-10-26T15:53:28Z"
+ content="""
+Can you confirm that the files in the directory it was adding were so large that it would normally take hours to checksum them all?
+"""]]
diff --git a/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_6_62daef4b4392c951b914a01b3effac11._comment b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_6_62daef4b4392c951b914a01b3effac11._comment
new file mode 100644
index 000000000..4adcc568f
--- /dev/null
+++ b/doc/forum/git-annex_on_Ubuntu_13.04_and_13.10_not_working/comment_6_62daef4b4392c951b914a01b3effac11._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlEeLtIxQCU0qe4q5lbrZp8AcUSUUcRrkg"
+ nickname="Zach"
+ subject="comment 6"
+ date="2013-10-26T21:05:07Z"
+ content="""
+The folder that took a while is actually only 291.5 MB total, containing 25,977 items in total. I know that is the folder that was having some issues because I committed each folder separately.
+"""]]
diff --git a/doc/forum/git-annex_on_archlinuxarm__44___armv6.mdwn b/doc/forum/git-annex_on_archlinuxarm__44___armv6.mdwn
new file mode 100644
index 000000000..edfd0ad4e
--- /dev/null
+++ b/doc/forum/git-annex_on_archlinuxarm__44___armv6.mdwn
@@ -0,0 +1,20 @@
+Hi!
+
+I can't get git-annex to run on my archlinuxARM sytem. It fails with
+
+ $ git annex test
+ error: git-annex died of signal 11
+
+ Its a RaspberryPi (model B I think) so its an ARM11 (armv6h if I'm not mistaken). I use archlinuxarm because I am familiar with the distribution and you can have a very lean system. There is a very crude package for git-annex arm and armv7 that is build like this: https://github.com/archlinuxarm/PKGBUILDs/blob/master/alarm/git-annex/PKGBUILD . Crude, because it just takes the debian package, changes the version of libraries where apropriate and packs it as archlinux package. Two problems: 1) It's not been tested on armv6. 2) The 4.20130417 version does not exist anymore on the debian mirrors.
+
+1. The debian package is not marked as armv5 or armv7 specific and is runs on the RaspberryPi with Raspbian (but in an pretty old version if I remember correctly). So I would have imagined it runs on armv6h in general.\\
+2. I just did the same magic as in the linked PKGBUILD with a more current version to build the package but it still crashes. Can I get the old version anywhere to check if it works with that?
+
+
+Cheers,
+ Hannes
+
+Background for whoever's interested :)
+I tried to set up a RaspberryPi to manage my files, contacts and calendars. That shouts out loud for owncloud because of its convenience (caldav, carddav, webdav and a nice interface bundled together). However, compared to git-annex owncloud is unbearably slow (on an RaspberryPi) and lacks git-annex's easy way to keep your files sorted even if you don't have them on your local disk.
+
+For these reasons I tried to install a hybrid git-annex/owncloud system. There, basically, the files are served by owncloud but at the same time also managed (and served) by git-annex (+ssh). As far as I can see that should not have any noticeable side effects in my use case (mostly single user). I have some external hard drives connected to the RaspberryPi of which I will just symlink the appropriate folders to the owncloud 'files' folder. This way I can also just take the drives with me and still have the same (UUID) git annex repository on them. Any comments?
diff --git a/doc/forum/git-annex_on_archlinuxarm__44___armv6/comment_1_88fa644df8614c2db0d092b3eb1d3156._comment b/doc/forum/git-annex_on_archlinuxarm__44___armv6/comment_1_88fa644df8614c2db0d092b3eb1d3156._comment
new file mode 100644
index 000000000..516ec0017
--- /dev/null
+++ b/doc/forum/git-annex_on_archlinuxarm__44___armv6/comment_1_88fa644df8614c2db0d092b3eb1d3156._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T16:56:50Z"
+ content="""
+You seem to be trying to take a binary built for one distribution with one CPU architecture and use it on another distribution on another CPU architecture. It's not very susprising that this does not work.
+
+Compiling git-annex from source for your particular architecture and distribution should not be difficult.
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram.mdwn b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram.mdwn
new file mode 100644
index 000000000..82ca06b85
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram.mdwn
@@ -0,0 +1,24 @@
+Hi all,
+
+git-annex basically renders my repository unmanageble. What is the
+best and save (!) way to recover?
+
+Here is my situation:
+
+I have a fairly large repository with ~8000 managed files taking about
+65GB of disk space.
+
+git-annex worked well there. But some programs choke on the
+symlinks. So, I converted the repository to direct mode. The
+transition worked well.
+
+Now git status reports a type change for the ~8000 files.
+
+But as soon as I run
+
+ git commit -m "typechange" even-only-one-of-the-files
+
+the process `git-annex pre-commit .` eats 3.5GB of ram, where I
+usually kill it, as I only have 4GB of ram....
+
+-- Andreas
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_1_ff16c7932b60b85c744bafc48bb040e4._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_1_ff16c7932b60b85c744bafc48bb040e4._comment
new file mode 100644
index 000000000..23e5e79e8
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_1_ff16c7932b60b85c744bafc48bb040e4._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 1"
+ date="2013-09-18T07:19:49Z"
+ content="""
+AFAIK in direct mode you are not supposed to commit you just run
+
+ git annex sync
+
+and it will commit if files are changed. you only add new files annexed files are handled by sync
+
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_2_5599cddf579d18f70cab6e48d04ae99d._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_2_5599cddf579d18f70cab6e48d04ae99d._comment
new file mode 100644
index 000000000..337c1627f
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_2_5599cddf579d18f70cab6e48d04ae99d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 2"
+ date="2013-09-18T12:27:38Z"
+ content="""
+Hi Hamza,
+
+thanks for that comment. I thought `git annex sync` is just a wrapper around `git commit -a` (among others).
+
+Using `git annex sync` does not help, as it just means that now `git annex sync` eats all my memory until swapping starts.
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_3_412941e9385f63153b23695641e71deb._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_3_412941e9385f63153b23695641e71deb._comment
new file mode 100644
index 000000000..6349500ca
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_3_412941e9385f63153b23695641e71deb._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 3"
+ date="2013-09-19T18:49:05Z"
+ content="""
+git-annex sync is a wrapper around git commit. But not -a! git commit -a will stage every one of your large files directly into the git repository, wasting much memory and worse, disk space. It is ok to use `git commit` or `git commit --staged` in direct mode after eg `git annex add`. But not `git commit -a` or `git commit even-only-one-of-the-files`. It's best to just use `git annex sync` rather than `git commit`, as it avoids finger memory causing you to run the wrong type of commit command. Please see [[direct_mode]] for the details.
+
+I was able to make pre-commit take a lot of memory by committing a 1 gb file directly to git. git-annex was buffering the whole file content in memory
+due to not thinking to check first if it was a symlink. I have fixed that bug.
+
+So I think you must have run that command you showed, and you now have a lot of data stored in your git repository that you had meant git-annex to handle. You might need to use git-filter-branch to remove it..
+
+This kind of thing is why I need to write the [[todo/direct_mode_guard]].
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_4_112ad140d9006c530db2121bec24de30._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_4_112ad140d9006c530db2121bec24de30._comment
new file mode 100644
index 000000000..e5ebfa328
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_4_112ad140d9006c530db2121bec24de30._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 4"
+ date="2013-09-19T20:06:39Z"
+ content="""
+Let me ask a simple question: All files are regular files (no symlinks). If I can live with loosing the history, is it save to just remove the .git directory and start over? Or do I risk anything?
+
+PS: .git is about 7GB
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_5_9178023b95683a649355f291165a1467._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_5_9178023b95683a649355f291165a1467._comment
new file mode 100644
index 000000000..7f5047ddd
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_5_9178023b95683a649355f291165a1467._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 5"
+ date="2013-09-19T20:57:18Z"
+ content="""
+You can safely delete the git repository in the situation you describe. Better yet: Tar it up, and check the tarball into git-annex with the other files when you start over. :) Then if I'm wrong, you still have that data.
+"""]]
diff --git a/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_6_9251203421c1c3c3aed7828c4b97ecb8._comment b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_6_9251203421c1c3c3aed7828c4b97ecb8._comment
new file mode 100644
index 000000000..ebb378e95
--- /dev/null
+++ b/doc/forum/git-annex_pre-commit_eats_all_my_4GB_of_ram/comment_6_9251203421c1c3c3aed7828c4b97ecb8._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 6"
+ date="2013-09-19T22:27:38Z"
+ content="""
+Thanks a bunch! That is what I did now. Seems good.
+
+May I additionally suggest a change in the man page of git annex? There I read
+
+ sync [remote ...]
+ ...
+ The sync process involves first committing all local changes (git commit -a), ...
+ ...
+
+which made me think, I could do `git commit -a` manually as well.
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files.mdwn b/doc/forum/git-annex_unused_not_dropping_deleted_files.mdwn
new file mode 100644
index 000000000..1669461bc
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files.mdwn
@@ -0,0 +1,34 @@
+I've been organizing my music collection deleted/replaces some files but git-annex unused does not show any unused files even though they are deleted and all repos are in sync.
+
+
+ git log --stat --all -S'SHA256E-s8034842--5c3475d7fef6f0c3545721f34e7cbfb6727a00708bdde192f0f1d53af251b444'
+ commit a0fecdc02f7564f8bce9726f6b934fefc11de58b
+ Date: Thu Sep 12 17:04:53 2013 +0300
+
+ Deleted
+
+ .../Dido - Sitting On the Roof of the World.mp3 | 1 -
+ 1 file changed, 1 deletion(-)
+
+ commit 7f216228fc0e6298f0290ee1d8646bc9b16eca10
+ Date: Mon Aug 5 03:49:55 2013 +0200
+
+ Initial Import
+
+ .../Dido - Sitting On the Roof of the World.mp3 | 1 +
+ 1 file changed, 1 insertion(+)`
+
+even though the file is deleted its still present in annex objects,
+
+ find .git -name '*5c3475d7fef6f0c3545721f34e7cbfb6727a00708bdde192f0f1d53af251b444*' -exec ls -al '{}' \;
+ total 7856
+ dr-xr-xr-x 2 user user 4096 Sep 9 01:24 .
+ drwxrwxr-x 3 user user 4096 Sep 9 01:24 ..
+ -r--r--r-- 1 user user 8034842 Aug 5 04:52 SHA256E-s8034842--5c3475d7fef6f0c3545721f34e7cbfb6727a00708bdde192f0f1d53af251b444.mp3
+ -r--r--r-- 1 user user 8034842 Aug 5 04:52 .git/annex/objects/Jz/74/SHA256E-s8034842--5c3475d7fef6f0c3545721f34e7cbfb6727a00708bdde192f0f1d53af251b444.mp3/SHA256E-s8034842--5c3475d7fef6f0c3545721f34e7cbfb6727a00708bdde192f0f1d53af251b444.mp3
+
+I got around 200 files that should be deleted but not showing up in unused. I though maybe one of the dead repos is causing the problem so i did a,
+
+ git annex forget --drop-dead
+
+and synced all repos. Still I can not get them to drop.
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_1_2152cfb09675e46e7492e198dd3ea094._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_1_2152cfb09675e46e7492e198dd3ea094._comment
new file mode 100644
index 000000000..72ed0bbe1
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_1_2152cfb09675e46e7492e198dd3ea094._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 1"
+ date="2013-09-13T15:34:03Z"
+ content="""
+The most likely explanation is that you have a branch in git that still contains the deleted file, which will prevent unused from removing it. Try `git branch -a` to see all branches (a tag could also do it).
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_2_97e666dbac9de2a5e688921cba8a42e9._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_2_97e666dbac9de2a5e688921cba8a42e9._comment
new file mode 100644
index 000000000..134106482
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_2_97e666dbac9de2a5e688921cba8a42e9._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 2"
+ date="2013-09-13T15:59:29Z"
+ content="""
+I did not create tags or branches, running returns,
+
+ git branch -a
+
+ git-annex
+ * master
+ synced/git-annex
+ synced/master
+ remotes/origin/HEAD -> origin/master
+ remotes/origin/git-annex
+ remotes/origin/master
+ remotes/origin/synced/master
+
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_3_d7b0e9515bface28f3650b8aa20ec2f4._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_3_d7b0e9515bface28f3650b8aa20ec2f4._comment
new file mode 100644
index 000000000..666172b28
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_3_d7b0e9515bface28f3650b8aa20ec2f4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 3"
+ date="2013-09-13T16:17:39Z"
+ content="""
+Depending on your git configuration, `git annex sync` might not be updating certian of these branches, such as remotes/origin/HEAD. You can check the branches out and see which still contains your deleted files.
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_4_5816f6cab42e27e724e735368f693b09._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_4_5816f6cab42e27e724e735368f693b09._comment
new file mode 100644
index 000000000..e1a503d23
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_4_5816f6cab42e27e724e735368f693b09._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 4"
+ date="2013-09-13T17:57:38Z"
+ content="""
+Which one of those branches I can safely delete? this is a central repo all other clients drop their stuff here it does not have any remotes (I did clones it from a client then removed origin section from config.)
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_5_8e97f39225515f0bf8b168dfd6a0efab._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_5_8e97f39225515f0bf8b168dfd6a0efab._comment
new file mode 100644
index 000000000..1da1f80db
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_5_8e97f39225515f0bf8b168dfd6a0efab._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 5"
+ date="2013-09-13T18:23:02Z"
+ content="""
+So this is a bare repository?
+
+It seems to have had an origin at one point; see the remotes/origin/* branches. If it no longer has that remote, then of course those branches will not be getting updated, and so will contain the old files and that's why unused won't find them. In that case, you could safely remove the remotes/origin/* branches.
+"""]]
diff --git a/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_6_bef37f8ec9c337387b79ffd6d56fe425._comment b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_6_bef37f8ec9c337387b79ffd6d56fe425._comment
new file mode 100644
index 000000000..fe1c94eca
--- /dev/null
+++ b/doc/forum/git-annex_unused_not_dropping_deleted_files/comment_6_bef37f8ec9c337387b79ffd6d56fe425._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/FHnTlSBo1eCGJRwueeKeB6.RCaPbGMPr5jxx8A--#ce0d8"
+ nickname="Hamza"
+ subject="comment 6"
+ date="2013-09-13T18:41:30Z"
+ content="""
+It is a non bare repo, I am using the following setup,
+
+http://git-annex.branchable.com/forum/Annex_dropping_files/
+"""]]
diff --git a/doc/forum/git-status_typechange_in_direct_mode.mdwn b/doc/forum/git-status_typechange_in_direct_mode.mdwn
new file mode 100644
index 000000000..6438fb890
--- /dev/null
+++ b/doc/forum/git-status_typechange_in_direct_mode.mdwn
@@ -0,0 +1,48 @@
+Hi all,
+
+how can I get rid of all those 'typechange' messages in `git status`
+when in direct mode?
+
+Here is an example session:
+
+ > git init
+ Initialized empty Git repository in /some/path/.git/
+ > git config user.name dtrn
+ > git config user.email drn@drn.com
+ > git annex init
+ init ok
+ (Recording state in git...)
+ > git annex direct
+ commit
+ # On branch master
+ #
+ # Initial commit
+ #
+ nothing to commit (create/copy files and use "git add" to track)
+ ok
+ direct ok
+ > dd if=/dev/zero of=testfile.bin count=1000
+ 1000+0 records in
+ 1000+0 records out
+ 512000 bytes (512 kB) copied, 0.00317424 s, 161 MB/s
+ > git annex add testfile.bin
+ add testfile.bin (checksum...) ok
+ (Recording state in git...)
+ > git commit -m "annexed testfile.bin"
+ ok
+ [master (root-commit) 281e740] annexed testfile.bin
+ 1 file changed, 1 insertion(+)
+ create mode 120000 testfile.bin
+ > git status
+ # On branch master
+ # Changes not staged for commit:
+ # (use "git add <file>..." to update what will be committed)
+ # (use "git checkout -- <file>..." to discard changes in working directory)
+ #
+ # typechange: testfile.bin
+ #
+ no changes added to commit (use "git add" and/or "git commit -a")
+
+
+Regards,
+Andreas
diff --git a/doc/forum/git-status_typechange_in_direct_mode/comment_1_12c8b67aadbfa2b073e12997a55d49a7._comment b/doc/forum/git-status_typechange_in_direct_mode/comment_1_12c8b67aadbfa2b073e12997a55d49a7._comment
new file mode 100644
index 000000000..31e476087
--- /dev/null
+++ b/doc/forum/git-status_typechange_in_direct_mode/comment_1_12c8b67aadbfa2b073e12997a55d49a7._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 1"
+ date="2013-09-20T15:24:25Z"
+ content="""
+These messages are normal in direct mode.
+
+They happen because git status does not know about git-annex's direct mode. So it sees a file that has a symlink checked into git, but a normal file in place in the working tree. Thus, its type has changed. Short of hacking or wrapping git, or switching to indirect mode ;), there's not much that can be done about this.
+
+You might want to read [[direct_mode]] for more about this, and some of the problems it can cause when running certian git commands.
+"""]]
diff --git a/doc/forum/git-status_typechange_in_direct_mode/comment_2_005d1b17f3c2ae192aa30c6e5163989e._comment b/doc/forum/git-status_typechange_in_direct_mode/comment_2_005d1b17f3c2ae192aa30c6e5163989e._comment
new file mode 100644
index 000000000..c598b212f
--- /dev/null
+++ b/doc/forum/git-status_typechange_in_direct_mode/comment_2_005d1b17f3c2ae192aa30c6e5163989e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 2"
+ date="2013-09-20T20:16:47Z"
+ content="""
+Thanks for the info and the quick reply.
+"""]]
diff --git a/doc/forum/git_annex_assistant__44___share_with_other_devices.mdwn b/doc/forum/git_annex_assistant__44___share_with_other_devices.mdwn
index 85e8438ad..faebb14a1 100644
--- a/doc/forum/git_annex_assistant__44___share_with_other_devices.mdwn
+++ b/doc/forum/git_annex_assistant__44___share_with_other_devices.mdwn
@@ -1 +1,3 @@
I am trying to share files between my PC at home at that at work using the walkthrough here: http://git-annex.branchable.com/assistant/remote_sharing_walkthrough/. However, I don't have the option on my machine to "Share with other devices". Any ideas why this would be missing? I am using Ubuntu 13.04 if that helps.
+
+Update: it now works after a software update, I guess I just had an older version of git-annex. Now, I have version 4.20130723.
diff --git a/doc/forum/git_annex_sync_dies___40__sometimes__41__.mdwn b/doc/forum/git_annex_sync_dies___40__sometimes__41__.mdwn
new file mode 100644
index 000000000..84f9d1125
--- /dev/null
+++ b/doc/forum/git_annex_sync_dies___40__sometimes__41__.mdwn
@@ -0,0 +1,22 @@
+I've set up git annex on my laptop and on a remote server using the gitolite v3 git-annex branch.
+When I 'git annex sync' from my laptop (mac OSX) to the server, and 'git annex copy . --to server' all works fine.
+
+Later, I tried to clone the repository on another machine (linux 2.6.32). again all is well. I 'git annex init' in the new clone and then try to 'git annex sync' -- now I run into problems.
+
+Specifically, the first request for the configlist (when I do 'git annex --debug sync' all is fine until the configlist request) somehow breaks and my ssh session shows:
+
+muxserver_listen bind(): Input/output error
+
+This seems to confuse the client, who now believes that git annex is not installed on the server (it is).
+
+If I issue the same command as git annex via ssh, all seems to work ok with the caveats below:
+
+I have a feeling it's related to the -o 'ControlPersist=yes' argument that git-annex appears to be giving ssh. If I include this option when I run via ssh, ssh dies:
+
+>ssh git@server -o "ControlMaster=auto" -o "ControlPersist=yes" "git-annex-shell 'configlist' '/~/PRJ'"
+command-line: line 0: Bad configuration option: ControlPersist
+
+
+(note that it appears to be ok to leave "ControlMaster=auto" in).
+
+any thoughts?
diff --git a/doc/forum/git_annex_sync_dies___40__sometimes__41__/comment_1_48bbac0545bf13bbf04da723e418d037._comment b/doc/forum/git_annex_sync_dies___40__sometimes__41__/comment_1_48bbac0545bf13bbf04da723e418d037._comment
new file mode 100644
index 000000000..9445421a4
--- /dev/null
+++ b/doc/forum/git_annex_sync_dies___40__sometimes__41__/comment_1_48bbac0545bf13bbf04da723e418d037._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-15T18:16:23Z"
+ content="""
+Since this seems to be a problem with ssh connection caching, you can disable that:
+
+git config annex.sshcaching false
+
+Seems like the problem would be in the version of ssh you have installed on your linux client. Or possibly some interaction between its version and the server's version.
+
+Since linux 2.6.32 is quite old, I'll bet you have an old ssh too.. what version?
+"""]]
diff --git a/doc/forum/git_annex_test_on_windows.mdwn b/doc/forum/git_annex_test_on_windows.mdwn
new file mode 100644
index 000000000..4e2f8dea6
--- /dev/null
+++ b/doc/forum/git_annex_test_on_windows.mdwn
@@ -0,0 +1,5 @@
+is it worth sharing back git annex test failures occourring on some windows setup ?
+i'm having 3 failures, what kind of report can i produce shall it be of any use ?
+is it enough a test log coming from git annex test > test.log 2>&1 ?
+thanks again
+
diff --git a/doc/forum/howto_update_feed.mdwn b/doc/forum/howto_update_feed.mdwn
new file mode 100644
index 000000000..5323e92eb
--- /dev/null
+++ b/doc/forum/howto_update_feed.mdwn
@@ -0,0 +1,14 @@
+I am using the importfeed [1] functionality.
+
+How am I supposed to update the feed/feeds?
+
+I understand that running
+
+ cd annex; git annex importfeed http://url/to/podcast
+
+a second time will 'do the right thing'. But that is cumbersome as I have to know the url again. Is there sth like git annex updatefeeds?
+
+
+
+
+[1] http://joeyh.name/blog/entry/git-annex_as_a_podcatcher/
diff --git a/doc/forum/howto_update_feed/comment_1_bec356619f370a618f19a187d09d2e35._comment b/doc/forum/howto_update_feed/comment_1_bec356619f370a618f19a187d09d2e35._comment
new file mode 100644
index 000000000..fa87e3494
--- /dev/null
+++ b/doc/forum/howto_update_feed/comment_1_bec356619f370a618f19a187d09d2e35._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-26T18:11:07Z"
+ content="""
+I have purposefully kept a list of feeds out of git-annex. I handle this by having a `feeds` file, which I check into git. Then a cron job runs: `xargs git-annex importfeed < feeds`
+"""]]
diff --git a/doc/forum/howto_update_feed/comment_2_84dfb80ba3db8d41164eb97022becae3._comment b/doc/forum/howto_update_feed/comment_2_84dfb80ba3db8d41164eb97022becae3._comment
new file mode 100644
index 000000000..4f28d8f4e
--- /dev/null
+++ b/doc/forum/howto_update_feed/comment_2_84dfb80ba3db8d41164eb97022becae3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 2"
+ date="2013-08-26T19:04:21Z"
+ content="""
+Thanks for that. I'll do the same ;-)
+"""]]
diff --git a/doc/forum/howto_update_feed/comment_3_20166db298c10074e062aecad59ffd71._comment b/doc/forum/howto_update_feed/comment_3_20166db298c10074e062aecad59ffd71._comment
new file mode 100644
index 000000000..73f48ac9b
--- /dev/null
+++ b/doc/forum/howto_update_feed/comment_3_20166db298c10074e062aecad59ffd71._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="203.45.2.230"
+ subject="comment 3"
+ date="2013-08-28T01:32:38Z"
+ content="""
+One thing I do slightly differently is put comments in my ```feeds``` file so I know what feed is what...
+
+ # NPR - Wait Wait... Don't Tell Me!
+ http://www.npr.org/rss/podcast.php?id=35
+ # NPR - Car Talk
+ http://www.npr.org/rss/podcast.php?id=510208
+
+
+Then I use
+
+ grep -v '^#' feeds| xargs git-annex importfeed --relaxed
+
+I reckon that makes maintenance easier.
+"""]]
diff --git a/doc/forum/howto_update_feed/comment_4_f040e31b763fc9a7aa092442b4d6b8e8._comment b/doc/forum/howto_update_feed/comment_4_f040e31b763fc9a7aa092442b4d6b8e8._comment
new file mode 100644
index 000000000..f7a35d1b6
--- /dev/null
+++ b/doc/forum/howto_update_feed/comment_4_f040e31b763fc9a7aa092442b4d6b8e8._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 4"
+ date="2013-09-01T18:06:51Z"
+ content="""
+Yet another solution, keeping it all in one script
+
+ #!/bin/sh
+
+ while IFS= read line
+ do
+ test -n \"${line%%#*}\" && echo git annex importfeed --relaxed \"$line\"
+ done <<EOF
+ # FooCast - Alice & Bob
+ http://feeds.foo.com/foocast
+ # FrobCast
+ http://meep.moop.com/feed
+ EOF
+"""]]
diff --git a/doc/forum/known_and_local_annex_keys.mdwn b/doc/forum/known_and_local_annex_keys.mdwn
new file mode 100644
index 000000000..7dcef8693
--- /dev/null
+++ b/doc/forum/known_and_local_annex_keys.mdwn
@@ -0,0 +1,14 @@
+I have a direct repository with the assistant running (v4.20131002). The repo is in the backup group and should be grabbing every known annex file. Yet `git annex status` says:
+
+ local annex keys: 1386
+ local annex size: 94.53 gigabytes
+ known annex keys: 1387
+ known annex size: 94.53 gigabytes
+
+As you can seem there is one more known annex key than there are local ones. Neither `git annex get` nor `git annex sync` changes the numbers. According to `tree` the repo dir contains exactly 1387 files, which means that the missing file must exist on disk.
+
+1) How do I find out which is the file in question? How do I get it synchronized?
+
+Yesterday there were 1376 known annex keys. Today there are 1387. For some reason the number of keys went up by 11, and I would like to know how and why. The log suggests that a couple of files have been added from inside the repo directory, but I am positive that these files already existed in the annex directory yesterday, and that I ran `git annex sync` manually without the number of local and/or known keys going up.
+
+2) Why weren't the files synced before? Is there a way to find out whether they were or were not part of the annex yesterday - maybe list all files sorted by the date they were added?
diff --git a/doc/forum/known_and_local_annex_keys/comment_1_3cb4828dc7116e4cf49e119f055ae9a3._comment b/doc/forum/known_and_local_annex_keys/comment_1_3cb4828dc7116e4cf49e119f055ae9a3._comment
new file mode 100644
index 000000000..24a5ef03e
--- /dev/null
+++ b/doc/forum/known_and_local_annex_keys/comment_1_3cb4828dc7116e4cf49e119f055ae9a3._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-28T16:56:20Z"
+ content="""
+I think you're stressing way too much about a number.
+
+It's quite possible for the known and local key counts to diverge while no data is missing. For example:
+
+<pre>
+joey@darkstar:~/tmp/test>touch foo
+joey@darkstar:~/tmp/test>touch bar
+joey@darkstar:~/tmp/test>git annex add foo bar
+
+local annex keys: 1
+known annex keys: 2
+</pre>
+
+"""]]
diff --git a/doc/forum/known_and_local_annex_keys/comment_2_68f20c881eafe986694bde10571cf1c0._comment b/doc/forum/known_and_local_annex_keys/comment_2_68f20c881eafe986694bde10571cf1c0._comment
new file mode 100644
index 000000000..944ec9caf
--- /dev/null
+++ b/doc/forum/known_and_local_annex_keys/comment_2_68f20c881eafe986694bde10571cf1c0._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="77.247.181.165"
+ subject="comment 2"
+ date="2013-10-28T18:31:21Z"
+ content="""
+I don't think I'm stressing too much. Rather, I'm inquiring about why git-annex is giving me wrong (or at least unclear) output that makes me worry about losing data. I plan to trust git-annex with a lot of important files, and in order to do that I want to make sure it's trustworthy. And that's where the inaccurate key numbers get in the way.
+
+So why do the local and known numbers diverge anyway? Would you consider adjusting the status output to be more accurate, or at least less confusing? I just want to be able to check that every single file in the repo is being backed up.
+"""]]
diff --git a/doc/forum/known_and_local_annex_keys/comment_3_e195a7091a06ce0427bb28aca9a17d04._comment b/doc/forum/known_and_local_annex_keys/comment_3_e195a7091a06ce0427bb28aca9a17d04._comment
new file mode 100644
index 000000000..fd9228b4f
--- /dev/null
+++ b/doc/forum/known_and_local_annex_keys/comment_3_e195a7091a06ce0427bb28aca9a17d04._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-10-28T19:06:00Z"
+ content="""
+I have adjusted the labels to be more clear.
+"""]]
diff --git a/doc/forum/known_and_local_annex_keys/comment_4_d81f0bf7465832cb676fd89f5d53ec18._comment b/doc/forum/known_and_local_annex_keys/comment_4_d81f0bf7465832cb676fd89f5d53ec18._comment
new file mode 100644
index 000000000..fccc576d3
--- /dev/null
+++ b/doc/forum/known_and_local_annex_keys/comment_4_d81f0bf7465832cb676fd89f5d53ec18._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="77.247.181.165"
+ subject="comment 4"
+ date="2013-10-28T19:24:12Z"
+ content="""
+Thanks, I'll check it out. And if you ever got around to introduce a means that can answer the above-mentioned integrity questions, that'd be really awesome.
+"""]]
diff --git a/doc/forum/lost_in_walkthrough....txt b/doc/forum/lost_in_walkthrough....txt
new file mode 100644
index 000000000..89f4af026
--- /dev/null
+++ b/doc/forum/lost_in_walkthrough....txt
@@ -0,0 +1,78 @@
+I'm trying to follow the steps of the "walkthrough" but I'm experiencing the following issue: when
+I sync one repository and do "git annex get ." I don't get the files from the other repository.
+Here is the transcript of the steps I followed - I've put them in a script (ga.sh) so I can replay
+them and show them on the shell while executing.
+Basically I have two repositories, "/tmp/a/annex" and "/tmp/b/annex", the second cloned from
+the first. All the other steps are the same as in the walkthrough.
+-----------------------------------
+> bash -x ga.sh
++ cd /tmp
++ mkdir a
++ mkdir b
++ cd a
++ mkdir annex
++ cd annex
++ git init
+Initialized empty Git repository in /tmp/a/annex/.git/
++ git annex init a
+init a ok
+(Recording state in git...)
++ cd /tmp/b
++ git clone /tmp/a/annex
+Cloning into 'annex'...
+done.
+warning: remote HEAD refers to nonexistent ref, unable to checkout.
+
++ cd annex
++ git annex init b
+init b ok
+(Recording state in git...)
++ git remote add a /tmp/a/annex
++ cd /tmp/a/annex
++ git remote add b /tmp/b/annex
++ dd if=/dev/urandom of=first bs=1024 count=1
+1+0 records in
+1+0 records out
+1024 bytes (1.0 kB) copied, 9.9167e-05 s, 10.3 MB/s
++ dd if=/dev/urandom of=second bs=1024 count=1
+1+0 records in
+1+0 records out
+1024 bytes (1.0 kB) copied, 0.000241635 s, 4.2 MB/s
++ git annex add .
+add first (checksum...) ok
+add second (checksum...) ok
+(Recording state in git...)
++ git commit -am added
+[master (root-commit) 5078564] added
+ 2 files changed, 2 insertions(+)
+ create mode 120000 first
+ create mode 120000 second
++ git mv first e
++ mkdir x
++ git mv second x
++ git commit -m moved
+fix x/second ok
+(Recording state in git...)
+[master 422492d] moved
+ 3 files changed, 1 insertion(+), 1 deletion(-)
+ rename first => e (100%)
+ delete mode 120000 second
+ create mode 120000 x/second
++ cd /tmp/b/annex
++ git annex sync a
+(merging origin/git-annex into git-annex...)
+(Recording state in git...)
+commit
+ok
+git-annex: no branch is checked out
++ git annex get .
+-------------------
+
+The last "git annex get ." does not retrieve the files in /tmp/a/annex ... why?
+I guess the issue starts when cloning /tmp/a/annex where no commit was done.
+
+Emanuele
+
+PS: I'm using git v1.7.9.5 (ubuntu 12.04) and the latest git-annex static binary
+downloaded a few minutes ago from the git-annex website.
+
diff --git a/doc/forum/lost_in_walkthrough.../comment_1_51b703b961ca762f0359e1c169f1ee75._comment b/doc/forum/lost_in_walkthrough.../comment_1_51b703b961ca762f0359e1c169f1ee75._comment
new file mode 100644
index 000000000..a5c574b4a
--- /dev/null
+++ b/doc/forum/lost_in_walkthrough.../comment_1_51b703b961ca762f0359e1c169f1ee75._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-02T19:32:50Z"
+ content="""
+I have fixed `git annex sync` to work even when run in a repository with no master branch.
+"""]]
diff --git a/doc/forum/lost_in_walkthrough.../comment_2_a9de0401a103bdd4401ba2d5983dc54a._comment b/doc/forum/lost_in_walkthrough.../comment_2_a9de0401a103bdd4401ba2d5983dc54a._comment
new file mode 100644
index 000000000..4a8110eb4
--- /dev/null
+++ b/doc/forum/lost_in_walkthrough.../comment_2_a9de0401a103bdd4401ba2d5983dc54a._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn2MI-Ci-bS9W5NITngsBJiL8LqWYcJ458"
+ nickname="Emanuele"
+ subject="comment 2"
+ date="2013-11-02T23:36:54Z"
+ content="""
+Great thanks! I'm glad my feedback helped improve git-annex!
+
+<https://github.com/joeyh/git-annex/commit/bc18cde32589cf53080c399e81b5680e4b>af6cef
+
+"""]]
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.txt
new file mode 100644
index 000000000..9de5779c1
--- /dev/null
+++ b/doc/forum/manual_update_of_.git__47__annex__47__objects.txt
@@ -0,0 +1,8 @@
+Let's suppose that I've manually modified files in .git/annex/objects,
+for example I ran an rsync or some other file synchronization software
+to copy files. As a result, some objects have disappeared, others have
+appeared. After that `git annex whereis .' displays stale information,
+it doesn't take the manual modifications to accound. `git annex fsck'
+seems to fix this, but it runs the rehashing of all new files, so it's
+slow. Is there a fast alternative, which notices all the object file
+changes, trusts them, and just updates .git/annex/index quickly?
diff --git a/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_1_ea6ec91150c8962e2711631f2422bf3a._comment b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_1_ea6ec91150c8962e2711631f2422bf3a._comment
new file mode 100644
index 000000000..f721e21a5
--- /dev/null
+++ b/doc/forum/manual_update_of_.git__47__annex__47__objects/comment_1_ea6ec91150c8962e2711631f2422bf3a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.51"
+ subject="comment 1"
+ date="2013-09-12T17:11:41Z"
+ content="""
+I do not recommend manually messing with the contents of .git/annex/objects. It is a good way to lose data.
+
+If you look at the documentation for fsck in git-annex's man page, you will find the answer to your question.
+"""]]
diff --git a/doc/forum/many_remotes.mdwn b/doc/forum/many_remotes.mdwn
new file mode 100644
index 000000000..4e463cb3c
--- /dev/null
+++ b/doc/forum/many_remotes.mdwn
@@ -0,0 +1,24 @@
+Thanks Joey for the great work.
+
+I'm using git annex for my tv-shows and movies Folder.
+
+I have 3 USB HDD (ext.150Gb,ext.200Gb, ext.2Tb) and a USB Stick (ATV), which are traveling between 3 Devices
+
+2 Notebooks (Lappi,Kiste) and a Nas.
+
+First of all, I'm made a mistake and mixed the remote Locations from the tvshows folder with the movies folder and did a git annex sync, ( this happened about two weeks ago)
+I think i can't undo this, only unannex will help.
+
+I've now watched the annex status output and noticed that there are many Remotes, some of them have a timestamp as name.
+
+see log file at http://pastebin.com/79bRVkK6
+
+Running git annex on ubuntu 12.04
+
+ christian@Lappi:~/Serien$ git annex version
+ git-annex version: 4.20130417
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP DNS
diff --git a/doc/forum/nfs_mounted_repo_results_in_errors_on_drop__47__move.mdwn b/doc/forum/nfs_mounted_repo_results_in_errors_on_drop__47__move.mdwn
deleted file mode 100644
index bf84f75c0..000000000
--- a/doc/forum/nfs_mounted_repo_results_in_errors_on_drop__47__move.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-Bug reports should be posted in [[bugs]], not in the forum. I have moved
-this misplaced bug report to
-[[bugs/nfs_mounted_repo_results_in_errors_on_drop_move]].
---[[Joey]]
diff --git a/doc/forum/nntp__47__usenet_special_remote/comment_2_48736ed17c98ffcfb13ec00b901b2dd6._comment b/doc/forum/nntp__47__usenet_special_remote/comment_2_48736ed17c98ffcfb13ec00b901b2dd6._comment
new file mode 100644
index 000000000..90b264f7b
--- /dev/null
+++ b/doc/forum/nntp__47__usenet_special_remote/comment_2_48736ed17c98ffcfb13ec00b901b2dd6._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 2"
+ date="2013-09-11T07:46:07Z"
+ content="""
+Only played a tiny bit with this since the initial post.
+
+I've decided that sql backend should be dropped entirely. Mostly the SQL backend was there because the code does something else entirely, and this was just a test.
+
+But since there has been no interest it will probably take ages before i actually get this finished :)
+
+"""]]
diff --git a/doc/forum/non-bare_repo_on_cloud_remote/comment_2_71baea93f6caaf7b81a9ac00bee91e5e._comment b/doc/forum/non-bare_repo_on_cloud_remote/comment_2_71baea93f6caaf7b81a9ac00bee91e5e._comment
new file mode 100644
index 000000000..145c57120
--- /dev/null
+++ b/doc/forum/non-bare_repo_on_cloud_remote/comment_2_71baea93f6caaf7b81a9ac00bee91e5e._comment
@@ -0,0 +1,67 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawniayrgSdVLUc3c6bf93VbO-_HT4hzxmyo"
+ nickname="Tobias"
+ subject="comment 2"
+ date="2013-08-08T19:05:07Z"
+ content="""
+Seems that I don't get it... Here is what I did:
+
+First, I create a new repo with the assistant on `user@laptop ~/temp/annex-test`, then:
+
+ user@laptop ~/temp/annex-test % echo test1 > test1
+ user@laptop ~/temp/annex-test % echo test2 > test2
+
+ user@server ~/tmp % mkdir annex-test
+ user@server ~/tmp % cd annex-test
+ user@server ~/tmp/annex-test % git init
+ Initialized empty Git repository in /home/tobru/tmp/annex-test/.git/
+ user@server ~/tmp/annex-test % git annex init
+ init ok
+ (Recording state in git...)
+ user@server ~/tmp/annex-test % mv .git/hooks/post-update.sample .git/hooks/post-update
+ user@server ~/tmp/annex-test % cat .git/hooks/post-update
+ #!/bin/sh
+ #
+ # An example hook script to prepare a packed repository for use over
+ # dumb transports.
+ #
+ # To enable this hook, rename this file to \"post-update\".
+
+ exec git update-server-info
+ user@server ~/tmp/annex-test % chmod +x .git/hooks/post-update
+ user@server ~/tmp/annex-test % echo '#!/bin/sh\ngit annex merge' > .git/hooks/post-receive
+ user@server ~/tmp/annex-test % chmod +x .git/hooks/post-receive
+
+ user@laptop ~/temp/annex-test % git remote add server ssh://user@server/home/tobru/tmp/annex-test
+ user@laptop ~/temp/annex-test % git annex assistant --stop
+ user@laptop ~/temp/annex-test % git annex sync
+ commit
+ ok
+ pull server
+ warning: no common commits
+ remote: Counting objects: 5, done.
+ remote: Compressing objects: 100% (3/3), done.
+ remote: Total 5 (delta 1), reused 0 (delta 0)
+ Unpacking objects: 100% (5/5), done.
+ From ssh://server.tobru.local/home/tobru/tmp/annex-test
+ * [new branch] git-annex -> server/git-annex
+ ok
+ (merging server/git-annex into git-annex...)
+ (Recording state in git...)
+ push server
+ Counting objects: 27, done.
+ Delta compression using up to 4 threads.
+ Compressing objects: 100% (20/20), done.
+ Writing objects: 100% (25/25), 2.36 KiB, done.
+ Total 25 (delta 2), reused 0 (delta 0)
+ remote: merge git-annex (merging synced/git-annex into git-annex...)
+ remote: ok
+ To ssh://tobru@server.tobru.local/home/tobru/tmp/annex-test
+ * [new branch] git-annex -> synced/git-annex
+ * [new branch] master -> synced/master
+ ok
+ user@laptop ~/temp/annex-test % git annex assistant
+
+Now I expect the files `test1` and `test2` to be at `user@server ~/tmp/annex-test`. But they are not displayed.
+What am I doing wrong? The main thing I wan't to achieve: Push the files from `laptop` to `server` without adding `laptop` as remote on the server.
+"""]]
diff --git a/doc/forum/preferred_content.mdwn b/doc/forum/preferred_content.mdwn
new file mode 100644
index 000000000..b4c215328
--- /dev/null
+++ b/doc/forum/preferred_content.mdwn
@@ -0,0 +1,11 @@
+Hello all,
+
+I'm trying to use "preferred content" with git-annex but I suspect that my version doesn't provide it.
+
+I'm using Debian "wheezy" that packs git-annex 3.20120629.
+
+I appreciate any help you can give.
+
+Thanks.
+
+Zaka.
diff --git a/doc/forum/preferred_content/comment_1_9c9e5f2ee5ae4d8459358ad16f879ef1._comment b/doc/forum/preferred_content/comment_1_9c9e5f2ee5ae4d8459358ad16f879ef1._comment
new file mode 100644
index 000000000..24de5840b
--- /dev/null
+++ b/doc/forum/preferred_content/comment_1_9c9e5f2ee5ae4d8459358ad16f879ef1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-07T18:38:22Z"
+ content="""
+The first version of git-annex to support preferred content settings was 3.20121009.
+
+There is a quite up-to-date backport available for Debian stable.
+"""]]
diff --git a/doc/forum/purge_files_with_no_copies.mdwn b/doc/forum/purge_files_with_no_copies.mdwn
new file mode 100644
index 000000000..5761d9290
--- /dev/null
+++ b/doc/forum/purge_files_with_no_copies.mdwn
@@ -0,0 +1,3 @@
+Hi guys, as a result of some improper handling I am left with a couple of files with no copies scattered all around my repos. Now, while my data loss is unfortunate, it is not tragic. What I would like to do now is to purge all of these files without having to look for them one by one. Is there any easy way to do this?
+
+Cheers
diff --git a/doc/forum/purge_files_with_no_copies/comment_1_12b578689eb8d5d38c06261ec65e2109._comment b/doc/forum/purge_files_with_no_copies/comment_1_12b578689eb8d5d38c06261ec65e2109._comment
new file mode 100644
index 000000000..0ea81ecfe
--- /dev/null
+++ b/doc/forum/purge_files_with_no_copies/comment_1_12b578689eb8d5d38c06261ec65e2109._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 1"
+ date="2013-09-19T20:59:32Z"
+ content="""
+This will output all files in your repository that git-annex thinks have no copies left:
+
+`git annex find --not --copies=1`
+
+Piping it to git rm is left as an excercise for the reader..
+"""]]
diff --git a/doc/forum/receiving_indirect_renames_on_direct_repo___63__.mdwn b/doc/forum/receiving_indirect_renames_on_direct_repo___63__.mdwn
new file mode 100644
index 000000000..51a3aa7b6
--- /dev/null
+++ b/doc/forum/receiving_indirect_renames_on_direct_repo___63__.mdwn
@@ -0,0 +1,254 @@
+I've been playing with a mixed setup, and I frequentely end up with conflicts which can be ascribed to mixing direct windows repos with indirect linux one(s), and making renames on the indirect ones.
+Possibly someone can address what I miss of the git-annex/git interaction.
+
+#### versions involved ####
+
+linux: git-annex version: 4.20131024
+win: git-annex version: 4.20131024-gca7b71e
+
+### Steps to reproduce behaviour ###
+
+###### 1. On linux, i setup bare origin "casa" and client repo "local":
+
+ [michele@home ~]$ git init --bare casa
+ Initialized empty Git repository in /home/sambahome/michele/casa/
+ [michele@home ~]$ cd casa
+ [michele@home casa]$ git annex init casa
+ init casa ok
+ (Recording state in git...)
+ [michele@home ~]$ cd ..; git clone casa local
+ Cloning into 'local'...
+ done.
+ warning: remote HEAD refers to nonexistent ref, unable to checkout.
+ [michele@home ~]$ cd local; git annex init local
+ init local ok
+ (Recording state in git...)
+ [michele@home local]$ echo lintest > lintest
+ [michele@home local]$ git annex add lintest
+ add lintest (checksum...) ok
+ (Recording state in git...)
+ [michele@home local]$ git annex sync
+ (merging origin/git-annex into git-annex...)
+ (Recording state in git...)
+ commit
+ ok
+ pull origin
+ ok
+ push origin
+ Counting objects: 18, done.
+ Delta compression using up to 4 threads.
+ Compressing objects: 100% (12/12), done.
+ Writing objects: 100% (16/16), 1.48 KiB | 0 bytes/s, done.
+ Total 16 (delta 1), reused 0 (delta 0)
+ To /home/sambahome/michele/casa
+ * [new branch] git-annex -> synced/git-annex
+ * [new branch] master -> synced/master
+ ok
+ ```
+
+###### 2. On windows I clone origin, and I sync empty
+
+ ```cmd
+ M:\>git clone ssh://michele@home/home/michele/casa win
+ Cloning into 'win'...
+ remote: Counting objects: 20, done.
+ remote: Compressing objects: 100% (15/15), done.
+ remote: Total 20 (delta 3), reused 0 (delta 0)
+ Receiving objects: 100% (20/20), done.
+ Resolving deltas: 100% (3/3), done.
+ M:\>cd win
+ M:\win>git annex status
+ Detected a crippled filesystem.
+ Enabling direct mode.
+ Detected a filesystem without fifo support.
+ Disabling ssh connection caching.
+ repository mode: direct
+ trusted repositories: (merging origin/git-annex origin/synced/git-annex into git-annex...)
+ (Recording state in git...)
+ 0
+ semitrusted repositories: 4
+ 00000000-0000-0000-0000-000000000001 -- web
+ 598ecfac-087d-49a3-b48d-beafd0d71805 -- origin (casa)
+ b2699c17-d0bc-40a0-b447-a64ad109b2a2 -- here (ALICUDI:M:\win)
+ bd4166eb-296b-4f0f-a3be-6c25e4c7cbb0 -- local
+ untrusted repositories: 0
+ transfers in progress: none
+ available local disk space: unknown
+ local annex keys: 0
+ local annex size: 0 bytes
+ known annex keys: 1
+ known annex size: 8 bytes
+ bloom filter size: 16 mebibytes (0% full)
+ backend usage:
+ SHA256E: 1
+ ```
+
+###### 3. I copy content from local to win
+
+ ```bash
+ [michele@home local]$ git annex copy --to origin lintest
+ copy lintest (to origin...) ok
+ (Recording state in git...)
+ [michele@home local]$ git annex sync
+ ...runs ok...
+ ```
+
+###### 4. and
+
+ ```cmd
+ M:\win>git annex sync
+ ...works
+ M:\win>git annex get .
+ ...works
+ M:\win>cat lintest
+ lintest
+ ```
+
+so far so good.
+###### 5. Now the renaming part (performed on linux indirect repo)
+
+ ```bash
+ [michele@home local]$ git mv lintest renamed
+ [michele@home local]$ git annex list
+ here
+ |origin
+ ||web
+ |||
+ XX_ renamed
+ [michele@home local]$ git annex sync
+ ...works
+ ```
+
+###### 6. now, by issuing sync on windows I start getting a "push issue":
+
+ ```
+ M:\win>git annex sync
+ commit
+ ok
+ pull origin
+ remote: Counting objects: 3, done.
+ remote: Total 2 (delta 0), reused 0 (delta 0)
+ Unpacking objects: 100% (2/2), done.
+ From ssh://home/home/michele/casa
+ c3b7a63..a0854bf master -> origin/master
+ c3b7a63..a0854bf synced/master -> origin/synced/master
+ ok
+ push origin
+ Counting objects: 9, done.
+ Delta compression using up to 2 threads.
+ Compressing objects: 100% (4/4), done.
+ Writing objects: 100% (5/5), 484 bytes, done.
+ Total 5 (delta 1), reused 0 (delta 0)
+ To ssh://michele@home/home/michele/casa
+ 6c18669..8cc74a0 git-annex -> synced/git-annex
+ ! [rejected] master -> synced/master (non-fast-forward)
+ error: failed to push some refs to 'ssh://michele@home/home/michele/casa'
+ hint: Updates were rejected because a pushed branch tip is behind its remote
+ hint: counterpart. Check out this branch and merge the remote changes
+ hint: (e.g. 'git pull') before pushing again.
+ hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+ failed
+ git-annex: sync: 1 failed
+
+ M:\win>
+ ```
+
+at this stage I tried to issue a git annex merge, git annex sync, leading to same result.
+
+somewhere in the forum I read i could try issuing a git pull origin master (this could be the problem).
+and the result is as such:
+
+ ```
+ M:\win>git pull master
+ fatal: 'master' does not appear to be a git repository
+ fatal: The remote end hung up unexpectedly
+
+ M:\win>git pull origin master
+ From ssh://home/home/michele/casa
+ * branch master -> FETCH_HEAD
+ Updating c3b7a63..a0854bf
+ error: Your local changes to the following files would be overwritten by merge:
+ lintest
+ Please, commit your changes or stash them before you can merge.
+ Aborting
+
+ M:\win>git status
+ # On branch master
+ # Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
+ #
+ # Changes not staged for commit:
+ # (use "git add <file>..." to update what will be committed)
+ # (use "git checkout -- <file>..." to discard changes in working directory)
+ #
+ # modified: lintest
+ #
+ no changes added to commit (use "git add" and/or "git commit -a")
+
+ M:\win>cat lintest
+ lintest
+ ```
+
+well, ok it appears modified for some weirdness (crlf?), we can live with it.
+
+ ```
+ M:\win>git checkout -->> this replaces files contents with simlink (due to git pull above?)
+ ```
+
+at this stage content is lost, and annex has no knowledge about it.
+
+ ```
+ M:\win>git annex fsck
+ fsck lintest ok
+
+ M:\win>cat lintest
+ .git/annex/objects/9Z/82/SHA256E-s8--2b721dbe9afe6031cce3004e909dd62e0b4b2f3944438b6a000dffc7ad657715/SHA256E-s8--2b721dbe9afe6031cce3004e90
+ M:\win>git annex list
+ here
+ |origin
+ ||web
+ |||
+ XX_ lintest
+ ```
+
+still I cannot sync, but now i can pull origin master:
+
+ ```cmd
+ M:\win>git pull origin master From ssh://home/home/michele/casa * branch master -> FETCH_HEAD Updating c3b7a63..a0854bf Fast-forward lintest => renamed | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lintest => renamed (100%)
+ ```
+
+this doesnt restore content (annex thinks its already there:
+
+ ```
+ M:\win>cat renamed
+ .git/annex/objects/9Z/82/SHA256E-s8--2b721dbe9afe6031cce3004e909dd62e0b4b2f3944438b6a000dffc7ad657715/SHA256E-s8--2b721dbe9afe6031cce3004e909dd62e0b4b2f3944438b6a000dffc7ad657715
+ ```
+
+I think my mistake is the use of the ```git checkout``` in direct mode. But why is the file detected as modified in the first place ?
+
+note: as long as i didn't drop on origin, i still can recover contents by 'forcing' a content refresh:
+
+ ```
+ M:\win>git annex get renamed --from origin
+ get renamed (from origin...)
+ SHA256E-s8--2b721dbe9afe6031cce3004e909dd62e0b4b2f3944438b6a000dffc7ad657715
+ 8 100% 7.81kB/s 0:00:00 (xfer#1, to-check=0/1)
+
+ sent 30 bytes received 153 bytes 8.13 bytes/sec
+ total size is 8 speedup is 0.04
+ ok
+ (Recording state in git...)
+
+ M:\win>cat renamed
+ .git/annex/objects/9Z/82/SHA256E-s8--2b721dbe9afe6031cce3004e909dd62e0b4b2f3944438b6a000dffc7ad657715/SHA256E-s8--2b721dbe9afe6031cce3004e909d
+ M:\win>git annex fsck
+ fsck renamed (fixing direct mode) (checksum...) ok
+
+ M:\win>cat renamed
+ lintest
+```
+
+
+
+
+
+
diff --git a/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_1_f4b0a14373c75cb752597c832e296bcc._comment b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_1_f4b0a14373c75cb752597c832e296bcc._comment
new file mode 100644
index 000000000..7b38c6af4
--- /dev/null
+++ b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_1_f4b0a14373c75cb752597c832e296bcc._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-26T19:35:46Z"
+ content="""
+You should **never, ever, ever** run `git pull`, or `git checkout` inside a direct repository. You need to read [[direct_mode]]. If you do not fully understand it, you should avoid running any git commands that are not `git annex foo` in a direct mode repository. If you forget and do run such git commands, you can generally recover by running `git annex fsck`, although it's possible that the git command you run overwrites your only copy of a file, and so you'd lose it.
+
+<pre>
+To ssh://michele@home/home/michele/casa
+ 6c18669..8cc74a0 git-annex -> synced/git-annex
+ ! [rejected] master -> synced/master (non-fast-forward)
+error: failed to push some refs to 'ssh://michele@home/home/michele/casa'
+</pre>
+
+I'll bet that if you look at the `git config` of this repository it failed to push to, you'll find that it has `receive.denyNonFastforwards` set to true. If you unset that, the push should work.
+"""]]
diff --git a/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_2_8c86dfc99f0b9040402c9d746decda53._comment b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_2_8c86dfc99f0b9040402c9d746decda53._comment
new file mode 100644
index 000000000..8b4ff46a4
--- /dev/null
+++ b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_2_8c86dfc99f0b9040402c9d746decda53._comment
@@ -0,0 +1,41 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkJafmCf-sg9_OM0pynFYM3AO4WCgJiaMI"
+ nickname="Michele"
+ subject="still cannot push when remote has renames"
+ date="2013-10-27T23:06:03Z"
+ content="""
+now, I went again through docs, and i realized how stupid was issuing a git pull on a direct repo. thanks for your patience.
+
+but, i double checked the configuration, I assume \"receive.denyNonFastForwards\" is false by default, but anyway I set it up explicitely so that now my git config (on the linux indirect repo - with respect to my previous example, I got rid of the \"extra\" bare repo in the middle) shows:
+
+ $ git config --list
+ user.email=m@g.com
+ user.name=michele
+ core.repositoryformatversion=0
+ core.filemode=true
+ core.bare=false
+ core.logallrefupdates=true
+ annex.uuid=d084e0fd-95a7-4c98-a206-fbf2c85b779d
+ annex.version=3
+ receive.denynonfastforwards=false
+
+still I am receiving the push refusal:
+
+ M:\win>git annex sync
+ commit
+ ok
+ pull origin
+ ok
+ push origin
+ To ssh://michele@home/home/michele/casa
+ ! [rejected] master -> synced/master (non-fast-forward)
+ error: failed to push some refs to 'ssh://michele@home/home/michele/casa'
+ hint: Updates were rejected because a pushed branch tip is behind its remote
+ hint: counterpart. Check out this branch and merge the remote changes
+ hint: (e.g. 'git pull') before pushing again.
+ hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+ failed
+ git-annex: sync: 1 failed
+
+Same happens with a bare repository in the middle. BTW: the windows \"client\" repository is behind NAT, so that the linux indirect doesn't actively sync against it: could that be source of the problem ?
+"""]]
diff --git a/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_3_0246fff6c7c75f6be45bd257ec3872a5._comment b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_3_0246fff6c7c75f6be45bd257ec3872a5._comment
new file mode 100644
index 000000000..0ffb2a097
--- /dev/null
+++ b/doc/forum/receiving_indirect_renames_on_direct_repo___63__/comment_3_0246fff6c7c75f6be45bd257ec3872a5._comment
@@ -0,0 +1,75 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkJafmCf-sg9_OM0pynFYM3AO4WCgJiaMI"
+ nickname="Michele"
+ subject="possible explanation"
+ date="2013-10-29T11:56:21Z"
+ content="""
+now, i tried to understand what happens. Instead of issuing the *git annex sync*, I relied on *git pull origin, git merge origin/master*, (I red [[http://git-annex.branchable.com/forum/Help_Windows_walkthrough/]] and I assume that pull origin / merge origin/master would work similarly to the \"download\" part of sync, *except for losing all my direct content*) just to understand what was going on, with a clarifying result:
+
+while git annex sync fails on push, git pull origin fails on pull:
+
+ M:\win>git pull origin
+ Updating 5408d6f..c566a69
+ error: Your local changes to the following files would be overwritten by merge:
+ myfile
+ Please, commit your changes or stash them before you can merge.
+ Aborting
+
+note that the file has not been modified locally (just got it through git annex get).
+issuing a git diff, reveals:
+
+ M:\win>git diff myfile
+ diff --git a/myfile b/myfile
+ index beaf3e8..dc5b4ff 120000
+ --- a/myfile
+ +++ b/myfile
+ @@ -1 +1 @@
+ -.git/annex/objects/z5/v7/SHA256E-s8--6090923ed0931dcc6699f32fb66fa4ba32c10924088b12c66fb4ce35a91ba98c/SHA256E-s8\ No newline at end of file
+ +linux.1
+ (END)
+
+ok, i follow suggestion, and I perform a git stash. that still wouldn't suffice for git annex sync:
+
+ M:\win>git annex sync
+ commit
+ ok
+ pull origin
+ ok
+ push origin
+ To ssh://michele@home/home/michele/homebase
+ ! [rejected] master -> synced/master (non-fast-forward)
+ error: failed to push some refs to 'ssh://michele@home/home/michele/homebase'
+ hint: Updates were rejected because a pushed branch tip is behind its remote
+ hint: counterpart. Check out this branch and merge the remote changes
+ hint: (e.g. 'git pull') before pushing again.
+ hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+ failed
+ git-annex: sync: 1 failed
+
+now, i can perform instead a *git pull origin*, since I am confident my content is stashed.
+
+ M:\win>git pull origin
+ Updating 5408d6f..c566a69
+ Fast-forward
+ myfile => myfile.renamed | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+ rename myfile => myfile.renamed (100%)
+
+merge is not doing anything more: at this stage content has gone (file is a direct-mode symlink nad it cannot be fixed by fsck).
+But i can recover it from stash (and I must do it unless I want to get the annex to think i still have content).
+
+ git stash apply
+
+voilà: the content is there! and the repos seems in good order.
+this only adds up that this is possibily a bug in the fact that git reports direct content as modified when indeed it hasn't been modified: but this affects git annex sync only when merging renaming files.
+git annex sync now works perfectly .
+
+to sum it up, I have two questions:
+
+1) does using stash to circumvent the problem expose me to any risk ?
+2) would the behaviour on receiving renames in the abovementioned situation worth to be signaled as a bug ?
+
+
+
+
+"""]]
diff --git a/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote.mdwn b/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote.mdwn
new file mode 100644
index 000000000..2c437fe35
--- /dev/null
+++ b/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote.mdwn
@@ -0,0 +1,8 @@
+Hi,
+
+I switched distribution and cloned my annex from the backup afterwards. getting the files from my backup worked fine, but i have a remote on an external disk and git-annex keeps saying it's unavailable despite it being there. I have the same username and hostname as on my old system so and the remote repo still has the uuid 3d661c5e-c84e-4902-b52e-decbafadfa4f. The only thing that changed is the path, it's know mounted unter /var/run/media/phaer/95... but a symlinked to the path below did not help. Any suggestions?
+
+ 3d661c5e-c84e-4902-b52e-decbafadfa4f -- phaer@kassiopeia:/media/phaer/9502bc14-b83e-471a-95a8-80ff9072a4ab/annex
+
+
+and thank you for this amazing piece of software.
diff --git a/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote/comment_1_c1962d757dd22f49e774afa13a9862ca._comment b/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote/comment_1_c1962d757dd22f49e774afa13a9862ca._comment
new file mode 100644
index 000000000..1223b2414
--- /dev/null
+++ b/doc/forum/reinstalled_os__44___cloned_annex__44___does_not_recognize_remote/comment_1_c1962d757dd22f49e774afa13a9862ca._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-21T22:24:35Z"
+ content="""
+It might help if you pasted the actual error message that git-annex shows when you try to use this remote. Along with the part of .git/config that configures this remote.
+
+In general, git-annex does not are if you've reinstalled your OS, moved things around, etc. As long as the git remote's path points to a repository, git-annex will see it and be able to use it.
+"""]]
diff --git a/doc/forum/safely_dropping_git-annex_history/comment_11_383882fafd32f25ed22b5eb2fb3691b9._comment b/doc/forum/safely_dropping_git-annex_history/comment_11_383882fafd32f25ed22b5eb2fb3691b9._comment
new file mode 100644
index 000000000..fbfe64156
--- /dev/null
+++ b/doc/forum/safely_dropping_git-annex_history/comment_11_383882fafd32f25ed22b5eb2fb3691b9._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
+ nickname="Michael"
+ subject="propagating squashed history to other remotes"
+ date="2013-08-12T01:44:59Z"
+ content="""
+The easiest method seems to be to force-push git-annex and master to other remotes, e.g.
+
+ git push -f myremote git-annex:refs/heads/git-annex
+
+Before doing this, make sure location logs etc had a chance to propagate across all remotes.
+
+It's a good idea to remove synched/ branches before doing git-annex sync on the repos with rewritten history, too:
+ git branch -D synced/master
+ git branch -D synced/annex
+
+
+"""]]
diff --git a/doc/forum/safely_dropping_git-annex_history/comment_12_47794a2abf29bf4ea2763ff89d872ab4._comment b/doc/forum/safely_dropping_git-annex_history/comment_12_47794a2abf29bf4ea2763ff89d872ab4._comment
new file mode 100644
index 000000000..5c0931604
--- /dev/null
+++ b/doc/forum/safely_dropping_git-annex_history/comment_12_47794a2abf29bf4ea2763ff89d872ab4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4830:1600:187::2"
+ subject="comment 12"
+ date="2013-09-04T06:38:00Z"
+ content="""
+`git annex forget` automates this now, without needing to force-push or have a flag day. Needs a version of git-annex supporting it installed on *all* the computers you use the repo on. Repos notice they need to forget when git annex is run in them, and do, automatically.
+"""]]
diff --git a/doc/forum/speed_up_assistant_startup_on_large_repositories.mdwn b/doc/forum/speed_up_assistant_startup_on_large_repositories.mdwn
new file mode 100644
index 000000000..e43476c7b
--- /dev/null
+++ b/doc/forum/speed_up_assistant_startup_on_large_repositories.mdwn
@@ -0,0 +1 @@
+Starting the assistant on a repository with a huge amount of files (f.e. `annexed files in working tree: 22087`) takes a very long time. Is there a way to speed it up? F.e. just checking the file stamps and comparing them with the last assistant run time? Checking if the files are modified could be done with the regular repository check. Thoughts?
diff --git a/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_1_5ba637a0f6d01ba24fe25e6265134e0a._comment b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_1_5ba637a0f6d01ba24fe25e6265134e0a._comment
new file mode 100644
index 000000000..0abe4dec8
--- /dev/null
+++ b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_1_5ba637a0f6d01ba24fe25e6265134e0a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-05T16:43:26Z"
+ content="""
+Checking the time stamps is what it does.
+
+How long is a very long time?
+"""]]
diff --git a/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_2_d65746697977f8971a4b59f5b413f926._comment b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_2_d65746697977f8971a4b59f5b413f926._comment
new file mode 100644
index 000000000..e6915d232
--- /dev/null
+++ b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_2_d65746697977f8971a4b59f5b413f926._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawne_amN4fko4p5cRY_9EYwaYuJKNn7LRio"
+ nickname="Tobias"
+ subject="measuring how-to"
+ date="2013-11-08T16:55:58Z"
+ content="""
+How can I measure how much time the startup scan takes? I tried to find it out using the debug log, but couldn't find any usable notice when the startup scan was finished. Maybe this two lines?
+
+ [...]
+ [2013-11-08 16:00:45 CET] Watcher: Performing startup scan
+ [...]
+ [2013-11-08 16:15:30 CET] Watcher: watching
+"""]]
diff --git a/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_3_be6c4fe5a0c745688438b716973791cc._comment b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_3_be6c4fe5a0c745688438b716973791cc._comment
new file mode 100644
index 000000000..5a6f0e5d0
--- /dev/null
+++ b/doc/forum/speed_up_assistant_startup_on_large_repositories/comment_3_be6c4fe5a0c745688438b716973791cc._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="108.236.230.124"
+ subject="comment 3"
+ date="2013-11-08T17:04:23Z"
+ content="""
+That's right.
+
+15 minutes is certianly a very long time.
+
+Is this on a slow spinning disk? USB disk?
+"""]]
diff --git a/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__.mdwn b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__.mdwn
new file mode 100644
index 000000000..06b58f973
--- /dev/null
+++ b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__.mdwn
@@ -0,0 +1,3 @@
+Hi,
+
+I own a computer that I use as a home server. I'm just getting started with git-annex, and I was trying to add an ssh remote. It connected fine, but only gave me the "encrypted rsync" option. I'd like to be able to access these files on the server as well, but the "use a git repository" option didn't show up. How do I enable this?
diff --git a/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_1_7244794579a191a677190c60758f32e7._comment b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_1_7244794579a191a677190c60758f32e7._comment
new file mode 100644
index 000000000..14e51e79a
--- /dev/null
+++ b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_1_7244794579a191a677190c60758f32e7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmR-xG9O2HWoybxYZPVbYVYxwitfcfDgtE"
+ nickname="Charles"
+ subject="comment 1"
+ date="2013-09-09T00:29:14Z"
+ content="""
+Oh actually, I just clicked the available option and it gave me a \"connection refused\" due to my using a port other than 22. I edited the .ssh/config, but it decided to use 22 anyway?
+"""]]
diff --git a/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_2_277cf12907bd7c5930eb4f137b115e29._comment b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_2_277cf12907bd7c5930eb4f137b115e29._comment
new file mode 100644
index 000000000..55f50b3f5
--- /dev/null
+++ b/doc/forum/ssh_remote_-_no___34__use_a_git_repository__34___option_during_setup__63__/comment_2_277cf12907bd7c5930eb4f137b115e29._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmR-xG9O2HWoybxYZPVbYVYxwitfcfDgtE"
+ nickname="Charles"
+ subject="comment 2"
+ date="2013-09-09T14:50:42Z"
+ content="""
+Never mind, I simply didn't have git-annex installed on the other computer. I'm going to make a thread in bugs about assistant always assuming port 22, you can delete this thread.
+"""]]
diff --git a/doc/forum/start_assistant_from_command_line.mdwn b/doc/forum/start_assistant_from_command_line.mdwn
new file mode 100644
index 000000000..3f48dd6d3
--- /dev/null
+++ b/doc/forum/start_assistant_from_command_line.mdwn
@@ -0,0 +1,11 @@
+I wanted to try out this probably great piece of software you wrote, alas I do not use a Debian distro with managed software menus (i.e. I use OpenBox), so I cannot simply open the assistant through my programs-menu. In fact, to do that I'd need the command to start the assistant so I can add it manually myself. Sadly, the man page did not gave me any advices... :(
+
+Any chance to give me the terminal command to start the assistant?
+
+***
+edit: just to update the thread: everythings okay now. Thanks for this great program!
+
+the commands (as posted by Paul):
+
+ git annex assistant
+ git annex webapp
diff --git a/doc/forum/start_assistant_from_command_line/comment_1_f8dfce1fca9f1212ccaf84e431db71a9._comment b/doc/forum/start_assistant_from_command_line/comment_1_f8dfce1fca9f1212ccaf84e431db71a9._comment
new file mode 100644
index 000000000..dc35d61bc
--- /dev/null
+++ b/doc/forum/start_assistant_from_command_line/comment_1_f8dfce1fca9f1212ccaf84e431db71a9._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmBhQgaA5QrFwT67-Bo0qPIx0HD9roDrso"
+ nickname="Paul"
+ subject="comment 1"
+ date="2013-10-21T19:20:28Z"
+ content="""
+ git annex assitant
+
+starts the assitant itself, you propably want the gui which you start by
+
+ git annex webapp
+"""]]
diff --git a/doc/forum/start_assistant_from_command_line/comment_2_e769c5d09afbff85961363ddc5eb4019._comment b/doc/forum/start_assistant_from_command_line/comment_2_e769c5d09afbff85961363ddc5eb4019._comment
new file mode 100644
index 000000000..b970990d4
--- /dev/null
+++ b/doc/forum/start_assistant_from_command_line/comment_2_e769c5d09afbff85961363ddc5eb4019._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkj7tMEJKcZpNXIFkHAAcNi5qJFSFyjn6o"
+ nickname="thissideup"
+ subject="comment 2"
+ date="2013-10-22T11:05:13Z"
+ content="""
+ah okay. That was what I was trying to do, but git-annex failed on my. Remembering that I was on Debian and checking the version (which was June 2012) - I supposed that I wasn't able to use the assistant yet.
+
+So now I am trying to compile from source using cabal, however I sadly ran into a roadblock: http://git-annex.branchable.com/forum/cabal_install_fails_on_uuid/
+"""]]
diff --git a/doc/forum/taskwarrior.mdwn b/doc/forum/taskwarrior.mdwn
new file mode 100644
index 000000000..3e44cc610
--- /dev/null
+++ b/doc/forum/taskwarrior.mdwn
@@ -0,0 +1,11 @@
+I try to sync my taskWarrior files .task/*.data with git-annex ... but there is two problem :
+
+- i need to chmod 755 my files because taskWarrior doesn't recognize them, or say "problem with permission"
+
+- taskwarrior seems crazy with symbolic link used by git-annex, undo not work, task appear multiple times , etc.
+
+Is there any solution ?
+Any user experienced the same problem?
+
+Thanks
+Sr.
diff --git a/doc/forum/taskwarrior/comment_1_1c3a29e7d292cb602d9d349f8009b51e._comment b/doc/forum/taskwarrior/comment_1_1c3a29e7d292cb602d9d349f8009b51e._comment
new file mode 100644
index 000000000..c8682b378
--- /dev/null
+++ b/doc/forum/taskwarrior/comment_1_1c3a29e7d292cb602d9d349f8009b51e._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 1"
+ date="2013-08-06T12:44:11Z"
+ content="""
+* You could try metastore (not merge friendly), git-cache-meta (pretty minimal) or metamonger (not done yet) to sync your file permissions
+* Look into direct mode to avoid symlinks
+* Alternatively, check your taskwarrior files into git, not git-annex, to avoid symlinks
+"""]]
diff --git a/doc/forum/ui/comment_2_b493ee97eb2378e72c12f3d137109580._comment b/doc/forum/ui/comment_2_b493ee97eb2378e72c12f3d137109580._comment
new file mode 100644
index 000000000..ee7995883
--- /dev/null
+++ b/doc/forum/ui/comment_2_b493ee97eb2378e72c12f3d137109580._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://mylesenglish.myopenid.com/"
+ ip="217.39.94.195"
+ subject="comment 2"
+ date="2013-09-16T19:21:31Z"
+ content="""
+This shell function behaves more like ls and shows the files that are present:
+
+ ga-ls () {
+ CWD=`pwd`
+ cd ${1:-.} && git annex find | cut -d / -f 1 | uniq
+ cd ${CWD}
+ }
+
+"""]]
diff --git a/doc/forum/unknown_response_from_git_cat-file.mdwn b/doc/forum/unknown_response_from_git_cat-file.mdwn
new file mode 100644
index 000000000..e4c559815
--- /dev/null
+++ b/doc/forum/unknown_response_from_git_cat-file.mdwn
@@ -0,0 +1,8 @@
+Hi,
+
+when running git annex add in my direct mode repository, since a few days ago I only get:
+
+$ git annex add
+git-annex: unknown response from git cat-file (":./Archiv/Someone missing",:./Archiv/Someone Like You Cover-fCvjvEGkTu4.flv)
+
+The :./Archiv/Someone missing part strikes me odd because it so much looks like broken shell meta-character escaping in git-annex, but I doubt that because it stopped working just suddenly.
diff --git a/doc/forum/unknown_response_from_git_cat-file/comment_1_f26ba569e715fe69b6de3093930362ee._comment b/doc/forum/unknown_response_from_git_cat-file/comment_1_f26ba569e715fe69b6de3093930362ee._comment
new file mode 100644
index 000000000..0ddef17af
--- /dev/null
+++ b/doc/forum/unknown_response_from_git_cat-file/comment_1_f26ba569e715fe69b6de3093930362ee._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:34:18Z"
+ content="""
+This is a bug in the 1.8.4 pre-release version of git. It will be fixed in the 1.8.4 release or another pre-release. git-annex version 4.20130802 has a workaround for this problem.
+"""]]
diff --git a/doc/forum/unlock__47__lock_always_gets_me/comment_2_f89b4349dde840c355a3bc28908decdf._comment b/doc/forum/unlock__47__lock_always_gets_me/comment_2_f89b4349dde840c355a3bc28908decdf._comment
new file mode 100644
index 000000000..f732c87da
--- /dev/null
+++ b/doc/forum/unlock__47__lock_always_gets_me/comment_2_f89b4349dde840c355a3bc28908decdf._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnRai_qFYPVvEgC6i1nlM1bh-C__jbhqS0"
+ nickname="Matthew"
+ subject="comment 2"
+ date="2013-09-07T12:26:46Z"
+ content="""
+I too was totally flummoxed by this.
+"""]]
diff --git a/doc/forum/webapp___47___assistant_without_watch.mdwn b/doc/forum/webapp___47___assistant_without_watch.mdwn
new file mode 100644
index 000000000..9bb1fcf1a
--- /dev/null
+++ b/doc/forum/webapp___47___assistant_without_watch.mdwn
@@ -0,0 +1,9 @@
+I did not recieve feedback on my comment [1], so I try to post my question again but more clearly.
+
+Is it possible to run the assistent/the webapp without the functionality of 'git annex watch'?
+
+I'd like to use the assistant and to have the automatic syncing but I do not want the local repository to be watched. Instead I prefer to manually add/drop my files.
+
+I do not see the 'pause button' mentioned in my earlier question [1].
+
+[1] http://git-annex.branchable.com/forum/webapp_and_manual_mode/
diff --git a/doc/forum/webapp___47___assistant_without_watch/comment_1_1bcd99aa81f937ded683e19a69d33dd9._comment b/doc/forum/webapp___47___assistant_without_watch/comment_1_1bcd99aa81f937ded683e19a69d33dd9._comment
new file mode 100644
index 000000000..c76128ae3
--- /dev/null
+++ b/doc/forum/webapp___47___assistant_without_watch/comment_1_1bcd99aa81f937ded683e19a69d33dd9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-26T18:14:17Z"
+ content="""
+The assistant is currently only able to transfer files that it has added itself. So if you disable syncing, you have to manually upload any files you add.
+
+I doubt that I will change this in the assistant, because supporting this use case would complicate it unnecessarily for a use case that is not what it's designed to do. It's more likely that `git annex sync` will get an option to also transfer file contents.
+"""]]
diff --git a/doc/forum/webapp___47___assistant_without_watch/comment_2_9f5b3f5bf7fedcd5baec519d97d3aa8c._comment b/doc/forum/webapp___47___assistant_without_watch/comment_2_9f5b3f5bf7fedcd5baec519d97d3aa8c._comment
new file mode 100644
index 000000000..a44155876
--- /dev/null
+++ b/doc/forum/webapp___47___assistant_without_watch/comment_2_9f5b3f5bf7fedcd5baec519d97d3aa8c._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="ringprince"
+ ip="134.76.140.110"
+ subject="comment 2"
+ date="2013-08-26T18:54:40Z"
+ content="""
+Thanks for the clarification.
+
+Although
+
+* not what I hoped for ;-)
+* I don't see that it would get complicated
+* I do not consider my use case special
+
+Anyway, thanks for this great piece of software.
+"""]]
diff --git a/doc/git-annex-shell.mdwn b/doc/git-annex-shell.mdwn
index 38659d0e2..c866154ac 100644
--- a/doc/git-annex-shell.mdwn
+++ b/doc/git-annex-shell.mdwn
@@ -60,6 +60,10 @@ first "/~/" or "/~user/" is expanded to the specified home directory.
This commits any staged changes to the git-annex branch.
It also runs the annex-content hook.
+* gcryptsetup gcryptid
+
+ Sets up a repository as a gcrypt repository.
+
# OPTIONS
Most options are the same as in git-annex. The ones specific
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 60736d579..4cf29155b 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -60,50 +60,57 @@ files in the directory. When no path is specified, most git-annex commands
default to acting on all relevant files in the current directory (and
subdirectories).
-* add [path ...]
+* `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
+ (Use `--force` to add ignored files.) Dotfiles are skipped unless explicitly
listed.
-* get [path ...]
+* `get [path ...]`
Makes the content of annexed files available in this repository. This
will involve copying them from another repository, or downloading them,
or transferring them from some kind of key-value store.
Normally git-annex will choose which repository to copy the content from,
- but you can override this using the --from option.
+ but you can override this using the `--from` option.
-* drop [path ...]
+* `drop [path ...]`
Drops the content of annexed files from this repository.
git-annex will refuse to drop content if it cannot verify it is
- safe to do so. This can be overridden with the --force switch.
+ safe to do so. This can be overridden with the `--force` switch.
- To drop content from a remote, specify --from.
+ To drop content from a remote, specify `--from`.
-* move [path ...]
+* `move [path ...]`
- When used with the --from option, moves the content of annexed files
+ When used with the `--from` option, moves the content of annexed files
from the specified repository to the current one.
- When used with the --to option, moves the content of annexed files from
+ When used with the `--to` option, moves the content of annexed files from
the current repository to the specified one.
-* copy [path ...]
+* `copy [path ...]`
- When used with the --from option, copies the content of annexed files
+ When used with the `--from` option, copies the content of annexed files
from the specified repository to the current one.
- When used with the --to option, copies the content of annexed files from
+ When used with the `--to` option, copies the content of annexed files from
the current repository to the specified one.
- To avoid contacting the remote to check if it has every file, specify --fast
+ To avoid contacting the remote to check if it has every file, specify `--fast`
-* unlock [path ...]
+* `status` [path ...]`
+
+ Similar to `git status --short`, displays the status of the files in the
+ working tree. Shows files that are not checked into git, files that
+ have been deleted, and files that have been modified.
+ Particulary useful in direct mode.
+
+* `unlock [path ...]`
Normally, the content of annexed files is protected from being changed.
Unlocking a annexed file allows it to be modified. This replaces the
@@ -111,24 +118,24 @@ subdirectories).
You can then modify it and `git annex add` (or `git commit`) to inject
it back into the annex.
-* edit [path ...]
+* `edit [path ...]`
This is an alias for the unlock command. May be easier to remember,
if you think of this as allowing you to edit an annexed file.
-* lock [path ...]
+* `lock [path ...]`
Use this to undo an unlock command if you don't want to modify
the files, or have made modifications you want to discard.
-* sync [remote ...]
+* `sync [remote ...]`
Use this command when you want to synchronize the local repository with
one or more of its remotes. You can specifiy the remotes to sync with;
- the default is to sync with all remotes. Or specify --fast to sync with
+ the default is to sync with all remotes. Or specify `--fast` to sync with
the remotes with the lowest annex-cost value.
- The sync process involves first committing all local changes (git commit -a),
+ The sync process involves first committing all local changes
then fetching and merging the `synced/master` and the `git-annex` branch
from the remote repositories and finally pushing the changes back to
those branches on the remote repositories. You can use standard git
@@ -148,7 +155,7 @@ subdirectories).
Note that sync does not transfer any file contents from or to the remote
repositories.
-* merge
+* `merge`
This performs the same merging that is done by the sync command, but
without pushing or pulling any data.
@@ -157,53 +164,95 @@ subdirectories).
post-receive hook. Then any syncs to the repository will update its working
copy automatically.
-* addurl [url ...]
+* `mirror [path ...]`
+
+ This causes a destination repository to mirror a source repository.
+
+ To use the local repository as the source repository,
+ specify mirror `--to` remote.
+
+ To use a remote as the source repository, specify mirror `--from` remote.
+
+ Each specified file in the source repository is mirrored to the destination
+ repository. If a file's content is present in the source repository, it is
+ copied to the destination repository. If a file's content is not present in
+ the source repository, it will be dropped from the destination repository
+ when possible.
+
+ Note that mirror does not sync the git repository, but only the file
+ contents.
+
+* `addurl [url ...]`
Downloads each url to its own file, which is added to the annex.
- To avoid immediately downloading the url, specify --fast.
+ To avoid immediately downloading the url, specify `--fast`.
To avoid storing the size of the url's content, and accept whatever
- is there at a future point, specify --relaxed. (Implies --fast.)
+ is there at a future point, specify `--relaxed`. (Implies `--fast`.)
Normally the filename is based on the full url, so will look like
"www.example.com_dir_subdir_bigfile". For a shorter filename, specify
- --pathdepth=N. For example, --pathdepth=1 will use "dir/subdir/bigfile",
- while --pathdepth=3 will use "bigfile". It can also be negative;
- --pathdepth=-2 will use the last two parts of the url.
+ `--pathdepth=N`. For example, `--pathdepth=1` will use "dir/subdir/bigfile",
+ while `--pathdepth=3` will use "bigfile". It can also be negative;
+ `--pathdepth=-2` will use the last two parts of the url.
- Or, to directly specify what file the url is added to, specify --file.
+ Or, to directly specify what file the url is added to, specify `--file`.
This changes the behavior; now all the specified urls are recorded as
alternate locations from which the file can be downloaded. In this mode,
addurl can be used both to add new files, or to add urls to existing files.
-* rmurl file url
+ When quvi is installed, urls are automatically tested to see if they
+ are on a video hosting site, and the video is downloaded instead.
+
+* `rmurl file url`
Record that the file is no longer available at the url.
-* import [path ...]
+* `import [path ...]`
Moves files from somewhere outside the git working copy, and adds them to
the annex. Individual files to import can be specified.
- If a directory is specified, all files in it are imported, and any
- subdirectory structure inside it is preserved.
+ If a directory is specified, the entire directory is imported.
+
+ git annex import /media/camera/DCIM/*
+
+ By default, importing two files with the same contents from two different
+ locations will result in both files being added to the repository.
+ (With all checksumming backends, including the default SHA256E,
+ only one copy of the data will be stored.)
+
+ To not delete files from the import location, use the
+ `--duplicate` option. This could allow importing the same files repeatedly
+ to different locations in a repository. More likely, it could be used to
+ import the same files to a number of different branches or separate git
+ repositories.
- git annex import /media/camera/DCIM/
+ To only import files whose content has not been seen before by git-annex,
+ use the `--deduplicate` option. Duplicate files will be deleted from the
+ import location.
+
+ The `--clean-duplicates` option does not import any new files, but any files
+ found in the import location that are duplicates of content in the annex
+ are deleted.
+
+ (Note that using `--deduplicate` or `--clean-duplicates` with the WORM
+ backend does not look at file content, but filename and mtime.)
-* importfeed [url ...]
+* `importfeed [url ...]`
Imports the contents of podcast feeds. Only downloads files whose
urls have not already been added to the repository before, so you can
delete, rename, etc the resulting files and repeated runs won't duplicate
- them. (Use --force to force downloading urls it's seen before.)
+ them. (Use `--force` to force downloading urls it's seen before.)
- Use --template to control where the files are stored.
+ Use `--template` to control where the files are stored.
The default template is '${feedtitle}/${itemtitle}${extension}'
(Other available variables: feedauthor, itemauthor, itemsummary, itemdescription, itemrights, itemid)
- The --relaxed and --fast options behave the same as they do in addurl.
+ The `--relaxed` and `--fast` options behave the same as they do in addurl.
-* watch
+* `watch`
Watches for changes to files in the current directory and its subdirectories,
and takes care of automatically adding new files, as well as dealing with
@@ -211,18 +260,26 @@ subdirectories).
background, you no longer need to manually run git commands when
manipulating your files.
- To not daemonize, run with --foreground ; to stop a running daemon,
- run with --stop
+ By default, all files in the directory will be added to the repository.
+ (Including dotfiles.) To block some files from being added, use
+ `.gitignore` files.
+
+ By default, all files that are added are added to the annex, the same
+ as when you run `git annex add`. If you configure annex.largefiles,
+ files that it does not match will instead be added with `git add`.
-* assistant
+ To not daemonize, run with `--foreground` ; to stop a running daemon,
+ run with `--stop`
+
+* `assistant`
Like watch, but also automatically syncs changes to other remotes.
Typically started at boot, or when you log in.
- With the --autostart option, the assistant is started in any repositories
+ With the `--autostart` option, the assistant is started in any repositories
it has created. These are listed in `~/.config/git-annex/autostart`
-* webapp
+* `webapp`
Opens a web app, that allows easy setup of a git-annex repository,
and control of the git-annex assistant.
@@ -230,7 +287,7 @@ subdirectories).
By default, the webapp can only be accessed from localhost, and running
it opens a browser window.
- With the --listen=address[:port] option, the webapp can be made to listen
+ With the `--listen=address[:port]` option, the webapp can be made to listen
for connections on the specified address. This disables running a
local web browser, and outputs the url you can use to open the webapp
from a remote computer.
@@ -238,7 +295,7 @@ subdirectories).
# REPOSITORY SETUP COMMANDS
-* init [description]
+* `init [description]`
Until a repository (or one of its remotes) has been initialized,
git-annex will refuse to operate on it, to avoid accidentially
@@ -248,7 +305,7 @@ subdirectories).
of a repository with its own description. If you don't provide one,
one will be generated.
-* describe repository description
+* `describe repository description`
Changes the description of a repository.
@@ -256,7 +313,7 @@ subdirectories).
by uuid. To change the description of the current repository, use
"here".
-* initremote name [param=value ...]
+* `initremote name [param=value ...]`
Creates a new special remote, and adds it to `.git/config`.
@@ -264,21 +321,32 @@ subdirectories).
types of special remotes need different configuration values. The
command will prompt for parameters as needed.
- All special remotes support encryption. You must either specify
- encryption=none to disable encryption, or use encryption=keyid
- (or encryption=emailaddress) to specify a gpg key that can access
- the encrypted special remote.
-
- Note that with encryption enabled, a gpg key is created. This requires
- sufficient entropy. If initremote seems to hang or take a long time
- while generating the key, you may want to ctrl-c it and re-run with --fast,
- which causes it to use a lower-quality source of randomness.
+ All special remotes support encryption. You can either specify
+ `encryption=none` to disable encryption, or specify
+ `encryption=hybrid keyid=$keyid ...` to specify a gpg key id (or an email
+ address associated with a key.)
+
+ There are actually three schemes that can be used for management of the
+ encryption keys. When using the encryption=hybrid scheme, additional
+ gpg keys can be given access to the encrypted special remote easily
+ (without re-encrypting everything). When using encryption=shared,
+ a shared key is generated and stored in the git repository, allowing
+ anyone who can clone the git repository to access it. Finally, when using
+ encryption=pubkey, content in the special remote is directly encrypted
+ to the specified gpg keys, and additional ones cannot easily be given
+ access.
+
+ Note that with encryption enabled, a cryptographic key is created.
+ This requires sufficient entropy. If initremote seems to hang or take
+ a long time while generating the key, you may want to ctrl-c it and
+ re-run with `--fast`, which causes it to use a lower-quality source of
+ randomness.
Example Amazon S3 remote:
- git annex initremote mys3 type=S3 encryption=me@example.com datacenter=EU
+ git annex initremote mys3 type=S3 encryption=hybrid keyid=me@example.com datacenter=EU
-* enableremote name [param=value ...]
+* `enableremote name [param=value ...]`
Enables use of an existing special remote in the current repository,
which may be a different repository than the one in which it was
@@ -292,61 +360,84 @@ subdirectories).
For example, the directory special remote requires a directory= parameter.
This command can also be used to modify the configuration of an existing
- special remote, by specifying new values for parameters that were originally
- set when using initremote. For example, to add a new gpg key to the keys
- that can access an encrypted remote:
+ special remote, by specifying new values for parameters that were
+ originally set when using initremote. (However, some settings such as
+ the as the encryption scheme cannot be changed once a special remote
+ has been created.)
+
+ The gpg keys that an encrypted special remote is encrypted to can be
+ changed using the keyid+= and keyid-= parameters. These respectively
+ add and remove keys from the list. However, note that removing a key
+ does NOT necessarily prevent the key's owner from accessing data
+ in the encrypted special remote
+ (which is by design impossible, short of deleting the remote).
+
+ One use-case of keyid-= is to replace a revoked key with
+ a new key:
- git annex enableremote mys3 encryption=friend@example.com
+ git annex enableremote mys3 keyid-=revokedkey keyid+=newkey
-* trust [repository ...]
+ Also, note that for encrypted special remotes using plain public-key
+ encryption (encryption=pubkey), adding or removing a key has NO effect
+ on files that have already been copied to the remote. Hence using
+ keyid+= and keyid-= with such remotes should be used with care, and
+ make little sense except in cases like the revoked key example above.
+
+* `trust [repository ...]`
Records that a repository is trusted to not unexpectedly lose
content. Use with care.
To trust the current repository, use "here".
-* untrust [repository ...]
+* `untrust [repository ...]`
Records that a repository is not trusted and could lose content
at any time.
-* semitrust [repository ...]
+* `semitrust [repository ...]`
Returns a repository to the default semi trusted state.
-* dead [repository ...]
+* `dead [repository ...]`
Indicates that the repository has been irretrevably lost.
(To undo, use semitrust.)
-* group repository groupname
+* `group repository groupname`
Adds a repository to a group, such as "archival", "enduser", or "transfer".
The groupname must be a single word.
-* ungroup repository groupname
+* `ungroup repository groupname`
Removes a repository from a group.
-* content repository [expression]
+* `wanted repository [expression]`
When run with an expression, configures the content that is preferred
to be held in the archive. See PREFERRED CONTENT below.
For example:
- git annex content . "include=*.mp3 or include=*.ogg"
+ git annex wanted . "include=*.mp3 or include=*.ogg"
Without an expression, displays the current preferred content setting
of the repository.
-* vicfg
+* `schedule repository [expression]`
+
+ When run with an expression, configures scheduled jobs to run at a
+ particular time. This can be used to make the assistant periodically run
+ incremental fscks. See SCHEDULED JOBS below.
+
+* `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.
-* direct
+* `direct`
Switches a repository to use direct mode, where rather than symlinks to
files, the files are directly present in the repository.
@@ -357,7 +448,7 @@ subdirectories).
use in direct mode repositories, and can result in data loss or other
bad behavior.
-* indirect
+* `indirect`
Switches a repository back from direct mode to the default, indirect mode.
@@ -365,23 +456,24 @@ subdirectories).
# REPOSITORY MAINTENANCE COMMANDS
-* fsck [path ...]
+* `fsck [path ...]`
With no parameters, this command checks the whole annex for consistency,
- and warns about or fixes any problems found.
+ and warns about or fixes any problems found. This is a good compliment to
+ `git fsck`.
With parameters, only the specified files are checked.
- To check a remote to fsck, specify --from.
+ To check a remote to fsck, specify `--from`.
To avoid expensive checksum calculations (and expensive transfers when
- fscking a remote), specify --fast.
+ fscking a remote), specify `--fast`.
- To start a new incremental fsck, specify --incremental. Then
- the next time you fsck, you can specify --more to skip over
+ To start a new incremental fsck, specify `--incremental`. Then
+ the next time you fsck, you can specify `--more` to skip over
files that have already been checked, and continue where it left off.
- The --incremental-schedule option makes a new incremental fsck be
+ The `--incremental-schedule` option makes a new incremental fsck be
started a configurable time after the last incremental fsck was started.
Once the current incremental fsck has completely finished, it causes
a new one to start.
@@ -391,116 +483,169 @@ subdirectories).
have been fscked. And once it's done, you'd like a new fsck pass to start,
but no more often than once a month. Then put this in a nightly cron job:
- git annex fsck --incremental-schedule 30d --time-limit 5h
+ git annex fsck --incremental-schedule 30d --time-limit 5h
To verify data integrity only while disregarding required number of copies,
- use --numcopies=1.
+ use `--numcopies=1`.
-* unused
+* `unused`
Checks the annex for data that does not correspond to any files present
in any tag or branch, and prints a numbered list of the data.
- To only show unused temp and bad files, specify --fast.
+ To only show unused temp and bad files, specify `--fast`.
- To check for annexed data on a remote, specify --from.
+ To check for annexed data on a remote, specify `--from`.
- After running this command, you can use the --unused option to
+ After running this command, you can use the `--unused` option to
operate on all the unused data that was found. For example, to
move all unused data to origin:
- git annex unused; git annex move --unused --to origin
+ git annex unused; git annex move --unused --to origin
-* dropunused [number|range ...]
+* `dropunused [number|range ...]`
Drops the data corresponding to the numbers, as listed by the last
`git annex unused`
You can also specify ranges of numbers, such as "1-1000".
- To drop the data from a remote, specify --from.
+ To drop the data from a remote, specify `--from.`
-* addunused [number|range ...]
+* `addunused [number|range ...]`
Adds back files for the content corresponding to the numbers or ranges,
as listed by the last `git annex unused`. The files will have names
starting with "unused."
-* fix [path ...]
+* `fix [path ...]`
Fixes up symlinks that have become broken to again point to annexed content.
This is useful to run if you have been moving the symlinks around,
but is done automatically when committing a change with git too.
-* upgrade
+* `upgrade`
Upgrades the repository to current layout.
-# QUERY COMMANDS
+* `forget`
-* version
+ Causes the git-annex branch to be rewritten, throwing away historical
+ data about past locations of files. The resulting branch will use less
+ space, but `git annex log` will not be able to show where
+ files used to be located.
+
+ To also prune references to repositories that have been marked as dead,
+ specify `--drop-dead`.
+
+ When this rewritten branch is merged into other clones of
+ the repository, `git-annex` will automatically perform the same rewriting
+ to their local `git-annex` branches. So the forgetfulness will automatically
+ propigate out from its starting point until all repositories running
+ git-annex have forgotten their old history. (You may need to force
+ git to push the branch to any git repositories not running git-annex.
+
+* `repair`
+
+ This can repair many of the problems with git repositories that `git fsck`
+ detects, but does not itself fix. It's useful if a repository has become
+ badly damaged. One way this can happen is if a repisitory used by git-annex
+ is on a removable drive that gets unplugged at the wrong time.
+
+ This command can actually be used inside git repositories that do not
+ use git-annex at all; when used in a repository using git-annex, it
+ does additional repairs of the git-annex branch.
+
+ It works by deleting any corrupt objects from the git repository, and
+ retriving all missing objects it can from the remotes of the repository.
+
+ If that is not sufficient to fully recover the repository, it can also
+ reset branches back to commits before the corruption happened, delete
+ branches that are no longer available due to the lost data, and remove any
+ missing files from the index. It will only do this if run with the
+ `--force` option, since that rewrites history and throws out missing data.
+ Note that the `--force` option never touches tags, even if they are no
+ longer usable due to missing data.
+
+ After running this command, you will probably want to run `git fsck` to
+ verify it fixed the repository. Note that fsck may still complain about
+ objects referenced by the reflog, or the stash, if they were unable to be
+ recovered. This command does not try to clean up either the reflog or the
+ stash.
+
+ It is also a good idea to run `git annex fsck --fast` after this command,
+ to make sure that the git-annex branch reflects reality.
- Shows the version of git-annex, as well as repository version information.
+# QUERY COMMANDS
-* find [path ...]
+* `find [path ...]`
Outputs a list of annexed files in the specified path. With no path,
finds files in the current directory and its subdirectories.
By default, only lists annexed files whose content is currently present.
This can be changed by specifying file matching options. To list all
- annexed files, present or not, specify --include "*". To list all
- annexed files whose content is not present, specify --not --in=here
+ annexed files, present or not, specify `--include "*"`. To list all
+ annexed files whose content is not present, specify `--not --in=here`
To output filenames terminated with nulls, for use with xargs -0,
- specify --print0. Or, a custom output formatting can be specified using
- --format. The default output format is the same as --format='${file}\\n'
+ specify `--print0`. Or, a custom output formatting can be specified using
+ `--format`. The default output format is the same as `--format='${file}\\n'`
These variables are available for use in formats: file, key, backend,
bytesize, humansize
-* whereis [path ...]
+* `whereis [path ...]`
- Displays a list of repositories known to contain the content of the
- specified file or files.
+ Displays a information about where the contents of files are located.
-* log [path ...]
+* `list [path ...]`
+
+ Displays a table of remotes that contain the contents of the specified
+ files. This is similar to whereis but a more compact display. Only
+ configured remotes are shown by default; specify --allrepos to list
+ all repositories.
+
+* `log [path ...]`
Displays the location log for the specified file or files,
showing each repository they were added to ("+") and removed from ("-").
To limit how far back to seach for location log changes, the options
- --since, --after, --until, --before, and --max-count can be specified.
- They are passed through to git log. For example, --since "1 month ago"
+ `--since`, `--after`, `--until`, `--before`, and `--max-count` can be specified.
+ They are passed through to git log. For example, `--since "1 month ago"`
To generate output suitable for the gource visualisation program,
- specify --gource.
+ specify `--gource`.
-* status [directory ...]
+* `info [directory ...]`
Displays some statistics and other information, including how much data
is in the annex and a list of all known repositories.
- To only show the data that can be gathered quickly, use --fast.
+ To only show the data that can be gathered quickly, use `--fast`.
- When a directory is specified, shows only an abbreviated status
+ When a directory is specified, shows a differently formatted info
display for that directory. In this mode, all of the file matching
options can be used to filter the files that will be included in
- the status.
+ the information.
For example, suppose you want to run "git annex get .", but
would first like to see how much disk space that will use.
Then run:
- git annex status . --not --in here
+ git annex info --fast . --not --in here
+* `version`
+
+ Shows the version of git-annex, as well as repository version information.
-* map
+* `map`
Helps you keep track of your repositories, and the connections between them,
by going out and looking at all the ones it can get to, and generating a
Graphviz file displaying it all. If the `dot` command is available, it is
used to display the file to your screen (using x11 backend). (To disable
- this display, specify --fast)
+ this display, specify `--fast`)
This command only connects to hosts that the host it's run on can
directly connect to. It does not try to tunnel through intermediate hosts.
@@ -514,10 +659,10 @@ subdirectories).
# UTILITY COMMANDS
-* migrate [path ...]
+* `migrate [path ...]`
Changes the specified annexed files to use the default key-value backend
- (or the one specified with --backend). Only files whose content
+ (or the one specified with `--backend`). Only files whose content
is currently available are migrated.
Note that the content is also still available using the old key after
@@ -527,7 +672,7 @@ subdirectories).
However, if a backend changes the information it uses to construct a key,
this can also be used to migrate files to use the new key format.
-* reinject src dest
+* `reinject src dest`
Moves the src file into the annex as the content of the dest file.
This can be useful if you have obtained the content of a file from
@@ -538,22 +683,26 @@ subdirectories).
Example:
- git annex reinject /tmp/foo.iso foo.iso
+ git annex reinject /tmp/foo.iso foo.iso
+
+* `unannex [path ...]`
-* unannex [path ...]
+ Use this to undo an accidental `git annex add` command. It puts the
+ file back how it was before the add.
- Use this to undo an accidental `git annex add` command. You can use
- `git annex unannex` to move content out of the annex at any point,
- even if you've already committed it.
+ Note that for safety, the content of the file remains in the annex,
+ until you use `git annex unused` and `git annex dropunused`.
This is not the command you should use if you intentionally annexed a
file and don't want its contents any more. In that case you should use
`git annex drop` instead, and you can also `git rm` the file.
- In --fast mode, this command leaves content in the annex, simply making
- a hard link to it.
+ Normally this does a slow copy of the file. In `--fast` mode, it
+ instead makes a hard link from the file to the content in the annex.
+ But use --fast mode with caution, because editing the file will
+ change the content in the annex.
-* uninit
+* `uninit`
Use this to stop using git annex. It will unannex every file in the
repository, and remove all of git-annex's other data, leaving you with a
@@ -561,21 +710,30 @@ subdirectories).
# PLUMBING COMMANDS
-* pre-commit [path ...]
+* `pre-commit [path ...]`
+
+ This is meant to be called from git's pre-commit hook. `git annex init`
+ automatically creates a pre-commit hook using this.
Fixes up symlinks that are staged as part of a commit, to ensure they
point to annexed content. Also handles injecting changes to unlocked
files into the annex.
- This is meant to be called from git's pre-commit hook. `git annex init`
- automatically creates a pre-commit hook using this.
+* `update-hook refname olvrev newrev`
+
+ This is meant to be called from git's update hook. `git annex init`
+ automatically creates an update hook using this.
-* fromkey key file
+ This denies updates being pushed for the currently checked out branch.
+ While receive.denyCurrentBranch normally prevents that, it does
+ not for fake bare repositories, as used by direct mode.
+
+* `fromkey key file`
This plumbing-level command can be used to manually set up a file
in the git repository to link to a specified key.
-* dropkey [key ...]
+* `dropkey [key ...]`
This plumbing-level command drops the annexed data for the specified
keys from this repository.
@@ -585,48 +743,48 @@ subdirectories).
Example:
- git annex dropkey SHA1-s10-7da006579dd64330eb2456001fd01948430572f2
+ git annex dropkey SHA1-s10-7da006579dd64330eb2456001fd01948430572f2
-* transferkeys
+* `transferkeys`
This plumbing-level command is used by the assistant to transfer data.
-* rekey [file key ...]
+* `rekey [file key ...]`
This plumbing-level command is similar to migrate, but you specify
both the file, and the new key to use for it.
- With --force, even files whose content is not currently available will
+ With `--force`, even files whose content is not currently available will
be rekeyed. Use with caution.
-* test
+* `test`
This runs git-annex's built-in test suite.
-* xmppgit
+* `xmppgit`
This command is used internally to perform git pulls over XMPP.
# OPTIONS
-* --force
+* `--force`
Force unsafe actions, such as dropping a file's content when no other
source of it can be verified to still exist, or adding ignored files.
Use with care.
-* --fast
+* `--fast`
Enables less expensive, but also less thorough versions of some commands.
What is avoided depends on the command.
-* --auto
+* `--auto`
Enables automatic mode. Commands that get, drop, or move file contents
will only do so when needed to help satisfy the setting of annex.numcopies,
and preferred content configuration.
-* --all
+* `--all`
Operate on all data that has been stored in the git annex,
including old versions of files. This is the default behavior when
@@ -634,56 +792,56 @@ subdirectories).
normal behavior is to only operate on specified files in the working
tree.
-* --unused
+* `--unused`
Operate on all data that has been determined to be unused by
a previous run of `git-annex unused`.
-* --quiet
+* `--quiet`
Avoid the default verbose display of what is done; only show errors
and progress displays.
-* --verbose
+* `--verbose`
Enable verbose display.
-* --json
+* `--json`
Rather than the normal output, generate JSON. This is intended to be
parsed by programs that use git-annex. Each line of output is a JSON
object. Note that json output is only usable with some git-annex commands,
- like status and find.
+ like info and find.
-* --debug
+* `--debug`
Show debug messages.
-* --no-debug
+* `--no-debug`
Disable debug messages.
-* --from=repository
+* `--from=repository`
Specifies a repository that content will be retrieved from, or that
should otherwise be acted on.
It should be specified using the name of a configured remote.
-* --to=repository
+* `--to=repository`
Specifies a repository that content will be sent to.
It should be specified using the name of a configured remote.
-* --numcopies=n
+* `--numcopies=n`
Overrides the `annex.numcopies` setting, forcing git-annex to ensure the
specified number of copies exist.
Note that setting numcopies to 0 is very unsafe.
-* --time-limit=time
+* `--time-limit=time`
Limits how long a git-annex command runs. The time can be something
like "5h", or "30m" or even "45s" or "10d".
@@ -694,16 +852,16 @@ subdirectories).
Also, note that if the time limit prevents git-annex from doing all it
was asked to, it will exit with a special code, 101.
-* --trust=repository
-* --semitrust=repository
-* --untrust=repository
+* `--trust=repository`
+* `--semitrust=repository`
+* `--untrust=repository`
Overrides trust settings for a repository. May be specified more than once.
The repository should be specified using the name of a configured remote,
or the UUID or description of a repository.
-* --trust-glacier-inventory
+* `--trust-glacier-inventory`
Amazon Glacier inventories take hours to retrieve, and may not represent
the current state of a repository. So git-annex does not trust that
@@ -714,14 +872,14 @@ subdirectories).
removed a file from Glacier. If you try to drop the only other copy of the
file, and this switch is enabled, you could lose data!
-* --backend=name
+* `--backend=name`
Specifies which key-value backend to use. This can be used when
adding a file to the annex, or migrating a file. Once files
are in the annex, their backend is known and this option is not
necessary.
-* --format=value
+* `--format=value`
Specifies a custom output format. The value is a format string,
in which '${var}' is expanded to the value of a variable. To right-justify
@@ -731,7 +889,11 @@ subdirectories).
Also, '\\n' is a newline, '\\000' is a NULL, etc.
-* -c name=value
+* `--user-agent=value`
+
+ Overrides the User-Agent to use when downloading files from the web.
+
+* `-c name=value`
Used to override git configuration settings. May be specified multiple times.
@@ -748,21 +910,21 @@ For example:
The above example prevents git-annex from working on mp3 files whose
file contents are present at either of two repositories.
-* --exclude=glob
+* `--exclude=glob`
Skips files matching the glob pattern. The glob is matched relative to
the current directory. For example:
- --exclude='*.mp3' --exclude='subdir/*'
+ --exclude='*.mp3' --exclude='subdir/*'
-* --include=glob
+* `--include=glob`
- Skips files not matching the glob pattern. (Same as --not --exclude.)
+ Skips files not matching the glob pattern. (Same as `--not --exclude`.)
For example, to include only mp3 and ogg files:
- --include='*.mp3' --or --include='*.ogg'
+ --include='*.mp3' --or --include='*.ogg'
-* --in=repository
+* `--in=repository`
Matches only files that git-annex believes have their contents present
in a repository. Note that it does not check the repository to verify
@@ -770,41 +932,41 @@ file contents are present at either of two repositories.
The repository should be specified using the name of a configured remote,
or the UUID or description of a repository. For the current repository,
- use --in=here
+ use `--in=here`
-* --copies=number
+* `--copies=number`
Matches only files that git-annex believes to have the specified number
of copies, or more. Note that it does not check remotes to verify that
the copies still exist.
-* --copies=trustlevel:number
+* `--copies=trustlevel:number`
Matches only files that git-annex believes have the specified number of
copies, on remotes with the specified trust level. For example,
- "--copies=trusted:2"
+ `--copies=trusted:2`
To match any trust level at or higher than a given level,
- use 'trustlevel+'. For example, "--copies=semitrusted+:2"
+ use 'trustlevel+'. For example, `--copies=semitrusted+:2`
-* --copies=groupname:number
+* `--copies=groupname:number`
Matches only files that git-annex believes have the specified number of
copies, on remotes in the specified group. For example,
- "--copies=archive:2"
+ `--copies=archive:2`
-* --inbackend=name
+* `--inbackend=name`
Matches only files whose content is stored using the specified key-value
backend.
-* --inallgroup=groupname
+* `--inallgroup=groupname`
Matches only files that git-annex believes are present in all repositories
in the specified group.
-* --smallerthan=size
-* --largerthan=size
+* `--smallerthan=size`
+* `--largerthan=size`
Matches only files whose content is smaller than, or larger than the
specified size.
@@ -812,25 +974,37 @@ file contents are present at either of two repositories.
The size can be specified with any commonly used units, for example,
"0.5 gb" or "100 KiloBytes"
-* --not
+* `--want-get`
+
+ Matches files that the preferred content settings for the repository
+ make it want to get. Note that this will match even files that are
+ already present, unless limited with eg, `--not --in .`
+
+* `--want-drop`
+
+ Matches files that the preferred content settings for the repository
+ make it want to drop. Note that this will match even files that have
+ already been dropped, unless limited with eg, `--in .`
+
+* `--not`
Inverts the next file matching option. For example, to only act on
- files with less than 3 copies, use --not --copies=3
+ files with less than 3 copies, use `--not --copies=3`
-* --and
+* `--and`
Requires that both the previous and the next file matching option matches.
The default.
-* --or
+* `--or`
Requires that either the previous, or the next file matching option matches.
-* -(
+* `-(`
Opens a group of file matching options.
-* -)
+* `-)`
Closes a group of file matching options.
@@ -838,8 +1012,8 @@ file contents are present at either of two repositories.
Each repository has a preferred content setting, which specifies content
that the repository wants to have present. These settings can be configured
-using `git annex vicfg`. They are used by the `--auto` option, and
-by the git-annex assistant.
+using `git annex vicfg` or `git annex wanted`.
+They are used by the `--auto` option, and by the git-annex assistant.
The preferred content settings are similar, but not identical to
the file matching options specified above, just without the dashes.
@@ -849,9 +1023,37 @@ For example:
The main differences are that `exclude=` and `include=` always
match relative to the top of the git repository, and that there is
-no equivilant to --in.
+no equivilant to `--in`.
+
+When a repository is in one of the standard predefined groups, like "backup"
+and "client", setting its preferred content to "standard" will use a
+built-in preferred content expression ddeveloped for that group.
-# CONFIGURATION
+# SCHEDULED JOBS
+
+The git-annex assistant daemon can be configured to run scheduled jobs.
+This is similar to cron and anacron (and you can use them if you prefer),
+but has the advantage of being integrated into git-annex, and so being able
+to eg, fsck a repository on a removable drive when the drive gets
+connected.
+
+The scheduled jobs can be configured using `git annex vicfg` or
+`git annex schedule`.
+
+These actions are available: "fsck self", "fsck UUID" (where UUID
+is the UUID of a remote to fsck). After the action comes the duration
+to allow the action to run, and finally the schedule of when to run it.
+
+To schedule multiple jobs, separate them with "; ".
+
+Some examples:
+
+ fsck self 30m every day at any time
+ fsck self 1h every month at 3 AM
+ fsck self 1h on day 1 of every month at any time
+ fsck self 1h every week divisible by 2 at any time
+
+# CONFIGURATION VIA .git/config
Like other git commands, git-annex is configured via `.git/config`.
Here are all the supported configuration settings.
@@ -892,7 +1094,7 @@ Here are all the supported configuration settings.
Example:
- annex.largefiles = largerthan=100kb and not (include=*.c or include=*.h)
+ annex.largefiles = largerthan=100kb and not (include=*.c or include=*.h)
* `annex.queuesize`
@@ -909,7 +1111,7 @@ Here are all the supported configuration settings.
up to 500000 keys. If your repository is larger than that,
you can adjust this to avoid `git annex unused` not noticing some unused
data files. Increasing this will make `git-annex unused` consume more memory;
- run `git annex status` for memory usage numbers.
+ run `git annex info` for memory usage numbers.
* `annex.bloomaccuracy`
@@ -917,7 +1119,7 @@ Here are all the supported configuration settings.
`git annex unused`. The default accuracy is 1000 --
1 unused file out of 1000 will be missed by `git annex unused`. Increasing
the accuracy will make `git annex unused` consume more memory;
- run `git annex status` for memory usage numbers.
+ run `git annex info` for memory usage numbers.
* `annex.sshcaching`
@@ -939,6 +1141,11 @@ Here are all the supported configuration settings.
to close it. On Mac OSX, when not using direct mode this defaults to
1 second, to work around a bad interaction with software there.
+* `annex.fscknudge`
+
+ When set to false, prevents the webapp from reminding you when using
+ repositories that lack consistency checks.
+
* `annex.autocommit`
Set to false to prevent the git-annex assistant from automatically
@@ -996,7 +1203,7 @@ Here are all the supported configuration settings.
If set to `true`, prevents git-annex
from storing file contents on this remote by default.
- (You can still request it be used by the --from and --to options.)
+ (You can still request it be used by the `--from` and `--to` options.)
This is, for example, useful if the remote is located somewhere
without git-annex-shell. (For example, if it's on GitHub).
@@ -1035,7 +1242,7 @@ Here are all the supported configuration settings.
Options to use when using rsync
to or from this remote. For example, to force ipv6, and limit
- the bandwidth to 100Kbyte/s, set it to "-6 --bwlimit 100"
+ the bandwidth to 100Kbyte/s, set it to `-6 --bwlimit 100`
* `remote.<name>.annex-rsync-transport`
@@ -1049,14 +1256,14 @@ Here are all the supported configuration settings.
* `remote.<name>.annex-bup-split-options`
Options to pass to bup split when storing content in this remote.
- For example, to limit the bandwidth to 100Kbyte/s, set it to "--bwlimit 100k"
+ For example, to limit the bandwidth to 100Kbyte/s, set it to `--bwlimit 100k`
(There is no corresponding option for bup join.)
* `remote.<name>.annex-gnupg-options`
Options to pass to GnuPG for symmetric encryption. For instance, to
use the AES cipher with a 256 bits key and disable compression, set it
- to "--cipher-algo AES256 --compress-algo none". (These options take
+ to `--cipher-algo AES256 --compress-algo none`. (These options take
precedence over the default GnuPG configuration, which is otherwise
used.)
@@ -1072,6 +1279,11 @@ Here are all the supported configuration settings.
(wget is always used in preference to curl if available.)
For example, to force ipv4 only, set it to "-4"
+* `annex.quvi-options`
+
+ Options to pass to quvi when using it to find the url to download for a
+ video.
+
* `annex.http-headers`
HTTP headers to send when downloading from the web. Multiple lines of
@@ -1131,6 +1343,15 @@ Here are all the supported configuration settings.
Used to identify the XMPP address of a Jabber buddy.
Normally this is set up by the git-annex assistant when pairing over XMPP.
+* `remote.<name>.gcrypt`
+
+ Used to identify gcrypt special remotes.
+ Normally this is automatically set up by `git annex initremote`.
+
+ It is set to "true" if this is a gcrypt remote.
+ If the gcrypt remote is accessible over ssh and has git-annex-shell
+ available to manage it, it's set to "shell"
+
# CONFIGURATION VIA .gitattributes
The key-value backend used when adding a new file to the annex can be
diff --git a/doc/git-recover-repository.mdwn b/doc/git-recover-repository.mdwn
new file mode 100644
index 000000000..dac4a310b
--- /dev/null
+++ b/doc/git-recover-repository.mdwn
@@ -0,0 +1,40 @@
+# NAME
+
+git-recover-repository - Fix a broken git repository
+
+# SYNOPSIS
+
+git-recover-repository [--force]
+
+# DESCRIPTION
+
+This can fix a corrupt or broken git repository, which git fsck would
+only complain has problems.
+
+It does by deleting all corrupt objects, and retreiving all missing
+objects that it can from the remotes of the repository.
+
+If that is not sufficient to fully recover the repository, it can also
+reset branches back to commits before the corruption happened, delete
+branches that are no longer available due to the lost data, and remove any
+missing files from the index. It will only do this if run with the
+`--force` option, since that rewrites history and throws out missing data.
+Note that the `--force` option never touches tags, even if they are no
+longer usable due to missing data.
+
+After running this command, you will probably want to run `git fsck` to
+verify it fixed the repository. Note that fsck may still complain about
+objects referenced by the reflog, or the stash, if they were unable to be
+recovered. This command does not try to clean up either the reflog or the
+stash.
+
+Since this command unpacks all packs in the repository, you may want to
+run `git gc` afterwards.
+
+# AUTHOR
+
+Joey Hess <joey@kitenet.net>
+
+<http://git-annex.branchable.com/>
+
+Warning: Automatically converted into a man page by mdwn2man. Edit with care
diff --git a/doc/how_it_works/comment_1_b3bdd6a06d5764db521ae54878131f5f._comment b/doc/how_it_works/comment_1_b3bdd6a06d5764db521ae54878131f5f._comment
new file mode 100644
index 000000000..60aeab732
--- /dev/null
+++ b/doc/how_it_works/comment_1_b3bdd6a06d5764db521ae54878131f5f._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnaH44G3QbxBAYyDwy0PbvL0ls60XoaR3Y"
+ nickname="Nigel"
+ subject="minor suggestion"
+ date="2013-08-10T14:31:31Z"
+ content="""
+The contents of large files are not stored in git, only the names of the files and some other metadata remain there.
+
+Would this read better to the newbie as:
+
+The contents of 'annexed' files are not stored in git, only the names of the files and some other metadata remain there.
+
+First time for me, the note about large files made me think that maybe annex operated on files above a certain size.
+"""]]
diff --git a/doc/install.mdwn b/doc/install.mdwn
index 27cd00a96..ecbf11a15 100644
--- a/doc/install.mdwn
+++ b/doc/install.mdwn
@@ -25,3 +25,7 @@ As a haskell package, git-annex can be installed from source pretty easily
## Installation from scratch
This is not recommended, but if you really want to, see [[fromscratch]].
+
+## See also
+
+[[autobuild overview|builds]]
diff --git a/doc/install/Android.mdwn b/doc/install/Android.mdwn
index dbd0c0198..537f6d518 100644
--- a/doc/install/Android.mdwn
+++ b/doc/install/Android.mdwn
@@ -7,25 +7,31 @@ Now git-annex can be used on Android!
First, ensure your Android device is configured to allow installation
of the app. Go to Setup -&gt; Security, and enable "Unknown Sources".
-[Download the git-annex.apk](http://downloads.kitenet.net/git-annex/android/current/)
-onto your Android device, and open it to install.
+Then download the git-annex.apk for your version of Android, and
+open it to install.
+
+* [Android 4.4 and 4.3 git-annex.apk](http://downloads.kitenet.net/git-annex/android/current/4.3/git-annex.apk)
+* [Android 4.0 to 4.2 git-annex.apk](http://downloads.kitenet.net/git-annex/android/current/4.0/git-annex.apk)
## autobuilds
-A daily build is also available.
+A daily build is also available, thanks to Mesar Hameed and the University
+of Bath CS department.
-* [download apk](http://downloads.kitenet.net/git-annex/autobuild/android/git-annex.apk) ([build logs](http://downloads.kitenet.net/git-annex/autobuild/android/))
+* [Android 4.4 and 4.3 git-annex.apk](http://downloads.kitenet.net/git-annex/autobuild/android/4.3/git-annex.apk)
+* [Android 4.0 to 4.2 git-annex.apk](http://downloads.kitenet.net/git-annex/autobuild/android/4.0/git-annex.apk)
+* [build logs](http://downloads.kitenet.net/git-annex/autobuild/android/)
## building it yourself
-git-annex can be built for Android, with `make android`. It's not an easy
-process:
-
-* First, install <https://github.com/neurocyte/ghc-android>.
-* You will need to have the Android SDK and NDK installed; see
- `standalone/android/Makefile` to configure the paths to them. You'll also
- need ant, and the JDK.
-* In `standalone/android/`, run `install-haskell-packages native`
-* You also need to install git and all the utilities listed on [[fromscratch]],
- on the system doing the building.
-* Then to build the full Android app bundle, use `make androidapp`
+git-annex can be built from source for Android.
+
+1. Run `standalone/android/buildchroot` as root (requires debootstrap).
+ This builds a chroot with an `androidbuilder` user.
+ The rest of the build will run in this chroot as that user.
+2. Then run `standalone/android/install-haskell-packages`
+ Note that this will break from time to time as new versions of packages
+ are released, and the patches it applies have to be updated when
+ this happens.
+3. Finally, once the chroot is set up, you can build an Android binary
+ with `make android`, and `make androidapp` will build the complete APK.
diff --git a/doc/install/Android/comment_10_225f2c6fe255be93702cfbd4dc172f3b._comment b/doc/install/Android/comment_10_225f2c6fe255be93702cfbd4dc172f3b._comment
new file mode 100644
index 000000000..f6a71981e
--- /dev/null
+++ b/doc/install/Android/comment_10_225f2c6fe255be93702cfbd4dc172f3b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="+1 F-Droid"
+ date="2013-09-24T18:36:48Z"
+ content="""
+Availability in F-Droid would be really neat. I imagine the unusual build requirements would require some work though.
+"""]]
diff --git a/doc/install/Android/comment_11_4e970633d9073fcf4bc33f3fff2525b2._comment b/doc/install/Android/comment_11_4e970633d9073fcf4bc33f3fff2525b2._comment
new file mode 100644
index 000000000..f57fb8d79
--- /dev/null
+++ b/doc/install/Android/comment_11_4e970633d9073fcf4bc33f3fff2525b2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmK0703vNSIQsP1mGf-4MAPnsBZiSc6yVo"
+ nickname="Emre"
+ subject="What am I missing?"
+ date="2013-10-15T21:54:07Z"
+ content="""
+I've setup repositories on both my linux PC & android mini pc and added jabber account on both. They are both at my home network. They detected each other fine. But when it comes to syncing files, there's a message which says \"Unable to download files from your other devices\" with a button for \"add a cloud repository\". I don't need to add a cloud repository since both computers are at the same network? Or am I missing something in the architecture of git-annex that even to sync two local computers in the same LAN, annex would still need an external repo? (and if so, why would that be?)
+I'm not really willing to add an external repository as I intend to add large files and I don't want that they are first uploaded using a slow connection & then re-downloaded.
+What am I missing?
+"""]]
diff --git a/doc/install/Android/comment_12_87da4f379a0276b662583e7e22061218._comment b/doc/install/Android/comment_12_87da4f379a0276b662583e7e22061218._comment
new file mode 100644
index 000000000..772fa1d6a
--- /dev/null
+++ b/doc/install/Android/comment_12_87da4f379a0276b662583e7e22061218._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 12"
+ date="2013-10-16T16:05:45Z"
+ content="""
+To make computers on your network directly communicate, they must be connected together using the user interface. This is normally using the local pairing interface. But local pairing does not yet work on Android. The best you can do to instead on your Android device, add the Linux PC as a ssh server. This will let the Android device send/receive files directly with it over the local network.
+"""]]
diff --git a/doc/install/Android/comment_5_40cb6cb72c4ad4aa19a4a40f41a6a757._comment b/doc/install/Android/comment_5_40cb6cb72c4ad4aa19a4a40f41a6a757._comment
deleted file mode 100644
index 74c207306..000000000
--- a/doc/install/Android/comment_5_40cb6cb72c4ad4aa19a4a40f41a6a757._comment
+++ /dev/null
@@ -1,13 +0,0 @@
-[[!comment format=mdwn
- username="https://www.google.com/accounts/o8/id?id=AItOawnljkMF1zhScDfvJYMhXXubnar_DakLoas"
- nickname="Tony"
- subject="broken under 4.3?"
- date="2013-07-28T00:36:51Z"
- content="""
-Things seem broken under the recently released 4.3 release for nexus devices:
-
->Falling back to hardcoded app location; cannot find expected files in /data/app-lib
->u0_a33@mako:/sdcard/git-annex.home $ git annex webapp
->CANNOT LINK EXECUTABLE: git-annex invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built. with -Bsymbolic?)
->1|u0_a33@mako:/sdcard/git-annex.home $
-"""]]
diff --git a/doc/install/Android/comment_6_b0f723538e7328d5070c563f070858bd._comment b/doc/install/Android/comment_6_b0f723538e7328d5070c563f070858bd._comment
deleted file mode 100644
index e6a7aa072..000000000
--- a/doc/install/Android/comment_6_b0f723538e7328d5070c563f070858bd._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- username="justjohn"
- ip="71.233.149.123"
- subject="Broken on 4.3 on Nexus 7"
- date="2013-07-28T16:14:18Z"
- content="""
-I'm seeing the same error as the previous comment from Tony on my Nexus 7 after I updated it to the stock (albeit rooted) 4.3 release from Google.
-"""]]
diff --git a/doc/install/Android/comment_8_34f7c42050fa48769a6bfae60d72e477._comment b/doc/install/Android/comment_8_34f7c42050fa48769a6bfae60d72e477._comment
new file mode 100644
index 000000000..efba6aeeb
--- /dev/null
+++ b/doc/install/Android/comment_8_34f7c42050fa48769a6bfae60d72e477._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmrb8I1K5jjNr7ZrLSvgmkeQGjYauPeGJU"
+ nickname="Martin"
+ subject="comment 8"
+ date="2013-08-18T16:44:02Z"
+ content="""
+Any chance that older versions of Android will be supported in the future?
+"""]]
diff --git a/doc/install/Android/comment_9_f3d289b78d6bdb3cc65689495a8439a5._comment b/doc/install/Android/comment_9_f3d289b78d6bdb3cc65689495a8439a5._comment
new file mode 100644
index 000000000..989304242
--- /dev/null
+++ b/doc/install/Android/comment_9_f3d289b78d6bdb3cc65689495a8439a5._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://openlifechallenge.wordpress.com/"
+ nickname="O"
+ subject="Add to F-Droid"
+ date="2013-09-08T09:56:38Z"
+ content="""
+Hi,
+Really enjoy this app for Android! Super simple to use but it would be great if you could fix a folder navigator option when choosing location for device repo, right now it does not work.
+
+Could you also add it to the F-Droid repository?
+"""]]
diff --git a/doc/install/ArchLinux/comment_2_e5f923e6d81cfb3fba7a72f60baaf4ab._comment b/doc/install/ArchLinux/comment_2_e5f923e6d81cfb3fba7a72f60baaf4ab._comment
new file mode 100644
index 000000000..9b1f29623
--- /dev/null
+++ b/doc/install/ArchLinux/comment_2_e5f923e6d81cfb3fba7a72f60baaf4ab._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="Stalling when creating repository in assistant"
+ date="2013-09-13T05:09:49Z"
+ content="""
+I am experiencing a weird issue with any install I've had on this one (and only) ArchLinux machine: all of aur/git-annex 4.20130516-1, aur/git-annex-bin-4.20130909-1, aur/git-annex-standalone-4.20130909-1 and a Cabal install just stall when trying to create the initial Git annex repo in the webapp.
+
+When started, it offers me to create the annex in ~/annex/ or ~/Desktop/annex/, where ~ gets turned into /home/USER when I press “Make repository”, but nothing else happens. This is regardless of if that repo exists when I try to create it or start the webapp.
+
+If I start the webapp from an existing annex (now in ~/annex), it seems to work a bit better, but any other remote (SSH) server that I try to add fails. I just get a fleeting Bootstrap message box when I click “Check this server”, and nothing in the logs of eithr git annex webapp or the ssh logs of the server.
+
+Any idea? Where should I look for more debug information?
+.
+
+"""]]
diff --git a/doc/install/ArchLinux/comment_3_8e607cd883ec174571e9dfe3b25bfd05._comment b/doc/install/ArchLinux/comment_3_8e607cd883ec174571e9dfe3b25bfd05._comment
new file mode 100644
index 000000000..48a2888a2
--- /dev/null
+++ b/doc/install/ArchLinux/comment_3_8e607cd883ec174571e9dfe3b25bfd05._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 3"
+ date="2013-09-13T15:35:59Z"
+ content="""
+Please post a [[bug report|bugs]] and start the webapp with the --debug option.
+"""]]
diff --git a/doc/install/ArchLinux/comment_4_a378391dd218859f381c479259dd8fe3._comment b/doc/install/ArchLinux/comment_4_a378391dd218859f381c479259dd8fe3._comment
new file mode 100644
index 000000000..9146da9c8
--- /dev/null
+++ b/doc/install/ArchLinux/comment_4_a378391dd218859f381c479259dd8fe3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://olivier.mehani.name/"
+ nickname="olivier-mehani"
+ subject="comment 4"
+ date="2013-09-16T01:23:58Z"
+ content="""
+Done [0]. Not much debug output, unfortunately...
+
+[0] http://git-annex.branchable.com/bugs/Assistant_stalls_when_adding__47__creating_repo_on_ArchLinux/?updated
+"""]]
diff --git a/doc/install/Debian.mdwn b/doc/install/Debian.mdwn
index 045531b34..c71d4d244 100644
--- a/doc/install/Debian.mdwn
+++ b/doc/install/Debian.mdwn
@@ -7,7 +7,11 @@
sudo apt-get install git-annex
Note: This version does not include support for the [[assistant]].
-The version of git-annex in unstable can be easily installed in wheezy.
+A backport is available with the assistant and other new features.
+
+Follow the instructions to [enable backports](http://backports.debian.org/Instructions/).
+
+ sudo apt-get -t wheezy-backports install git-annex
## Debian 6.0 "squeeze"
diff --git a/doc/install/Debian/comment_14_a34e23d9aa3027012ab1236aa4f7d5cb._comment b/doc/install/Debian/comment_14_a34e23d9aa3027012ab1236aa4f7d5cb._comment
new file mode 100644
index 000000000..86f1d6050
--- /dev/null
+++ b/doc/install/Debian/comment_14_a34e23d9aa3027012ab1236aa4f7d5cb._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="Miles"
+ ip="88.175.62.104"
+ subject="installed git-annex on debian but cannot find it"
+ date="2013-08-19T23:29:24Z"
+ content="""
+I am an absolute beginner when it comes to linux in debian in particular. I installed git-annex via the root terminal, but now I do not know where to find it. I searched for in the file system but could not locate it. Any help is appreciated.
+"""]]
diff --git a/doc/install/Debian/comment_15_20d8271ba3f6cfe3c8849c3d41607630._comment b/doc/install/Debian/comment_15_20d8271ba3f6cfe3c8849c3d41607630._comment
new file mode 100644
index 000000000..6f32c2b0b
--- /dev/null
+++ b/doc/install/Debian/comment_15_20d8271ba3f6cfe3c8849c3d41607630._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk_GWOEjK4Sn4hUB6ofFlE3CNeC7tO56J8"
+ nickname="John"
+ subject="Re: installed git-annex on debian but cannot find it "
+ date="2013-08-20T00:50:28Z"
+ content="""
+@Miles - The command is git annex webapp to bring up the web interface.
+"""]]
diff --git a/doc/install/Fedora/comment_4_93b3402e4c51e1a5c96f907bb528164b._comment b/doc/install/Fedora/comment_4_93b3402e4c51e1a5c96f907bb528164b._comment
new file mode 100644
index 000000000..afdbf1dc1
--- /dev/null
+++ b/doc/install/Fedora/comment_4_93b3402e4c51e1a5c96f907bb528164b._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkJafmCf-sg9_OM0pynFYM3AO4WCgJiaMI"
+ nickname="Michele"
+ subject="installing on fc19"
+ date="2013-10-18T21:05:56Z"
+ content="""
+i share my experience in installing from source on fc19, I must admit these are useful only for haskell novices:
+should cabal complain about missing libffi.so.5 (as it happened to me), do
+
+ yum install compat-libffi
+
+and you'll get the missing library (the shipping version with fc19 is libffi.so.6)
+also: in order for the git annex to be picked up globally or better to end up in the default path i had to:
+
+ cabal install --global
+"""]]
diff --git a/doc/install/Fedora/comment_5_0427e0503764b29e57abf9e97155136b._comment b/doc/install/Fedora/comment_5_0427e0503764b29e57abf9e97155136b._comment
new file mode 100644
index 000000000..df518ea11
--- /dev/null
+++ b/doc/install/Fedora/comment_5_0427e0503764b29e57abf9e97155136b._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://mebus.myopenid.com/"
+ ip="2a01:198:3eb:0:4a5b:39ff:fea4:55b3"
+ subject="Error on Fedora 19"
+ date="2013-10-19T14:57:12Z"
+ content="""
+On Fedora 19, I am getting this error:
+
+http://pastebin.com/raw.php?i=c9SNjbXV
+
+Mebus
+
+
+
+"""]]
diff --git a/doc/install/Fedora/comment_6_1b1b38a79251fe2e8c1e4debbe3bc3c5._comment b/doc/install/Fedora/comment_6_1b1b38a79251fe2e8c1e4debbe3bc3c5._comment
new file mode 100644
index 000000000..ffb6f0605
--- /dev/null
+++ b/doc/install/Fedora/comment_6_1b1b38a79251fe2e8c1e4debbe3bc3c5._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://mebus.myopenid.com/"
+ ip="2a01:198:3eb:0:4a5b:39ff:fea4:55b3"
+ subject="comment 6"
+ date="2013-10-19T15:09:34Z"
+ content="""
+Worked! I forgot to install c2hs.
+
+Mebus
+
+
+"""]]
diff --git a/doc/install/Linux_standalone.mdwn b/doc/install/Linux_standalone.mdwn
index ccebd3798..e8df8adc0 100644
--- a/doc/install/Linux_standalone.mdwn
+++ b/doc/install/Linux_standalone.mdwn
@@ -20,7 +20,8 @@ Warning: This is a last resort. Most Linux users should instead
## autobuilds
-A daily build is also available.
+A daily build is also available, thanks to Mesar Hameed and the University
+of Bath CS department.
* i386: [download tarball](https://downloads.kitenet.net/git-annex/autobuild/i386/git-annex-standalone-i386.tar.gz) ([build logs](https://downloads.kitenet.net/git-annex/autobuild/i386/))
* amd64: [download tarball](https://downloads.kitenet.net/git-annex/autobuild/amd64/git-annex-standalone-amd64.tar.gz) ([build logs](https://downloads.kitenet.net/git-annex/autobuild/amd64/))
@@ -30,4 +31,4 @@ A daily build is also available.
Eskild Hustvedt has contributed a
[gitannex-install](https://github.com/zerodogg/scriptbucket/blob/master/gitannex-install)
script to manage keeping up to date with new releases using the standalone
-built.
+build.
diff --git a/doc/install/OSX.mdwn b/doc/install/OSX.mdwn
index fba44e2a4..84b960e51 100644
--- a/doc/install/OSX.mdwn
+++ b/doc/install/OSX.mdwn
@@ -1,12 +1,13 @@
## git-annex.app
[[!img /assistant/osx-app.png align=right link=/assistant]]
-For easy installation, use the
-[beta release of git-annex.app](https://downloads.kitenet.net/git-annex/OSX/current/).
+For easy installation, use the prebuilt app bundle.
-Be sure to select the build matching your version of OSX.
+* 10.9 Mavericks: [git-annex.dmg.bz2](https://downloads.kitenet.net/git-annex/OSX/current/10.9_Mavericks/git-annex.dmg.bz2)
+* 10.8.2 Mountain Lion: [git-annex.dmg.bz2](https://downloads.kitenet.net/git-annex/OSX/current/10.8.2_Mountain_Lion/git-annex.dmg.bz2) **warning: not being updated any longer**
+* 10.7.5 Lion: [git-annex.dmg.bz2](https://downloads.kitenet.net/git-annex/OSX/current/10.7.5_Lion/git-annex.dmg.bz2)
-If you want to run the [[git-annex_assistant|/assistant]], just
+To run the [[git-annex_assistant|/assistant]], just
install the app, look for the icon, and start it up.
To use git-annex at the command line, you can add
@@ -17,20 +18,17 @@ Alternatively, from the command line you can run
programs bundled inside the app, including not just git-annex, but git, and
several more. Handy if you don't otherwise have git installed.
-This is still a work in progress. See [[/bugs/OSX_app_issues]] for problem
-reports.
-
## autobuilds
[Jimmy Tang](http://www.sgenomics.org/~jtang/) autobuilds
the app for OSX Lion.
-* [autobuild of git-annex.app](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/ref/master/git-annex.dmg.bz2) ([build logs](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/))
+* [autobuild of git-annex.dmg.bz2](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/ref/master/git-annex.dmg.bz2) ([build logs](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/))
* [past builds](http://www.sgenomics.org/~jtang/gitbuilder-git-annex-x00-x86_64-apple-darwin10.8.0-binary/sha1/) -- directories are named from the commitid's
-[[Joey]] autobuilds the app for Mountain Lion.
+[[Joey]] autobuilds the app for Mavericks.
-* [autobuild of git-annex.app](https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mountain-lion/git-annex.dmg.bz2) ([build logs](https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mountain-lion/))
+* [autobuild of git-annex.dmg.bz2](https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks/git-annex.dmg.bz2) ([build logs](https://downloads.kitenet.net/git-annex/autobuild/x86_64-apple-mavericks/))
## using Brew
diff --git a/doc/install/OSX/comment_23_3d82a270dd4b0159f4aab5675166e1e3._comment b/doc/install/OSX/comment_23_3d82a270dd4b0159f4aab5675166e1e3._comment
new file mode 100644
index 000000000..08792aa21
--- /dev/null
+++ b/doc/install/OSX/comment_23_3d82a270dd4b0159f4aab5675166e1e3._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmL8pteP2jbYJUn1M3CbeLDvz2SWAA1wtg"
+ nickname="Kristian"
+ subject="Build failure using Haskel Platform"
+ date="2013-09-15T18:49:01Z"
+ content="""
+I get this error when I try to build git-annex using \"cabal install git-annex\"
+
+ [ 34 of 347] Compiling Utility.Misc ( Utility/Misc.hs, dist/build/git-annex/git-annex-tmp/Utility/Misc.o )
+ [ 35 of 347] Compiling Utility.Process ( Utility/Process.hs, dist/build/git-annex/git-annex-tmp/Utility/Process.o )
+ [ 36 of 347] Compiling Utility.Network ( Utility/Network.hs, dist/build/git-annex/git-annex-tmp/Utility/Network.o )
+ [ 37 of 347] Compiling Utility.SRV ( Utility/SRV.hs, dist/build/git-annex/git-annex-tmp/Utility/SRV.o )
+
+ Utility/SRV.hs:70:54:
+ Couldn't match expected type `Maybe
+ [(Int, Int, Integer, B8.ByteString)]'
+ with actual type `Either
+ dns-1.0.0:Network.DNS.Internal.DNSError
+ [(Int, Int, Int, dns-1.0.0:Network.DNS.Internal.Domain)]'
+ In the third argument of `maybe', namely `r'
+ In the second argument of `($)', namely
+ `maybe [] (orderHosts . map tohosts) r'
+ In a stmt of a 'do' block:
+ return $ maybe [] (orderHosts . map tohosts) r
+ Failed to install git-annex-4.20130909
+ cabal: Error: some packages failed to install:
+ git-annex-4.20130909 failed during the building phase. The exception was:
+ ExitFailure 1
+
+"""]]
diff --git a/doc/install/OSX/comment_24_b9d3563a2cc3d769f27876e028dc344d._comment b/doc/install/OSX/comment_24_b9d3563a2cc3d769f27876e028dc344d._comment
new file mode 100644
index 000000000..4b4bf3eb7
--- /dev/null
+++ b/doc/install/OSX/comment_24_b9d3563a2cc3d769f27876e028dc344d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.128"
+ subject="comment 24"
+ date="2013-09-17T15:56:17Z"
+ content="""
+@Kristian, a new version of the DNS library has caused this. A workaround is to pass `-f-DNS` to the cabal command.
+
+I am in the process of adding support for the new DNS library version in git now.
+
+By the way, please [[file_a_bug|bugs]] if you have a big ugly looking build failure like that, so as to not clutter up this page.
+"""]]
diff --git a/doc/install/OSX/comment_25_db90984062a07576a4777b2d743161f1._comment b/doc/install/OSX/comment_25_db90984062a07576a4777b2d743161f1._comment
new file mode 100644
index 000000000..2a924e8f9
--- /dev/null
+++ b/doc/install/OSX/comment_25_db90984062a07576a4777b2d743161f1._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnyMzZZLS1xGW1raqc_9Md6Ksdkvx5rUJU"
+ nickname="Michael"
+ subject="confusion with bundled programs"
+ date="2013-10-02T21:39:11Z"
+ content="""
+I have fiddled with the fresh (as of Oct 2nd) build of assistant on OS X 10.8.5, and there has been a lot of problems with bundled software
+
+bundled git is an old 1.7.x version which keeps saying in the daemon logs it is too old to honor .gitignores etc
+at the same time I have git 1.8.4 installed through homebrew which works very nicely throughout my system
+
+I also have homebrew-installed gpg2:
+
+$ gpg2 --version
+gpg (GnuPG) 2.0.21
+libgcrypt 1.5.3
+
+(and have briefly experimented with using GPGSuite from gpgtools.org, which kept bailing with invalid autolocate directive in gpg.conf)
+
+however there is some unidentifiable gpg binary bundled with the assistant, which cannot connect to gpg-agent from gpg2, and doesn't work with GPGSuite (see above)
+
+is there a way to completely forgo usage of bundled software and have the webapp use whatever is already available on the system?
+
+"""]]
diff --git a/doc/install/OSX/comment_27_2a60108a440231ba83f5a54b6bcc5488._comment b/doc/install/OSX/comment_27_2a60108a440231ba83f5a54b6bcc5488._comment
new file mode 100644
index 000000000..9a5b9c9c1
--- /dev/null
+++ b/doc/install/OSX/comment_27_2a60108a440231ba83f5a54b6bcc5488._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 27"
+ date="2013-10-16T09:40:23Z"
+ content="""
+The [FSevents framework itself has been around since leopard](http://arstechnica.com/apple/2007/10/mac-os-x-10-5/7/).
+
+[This fsevents wrapper project](https://github.com/rastersize/CDEvents) supports snow leopard and even leopard, maybe it will provide some clues on how it was done.
+
+I'm guessing it would be worth it, [snow leopard is still the most popular OSX as of April](http://www.patentlyapple.com/patently-apple/2013/04/snow-leopard-remains-the-most-popular-version-of-os-x.html). From my own experience, snow leopard is a huge life extender for 2+ year old hardware. Lion just makes them sluggishly painful to use.
+
+Maybe someone could volunteer an SL machine for remote development? Sorry, mine are tied down :(
+"""]]
diff --git a/doc/install/OSX/comment_27_d453510b9bb62072a4c663206c12c8a4._comment b/doc/install/OSX/comment_27_d453510b9bb62072a4c663206c12c8a4._comment
new file mode 100644
index 000000000..cc9b44c1a
--- /dev/null
+++ b/doc/install/OSX/comment_27_d453510b9bb62072a4c663206c12c8a4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 27"
+ date="2013-10-16T15:14:53Z"
+ content="""
+The git-annex assistant uses **file level** FSevents to detect which files have been changed. Would it be possible to make it work with older versions that don't provide file-level events? Probably. The code for BSD kqueue deals with similar limitations in needing to scan the directory to find the files that actually changed. If someone cares about old versions of OSX and wants to do that work I'll happily support you.
+"""]]
diff --git a/doc/install/OSX/comment_28_0970bfd63137ea48701dff6aea1b4bcb._comment b/doc/install/OSX/comment_28_0970bfd63137ea48701dff6aea1b4bcb._comment
new file mode 100644
index 000000000..a672a70c4
--- /dev/null
+++ b/doc/install/OSX/comment_28_0970bfd63137ea48701dff6aea1b4bcb._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="dbus support?"
+ date="2013-10-18T08:24:11Z"
+ content="""
+Hello,
+
+I just compiled git-annex using cabal on OS X, and I see there is no dbus support:
+
+ Assistant/Threads/NetWatcher.hs:26:0:
+ warning: #warning Building without dbus support; will poll for network connection changes
+
+ Assistant/Threads/MountWatcher.hs:33:0:
+ warning: #warning Building without dbus support; will use mtab polling
+
+Is this problematic? I see I can install dbus using homebrew. If I do so, will I have dbus support (after recompiling git-annex)?
+"""]]
diff --git a/doc/install/OSX/comment_29_8622ed56c6a8034c20fb311418d94003._comment b/doc/install/OSX/comment_29_8622ed56c6a8034c20fb311418d94003._comment
new file mode 100644
index 000000000..c0552d9d9
--- /dev/null
+++ b/doc/install/OSX/comment_29_8622ed56c6a8034c20fb311418d94003._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 29"
+ date="2013-10-18T15:58:59Z"
+ content="""
+I think I dragged you out of dev mode for commenting unnecessarily, sorry about that. Apparently, [Lion](http://www.redmondpie.com/os-x-lion-vs-os-x-snow-leopard-head-to-head-performance-showdown/) and [Mountain Lion are fine on older hardware](http://apple.stackexchange.com/questions/58453/will-mountain-lion-make-an-older-computer-run-faster-or-slower). For a while [a daemon cause Lion slowdowns for a day after upgrade](https://discussions.apple.com/message/15719036) for a while, which was enough to cause a reputation.
+"""]]
diff --git a/doc/install/OSX/comment_30_ce58633ef5b2f8f4caa7e626358f33be._comment b/doc/install/OSX/comment_30_ce58633ef5b2f8f4caa7e626358f33be._comment
new file mode 100644
index 000000000..9fcf7aa03
--- /dev/null
+++ b/doc/install/OSX/comment_30_ce58633ef5b2f8f4caa7e626358f33be._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 30"
+ date="2013-10-19T15:31:45Z"
+ content="""
+@Alan you don't need to install dbus on OSX. The polling code will work. On the other hand if you'd like to experiment with installing dbus and report back, perhaps it's worth a try. It's nice when the git-annex assistant can instantly detect when drives are plugged in, and then the network connection changes and react to it. On Linux, dbus gives it that capability.
+"""]]
diff --git a/doc/install/OSX/comment_31_09084a7b3cf06bfa3add0f4991476ffe._comment b/doc/install/OSX/comment_31_09084a7b3cf06bfa3add0f4991476ffe._comment
new file mode 100644
index 000000000..df9134194
--- /dev/null
+++ b/doc/install/OSX/comment_31_09084a7b3cf06bfa3add0f4991476ffe._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="dbus and homebrew"
+ date="2013-10-20T17:25:04Z"
+ content="""
+I'm trying to build git-annex with dbus support, and even though I installed dbus (through homebrew), at the end of compilation I get the warning about \"building without dbus\". Is there something special I need to do for git-annex to see I have installed dbus?
+
+(Also, it tells me at the beginning that I don't have gcrypt, but libgcrypt is installed.)
+"""]]
diff --git a/doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment b/doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment
new file mode 100644
index 000000000..dbb0433f7
--- /dev/null
+++ b/doc/install/OSX/comment_32_a46d8e3e7795b9afb1e1c2be943d12af._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 32"
+ date="2013-10-21T22:47:14Z"
+ content="""
+You probably need to install libdbus dev stuff, and then the haskell dbus library. But it's certianly going to need code changes to make git-annex use dbus in any way on OSX, assuming there are even useful dbus events generated for network connections and drives being mounted on OSX.
+
+It was saying \"gcrypt\" when it meant \"git-remote-gcrypt\".
+"""]]
diff --git a/doc/install/OSX/comment_33_203a36322b3c453c05c8906c64e62e06._comment b/doc/install/OSX/comment_33_203a36322b3c453c05c8906c64e62e06._comment
new file mode 100644
index 000000000..7e2853a4e
--- /dev/null
+++ b/doc/install/OSX/comment_33_203a36322b3c453c05c8906c64e62e06._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://alan.petitepomme.net/"
+ nickname="Alan Schmitt"
+ subject="comment 33"
+ date="2013-10-23T11:39:51Z"
+ content="""
+I installed the haskell DBus library, but it's still not picking it up. Is there some additional option to pass to cabal, or is it supposed to find it automatically?
+"""]]
diff --git a/doc/install/OSX/comment_34_c9362141d15a2f68a75df9f8bfe29da0._comment b/doc/install/OSX/comment_34_c9362141d15a2f68a75df9f8bfe29da0._comment
new file mode 100644
index 000000000..65a7e0ea7
--- /dev/null
+++ b/doc/install/OSX/comment_34_c9362141d15a2f68a75df9f8bfe29da0._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl-xMSPoRHcT5d2nAc1K8pWVi-AexKkYik"
+ nickname="Ralf"
+ subject="Mac OS X Maverick - symbol not found"
+ date="2013-10-27T21:02:45Z"
+ content="""
+Just to mention that the beta dated 24 Oct 2013 and Joey's autobuild of 27 Oct both don't start with the following error message for git-annex, git-annex-webapp under Mac OS X 10.9 Maverick with latest XCode installed:
+
+ dyld: Symbol not found: _objc_debug_taggedpointer_mask
+ Referenced from: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+ Expected in: /Applications/git-annex.app/Contents/MacOS/bundle/I
+ in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
+
+ Trace/BPT trap: 5
+
+Many thanks. Can I help?
+"""]]
diff --git a/doc/install/OSX/comment_35_8106196c3fef70652cb2106e2d5857db._comment b/doc/install/OSX/comment_35_8106196c3fef70652cb2106e2d5857db._comment
new file mode 100644
index 000000000..697dafa0b
--- /dev/null
+++ b/doc/install/OSX/comment_35_8106196c3fef70652cb2106e2d5857db._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 35"
+ date="2013-10-27T21:06:57Z"
+ content="""
+We do not yet have an autobuild for 10.9. You can build from source: <http://git-annex.branchable.com/bugs/git_annex_doesn__39__t_work_in_Max_OS_X_10.9/#comment-8e8ee5e50506a6fde029d236f4809df8>
+"""]]
diff --git a/doc/install/Ubuntu.mdwn b/doc/install/Ubuntu.mdwn
index 107a1a8e7..61b1489ff 100644
--- a/doc/install/Ubuntu.mdwn
+++ b/doc/install/Ubuntu.mdwn
@@ -1,7 +1,17 @@
-## Saucy, Raring
+## Saucy
sudo apt-get install git-annex
+Warning: The version of git-annex shipped in Ubuntu Saucy had
+[a bug that can cause problems when creating repositories using the webapp](http://git-annex.branchable.com/bugs/Freshly_initialized_repo_has_staged_change___34__deleted:_uuid.log__34__/).
+
+## Raring
+
+ sudo apt-get install git-annex
+
+Note: This version is too old to include the [[assistant]] or its WebApp,
+but is otherwise usable.
+
## Precise
sudo apt-get install git-annex
diff --git a/doc/install/Ubuntu/comment_10_490e065314693423ab6969d8ae6978fe._comment b/doc/install/Ubuntu/comment_10_490e065314693423ab6969d8ae6978fe._comment
new file mode 100644
index 000000000..d598adfba
--- /dev/null
+++ b/doc/install/Ubuntu/comment_10_490e065314693423ab6969d8ae6978fe._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkdiXn5s1wX2Zncy1S7_h-yPTv2gt0bmmY"
+ nickname="Jacob"
+ subject="comment 10"
+ date="2013-10-16T11:43:36Z"
+ content="""
+would be great to get the PPA updated with the latest git-annex; i'm finding synchronisation bugs (ie. updates made to word documents aren't replicated), and discovered its rather old now.
+"""]]
diff --git a/doc/install/Ubuntu/comment_11_4ebac3fb43de854ed1a3b1d2ea94011a._comment b/doc/install/Ubuntu/comment_11_4ebac3fb43de854ed1a3b1d2ea94011a._comment
new file mode 100644
index 000000000..68a889176
--- /dev/null
+++ b/doc/install/Ubuntu/comment_11_4ebac3fb43de854ed1a3b1d2ea94011a._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="fmarier"
+ ip="207.134.53.206"
+ subject="Re: comment 10"
+ date="2013-10-16T13:43:37Z"
+ content="""
+Jacob: make sure you have the right URL for the PPA: https://launchpad.net/~fmarier/+archive/git-annex
+
+It used to be in my main PPA, now it's in a separate PPA by itself. The package was removed from the original PPA (hence it won't update) but is fully up to date in the new one.
+"""]]
diff --git a/doc/install/Ubuntu/comment_12_38f69dffe2db0d15e4c4e5cb47f40ef8._comment b/doc/install/Ubuntu/comment_12_38f69dffe2db0d15e4c4e5cb47f40ef8._comment
new file mode 100644
index 000000000..7cbf8c0ae
--- /dev/null
+++ b/doc/install/Ubuntu/comment_12_38f69dffe2db0d15e4c4e5cb47f40ef8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="Raring?"
+ date="2013-11-01T20:28:04Z"
+ content="""
+I'm also on Raring and the latest version available is 3.20121112ubuntu4, nearly a year old. The PPA is only for Precise. The tarball is a daily snapshot, and I would much rather run a released version right now. What can I do? Can't the PPA be built automatically for Raring and Saucy?
+"""]]
diff --git a/doc/install/Ubuntu/comment_9_c2f8b35ada873acb1ce593b04e2899fe._comment b/doc/install/Ubuntu/comment_9_c2f8b35ada873acb1ce593b04e2899fe._comment
new file mode 100644
index 000000000..828b80e39
--- /dev/null
+++ b/doc/install/Ubuntu/comment_9_c2f8b35ada873acb1ce593b04e2899fe._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="https://openid.stackexchange.com/user/2eeca722-8d1c-41fe-8fda-13af7eaff6ae"
+ nickname="Diggory"
+ subject="Outdated in 13.04"
+ date="2013-10-08T16:36:10Z"
+ content="""
+13.04 Raring also has fairly outdated packages: 3.20121112ubuntu4
+Is there a PPA or some such for this? I suppose since Saucy will be out soon this is less critical, but would still be useful.
+
+These don't have direct mode, which (I think; I haven't tested it yet) is the feature I've been waiting for.
+"""]]
diff --git a/doc/install/Windows.mdwn b/doc/install/Windows.mdwn
index c327d11ca..74017d699 100644
--- a/doc/install/Windows.mdwn
+++ b/doc/install/Windows.mdwn
@@ -26,7 +26,8 @@ A daily build is also available, thanks to Yury V. Zaytsev and
To build git-annex from source on Windows, you need to install
the Haskell Platform, Mingw, and Cygwin. Use Cygwin to install
-gcc, rsync, git, wget, ssh, and gpg.
+gcc, rsync, git, wget, ssh, and gnupg. To build the git-annex installer,
+you also need to install the NulSoft installer system.
There is a shell script `standalone/windows/build.sh` that can be
used to build git-annex. Note that this shell script cannot be run
diff --git a/doc/install/cabal.mdwn b/doc/install/cabal.mdwn
index 6c5c0d4c6..3270dd0f9 100644
--- a/doc/install/cabal.mdwn
+++ b/doc/install/cabal.mdwn
@@ -1,4 +1,14 @@
-As a haskell package, git-annex can be installed using cabal.
+As a haskell package, git-annex can be installed using cabal.
+
+This involves building a lot of haskell packages from source, and so it has
+a lot of moving parts, and it's not uncommon for it to be broken from time
+to time.
+
+If you are not comfortable tracking down and dealing with library build
+problems, installing git-annex with cabal is probably not the right choice
+for you!
+
+## prerequisites
Start by installing the [Haskell Platform][]. In Debian, this is as
simple as:
@@ -40,3 +50,9 @@ you want, and use cabal as follows inside its source tree:
cabal configure
cabal build
cabal install --bindir=$HOME/bin
+
+## EKG
+
+When building with cabal, you can optionally enable the
+[[EKG monitoring interface|ekg]]. This is great for debugging resource
+usage problems.
diff --git a/doc/install/cabal/comment_12_b93ca271dffca3f948645d3e1326c1d9._comment b/doc/install/cabal/comment_12_b93ca271dffca3f948645d3e1326c1d9._comment
new file mode 100644
index 000000000..8d9c97898
--- /dev/null
+++ b/doc/install/cabal/comment_12_b93ca271dffca3f948645d3e1326c1d9._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 12"
+ date="2013-08-07T16:31:30Z"
+ content="""
+The Linux standalone builds for i386 and amd64 will not work on Arm systems.
+
+There are builds of git-annex for arm in eg, Debian. You should be able to use one of those if this system is running Debian. You may need to upgrade to eg, Debian stable, which includes git-annex.
+
+It looks like you have an old and/or broken GHC compiler too. You could upgrade that to a newer version (eg from Debian stable) and build it that way, but it seems like the long way around if you have a Debian system there.
+"""]]
diff --git a/doc/install/cabal/comment_13_3dac019cda71bf99878c0a1d9382323b._comment b/doc/install/cabal/comment_13_3dac019cda71bf99878c0a1d9382323b._comment
new file mode 100644
index 000000000..80e3a6ad1
--- /dev/null
+++ b/doc/install/cabal/comment_13_3dac019cda71bf99878c0a1d9382323b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlXEIT2PEAuHuInLP4UYVzWE0lceMYd2lA"
+ nickname="Gregor"
+ subject="TonidoPlug"
+ date="2013-08-09T17:46:28Z"
+ content="""
+@Joey Thanks for the answer. I didn't want to mess around too much with the TonidoPlug. I am currently setting up a raspberry pi, which works fine.
+"""]]
diff --git a/doc/install/cabal/comment_14_14b46470593f84f8c3768a91cb77bdab._comment b/doc/install/cabal/comment_14_14b46470593f84f8c3768a91cb77bdab._comment
new file mode 100644
index 000000000..93fca1653
--- /dev/null
+++ b/doc/install/cabal/comment_14_14b46470593f84f8c3768a91cb77bdab._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlfIVXjkzrYE9qJAO2A0H7K6tKGMaSgc3U"
+ nickname="Daniel"
+ subject="Problems with cryptocipher"
+ date="2013-08-22T01:36:50Z"
+ content="""
+I had problems following these directions on recent releases of Fedora/Ubuntu. The install attempts failed on cryptocipher-0.3.1, which I think came as a dependency of Yesod.
+I was able to work around this by installing yesod-platform with cabal first, then installing git-annex.
+"""]]
diff --git a/doc/install/cabal/comment_15_c3a5b0aad28a90e0bb8da31a430578eb._comment b/doc/install/cabal/comment_15_c3a5b0aad28a90e0bb8da31a430578eb._comment
new file mode 100644
index 000000000..fc64af234
--- /dev/null
+++ b/doc/install/cabal/comment_15_c3a5b0aad28a90e0bb8da31a430578eb._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="77.247.181.162"
+ subject="git-annex assistant on Arm"
+ date="2013-08-23T03:07:11Z"
+ content="""
+I'd like to use the assistant's power on a Raspberry Pi to build an always-on file/sync server. Is there a way to get the assistant running on Arm? I know there's a Debian package, but it's Version 3.20120629 and comes without the assistant. Has anyone ever successfully built a recent git-annex version on Arm? What would I need in order to do it myself?
+"""]]
diff --git a/doc/install/cabal/comment_16_4faf214f97f9516898d7c17d743ef825._comment b/doc/install/cabal/comment_16_4faf214f97f9516898d7c17d743ef825._comment
new file mode 100644
index 000000000..be14b3908
--- /dev/null
+++ b/doc/install/cabal/comment_16_4faf214f97f9516898d7c17d743ef825._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 16"
+ date="2013-08-23T17:37:52Z"
+ content="""
+The git-annex assistant can easily be built on arm. But not the webapp. It's entirely possible to use the assistant without the webapp though; you just have to make the git repository and configure the remotes by hand, and then the assistant will sync them the same way the webapp does.
+
+It is possible but very involved to build the webapp for arm. I do not anticipate doing it in the Debian package until ghc gets proper template haskell support for arm. See [[forum/Webapp_on_ARM]]
+"""]]
diff --git a/doc/install/cabal/comment_17_2a9d6807a3a13815c824985521757167._comment b/doc/install/cabal/comment_17_2a9d6807a3a13815c824985521757167._comment
new file mode 100644
index 000000000..c0b570dfb
--- /dev/null
+++ b/doc/install/cabal/comment_17_2a9d6807a3a13815c824985521757167._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="77.247.181.162"
+ subject="comment 17"
+ date="2013-08-23T18:51:51Z"
+ content="""
+Thanks for the quick answer. I will try to build git-annex with just the assistant, as you suggest, and once it works set up the server by hand as you suggest.
+
+BTW: Awesome job you're doing with git-annex. I appreciate your enthusiasm.
+"""]]
diff --git a/doc/install/cabal/comment_18_1efa0c7a963ec452fc6336fbe4964f6e._comment b/doc/install/cabal/comment_18_1efa0c7a963ec452fc6336fbe4964f6e._comment
new file mode 100644
index 000000000..e3a523e22
--- /dev/null
+++ b/doc/install/cabal/comment_18_1efa0c7a963ec452fc6336fbe4964f6e._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="96.47.226.20"
+ subject="git-annex assistant for the Raspberry Pi"
+ date="2013-09-04T03:58:37Z"
+ content="""
+It took a while and a few tries, but I finally built the git-annex binary including the assistant on a Raspberry Pi. The build comes without the flags webapp, webdav, and dbus as these rely on a Template Haskell compiler that hasn't been ported to Arm architecture yet.
+
+I put the binary up on Github in case anyone's interested: <https://github.com/tradloff/git-annex-RPi>
+"""]]
diff --git a/doc/install/cabal/comment_19_6f42f9234f9ff6a2ca6bbb4d2643843e._comment b/doc/install/cabal/comment_19_6f42f9234f9ff6a2ca6bbb4d2643843e._comment
new file mode 100644
index 000000000..27a3e8c62
--- /dev/null
+++ b/doc/install/cabal/comment_19_6f42f9234f9ff6a2ca6bbb4d2643843e._comment
@@ -0,0 +1,44 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlu7K3h7Ry1uDAU_ERYGuqt0LoGNJqGuRo"
+ nickname="Nathan"
+ subject="Cabal installing git-annex on Ubuntu 12.04 Precise with GHC 7.6.3"
+ date="2013-09-25T22:39:04Z"
+ content="""
+I now realize [there is a Ubuntu 12.04 Precise PPA with a current
+version of
+git-annex](http://git-annex.branchable.com/install/Ubuntu/), so that's
+probably a better choice, but here's how I cabal isntalled git-annex.
+
+1. Apt install non-cabal dependencies:
+
+ sudo aptitude install c2hs libgsasl7-dev libxml2-dev
+
+2. Manually cabal install yesod-platform to avoid the [cryptocipher problem
+ mentioned above](
+ http://git-annex.branchable.com/install/cabal/#comment-1807da37dc144b572b76aaf4b574bb54):
+
+ cabal install yesod-platform
+
+3. Cabal install git-annex with DNS flag disabled:
+
+ cabal install git-annex -f\"-dns\"
+
+I was getting this error building git-annex before disabling the DNS flag:
+
+ Utility/SRV.hs:70:54:
+ Couldn't match expected type `Maybe
+ [(Int, Int, Integer, B8.ByteString)]'
+ with actual type `Either
+ dns-1.0.0:Network.DNS.Internal.DNSError
+ [(Int, Int, Int, dns-1.0.0:Network.DNS.Internal.Domain)]'
+ In the third argument of `maybe', namely `r'
+ In the second argument of `($)', namely
+ `maybe [] (orderHosts . map tohosts) r'
+ In a stmt of a 'do' block:
+ return $ maybe [] (orderHosts . map tohosts) r
+
+Looking at Utiltity/SRV.hs, it appears that disabling the DNS flag
+just makes git annex use a different DNS library (ADNS), not
+actually disable DNS lookups.
+
+"""]]
diff --git a/doc/install/cabal/comment_20_0f553be2a4c666e3bed58b2bce549406._comment b/doc/install/cabal/comment_20_0f553be2a4c666e3bed58b2bce549406._comment
new file mode 100644
index 000000000..288c0e017
--- /dev/null
+++ b/doc/install/cabal/comment_20_0f553be2a4c666e3bed58b2bce549406._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlkA6XinbeOdnEDxEGQUWyjqPGh0kdMXr4"
+ nickname="Blake"
+ subject="Updating git-annex via cabal"
+ date="2013-10-09T21:21:22Z"
+ content="""
+What is the best way to update git-annex and the dependencies via cabal? Just the `$ cabal install *` commands again?
+"""]]
diff --git a/doc/install/cabal/comment_21_f91a6ec21e96eced73ea9579fd8cbd15._comment b/doc/install/cabal/comment_21_f91a6ec21e96eced73ea9579fd8cbd15._comment
new file mode 100644
index 000000000..ef8a3d2a3
--- /dev/null
+++ b/doc/install/cabal/comment_21_f91a6ec21e96eced73ea9579fd8cbd15._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 21"
+ date="2013-10-11T17:09:33Z"
+ content="""
+If you run the \"cabal update\" command followed by the \"cabal install\" command it'll upgrade git-annex.
+"""]]
diff --git a/doc/install/cabal/comment_22_2f27b78215f97ade1986ca806c634cb3._comment b/doc/install/cabal/comment_22_2f27b78215f97ade1986ca806c634cb3._comment
new file mode 100644
index 000000000..d7ff05617
--- /dev/null
+++ b/doc/install/cabal/comment_22_2f27b78215f97ade1986ca806c634cb3._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="96.44.189.100"
+ subject="&quot;Could not find module Crypto.Hash&quot; error when building git-annex "
+ date="2013-10-21T19:55:12Z"
+ content="""
+Lately I get this error message when trying to build git-annex-v4.20131002:
+
+ Utility/Hash.hs:7:8:
+ Could not find module `Crypto.Hash'
+ Perhaps you meant
+ Crypto.HMAC (needs flag -package crypto-api-0.10.2)
+ Use -v to see a list of the files searched for.
+
+crypto-api-0.10.2 is installed as a debian dev package. All the dependencies are met. I have no idea what's going on.
+"""]]
diff --git a/doc/install/cabal/comment_23_c34d2b1d95830a3e58671a5b566a1758._comment b/doc/install/cabal/comment_23_c34d2b1d95830a3e58671a5b566a1758._comment
new file mode 100644
index 000000000..03a5b87ce
--- /dev/null
+++ b/doc/install/cabal/comment_23_c34d2b1d95830a3e58671a5b566a1758._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 23"
+ date="2013-10-21T22:09:05Z"
+ content="""
+git-annex needs cryptohash version 0.10.0 or greater. You appear to have an old version. You can cabal `configure -f-CryptoHash` if it's for some reason failing to disable the cryptohash support despite the declared dependency not being met.
+"""]]
diff --git a/doc/install/cabal/comment_24_40cbde8ec067b3a860e6df1a9bea5f76._comment b/doc/install/cabal/comment_24_40cbde8ec067b3a860e6df1a9bea5f76._comment
new file mode 100644
index 000000000..3bb160546
--- /dev/null
+++ b/doc/install/cabal/comment_24_40cbde8ec067b3a860e6df1a9bea5f76._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="37.130.227.133"
+ subject="comment 24"
+ date="2013-10-22T17:55:32Z"
+ content="""
+I fixed the error by installing a newer version of cryptohash. Thanks for pointing out the culprit.
+"""]]
diff --git a/doc/install/cabal/comment_25_8a7664e6f9271718dc607a0782366c5b._comment b/doc/install/cabal/comment_25_8a7664e6f9271718dc607a0782366c5b._comment
new file mode 100644
index 000000000..929956ede
--- /dev/null
+++ b/doc/install/cabal/comment_25_8a7664e6f9271718dc607a0782366c5b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="141.138.141.208"
+ subject="Bad version on Hackage"
+ date="2013-10-30T18:56:25Z"
+ content="""
+Quick note: The latest version in the Hackage repository (git-annex-4.20131024) fails to build, due to a faulty version of Assistant/Threads/Cronner.hs.
+"""]]
diff --git a/doc/install/cabal/comment_26_bd455c732639728bce2bfc39e32871d2._comment b/doc/install/cabal/comment_26_bd455c732639728bce2bfc39e32871d2._comment
new file mode 100644
index 000000000..5b1f06023
--- /dev/null
+++ b/doc/install/cabal/comment_26_bd455c732639728bce2bfc39e32871d2._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 26"
+ date="2013-11-01T16:33:25Z"
+ content="""
+@RaspberryPie that only affected builds without the webapp, in any case it's fixed now.
+"""]]
diff --git a/doc/install/cabal/comment_27_c080e9239b6eec88d329c28da7bb4141._comment b/doc/install/cabal/comment_27_c080e9239b6eec88d329c28da7bb4141._comment
new file mode 100644
index 000000000..4c007c9ad
--- /dev/null
+++ b/doc/install/cabal/comment_27_c080e9239b6eec88d329c28da7bb4141._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="37.221.160.203"
+ subject="comment 27"
+ date="2013-11-02T12:52:18Z"
+ content="""
+Okay, the error doesn't show up anymore. I didn't even get to Cronner though, because this time I got a different error:
+
+ Assistant/Alert.hs:195:20:
+ Couldn't match expected type `Assistant ()' with actual type `()'
+ Expected type: Maybe Remote -> Assistant ()
+ Actual type: Maybe Remote -> ()
+ In the expression: noop
+ In an equation for `notFsckedNudge': notFsckedNudge _ = noop
+
+This is from trying to compile 4.20131101 with `-f\"-webapp -webdav\"`
+"""]]
diff --git a/doc/install/cabal/comment_28_15951dd070a675300420eea137a28ef9._comment b/doc/install/cabal/comment_28_15951dd070a675300420eea137a28ef9._comment
new file mode 100644
index 000000000..19a570cae
--- /dev/null
+++ b/doc/install/cabal/comment_28_15951dd070a675300420eea137a28ef9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 28"
+ date="2013-11-02T17:40:18Z"
+ content="""
+Unfortunate about that. I've fixed it in git.
+
+(It would be best to file bug reports about build failures to avoid cluttering up this page.)
+"""]]
diff --git a/doc/install/fromscratch.mdwn b/doc/install/fromscratch.mdwn
index 63d4b1cbb..ae9065cd0 100644
--- a/doc/install/fromscratch.mdwn
+++ b/doc/install/fromscratch.mdwn
@@ -7,10 +7,12 @@ quite a lot.
* [MissingH](http://github.com/jgoerzen/missingh/wiki)
* [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)
@@ -22,6 +24,7 @@ quite a lot.
* [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)
* Optional haskell stuff, used by the [[assistant]] and its webapp
* [stm](http://hackage.haskell.org/package/stm)
(version 2.3 or newer)
@@ -46,7 +49,6 @@ quite a lot.
* [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)
- * [async](http://hackage.haskell.org/package/async)
* [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)
@@ -61,6 +63,8 @@ quite a lot.
* [gpg](http://gnupg.org/) (optional; needed for encryption)
* [lsof](ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/)
(optional; recommended for watch mode)
+ * [gcrypt](https://github.com/joeyh/git-remote-gcrypt)
+ (optional)
* multicast DNS support, provided on linux by [nss-mdns](http://www.0pointer.de/lennart/projects/nss-mdns/)
(optional; recommended for the assistant to support pairing well)
* [ikiwiki](http://ikiwiki.info) (optional; used to build the docs)
diff --git a/doc/install/openSUSE.mdwn b/doc/install/openSUSE.mdwn
index 27de5c60e..760def98c 100644
--- a/doc/install/openSUSE.mdwn
+++ b/doc/install/openSUSE.mdwn
@@ -1,3 +1,3 @@
-Haskell Platform 2012.4 is now [officially available for openSUSE](http://software.opensuse.org/package/haskell-platform) via 1-Click Install.
+Haskell Platform is now [officially available for openSUSE](http://software.opensuse.org/package/haskell-platform) via 1-Click Install.
-At the time of writing, there are [unofficial packages of git-annex](http://software.opensuse.org/package/git-annex) available for openSUSE 12.2. It should also be possible to build it via cabal or from source as described on the [[install]] page.
+At the time of writing, there are [unofficial packages of git-annex](http://software.opensuse.org/package/git-annex) available for openSUSE. It should also be possible to build it via cabal or from source as described on the [[install]] page.
diff --git a/doc/internals.mdwn b/doc/internals.mdwn
index 84d9bcb50..b508c3348 100644
--- a/doc/internals.mdwn
+++ b/doc/internals.mdwn
@@ -16,7 +16,7 @@ Each subdirectory has the [[name_of_a_key|key_format]] in one of the
[[key-value_backends|backends]]. The file inside also has the name of the key.
This two-level structure is used because it allows the write bit to be removed
from the subdirectories as well as from the files. That prevents accidentially
-deleting or changing the file contents.
+deleting or changing the file contents. See [[permissions]] for details.
In [[direct_mode]], file contents are not stored in here, and instead
are stored directly in the file. However, the same symlinks are still
diff --git a/doc/internals/lockdown.mdwn b/doc/internals/lockdown.mdwn
new file mode 100644
index 000000000..a7775cd3a
--- /dev/null
+++ b/doc/internals/lockdown.mdwn
@@ -0,0 +1,44 @@
+Object files stored in `.git/annex/objects` are each put in their own directory.
+This allows the write bit to be removed from both the file, and its directory,
+which prevents accidentially deleting or changing the file contents.
+
+The reasoning for doing this follows:
+
+Normally with git, once you have committed a file, editing the file in the
+working tree cannot cause you to lose the committed version. This is an
+important property of git. Of course you can `rm -rf .git` and delete
+commits if you like (before you've pushed them). But you can't lose a
+committed version of the file because of something you do with the working
+tree version.
+
+It's easy for git to do this, because committing a file makes a copy of it.
+But git-annex does not make a local copy of a file added to it, because
+the file could be very large.
+
+So, it's important for git-annex to find another way to preserve the expected
+property that once committed, you cannot accidentially lose a file.
+The most important protection it makes is just to remove the write bit of
+the file. Thus preventing programs from modifying it.
+
+But, that does not prevent any program that might follow the symlink and
+delete the symlinked file. This might seem an unlikely thing for a program to
+do at first, but consider a command like:
+`tar cf foo.tar foo --remove-files --dereference`
+
+When I tested this, I didn't know if it would remove the file foo symlinked
+to or not! It turned out that my tar doesn't remove it. But it could
+have easily went the other way.
+
+Rather than needing to worry about every possible program that might
+decide to do something like this, git-annex removes the write bit from the
+directory containing the annexed object, as well as removing the write
+bit from the file. (The only bad consequence of this is that `rm -rf .git`
+doesn't work unless you first run `chmod -R +w .git`)
+
+----
+
+It's known that this lockdown mechanism is incomplete. The worst hole in
+it is that if you explicitly run `chmod +w` on an annexed file in the working
+tree, this follows the symlink and allows writing to the file. It would be
+better to make the files fully immutable. But most systems either don't
+support immutable attributes, or only let root make files immutable.
diff --git a/doc/news/git_annex_fall_of_code.mdwn b/doc/news/git_annex_fall_of_code.mdwn
new file mode 100644
index 000000000..79e0ff690
--- /dev/null
+++ b/doc/news/git_annex_fall_of_code.mdwn
@@ -0,0 +1,27 @@
+Thanks to my recent successful git-annex
+[crowdfunding campaign](http://campaign.joeyh.name/), $1000 has been set
+aside to award others for their contributions to git-annex by
+the end of 2013. This is not a lot of money, but I hope that the
+reward and recognition will encourage some more people to work on git-annex.
+
+You don't need to know Haskell! You could contribute some interesting and
+useful special remote hooks, or write better documentation.
+
+On the other hand, if you have learned Haskell, this might be your first
+chance to make some money with it! Some ideas for things to work on that
+would be particularly award-worthy:
+
+* Port git-annex to IOS, using [ghc-ios](https://github.com/ghc-ios).
+ I don't plan to ever do this myself, but you could make it happen.
+* Get the git-annex assistant working in Windows, building on the existing
+ port to Windows. Otherwise, this is on my roadmap for February.
+* Solve existing [[bugs]] or [[todo]] items. There are more than I can
+ keep up with.
+
+The amount of the awards will vary depending on the size of the
+contribution. Since this is getting started later than is ideal,
+I reserve the right to extend it past the end of the year if I don't get
+enough participants.
+
+If you'd like to participate in this program, just email me at
+<id@joeyh.name>. --[[Joey]]
diff --git a/doc/news/version_4.20130621.mdwn b/doc/news/version_4.20130621.mdwn
deleted file mode 100644
index 57694b2e5..000000000
--- a/doc/news/version_4.20130621.mdwn
+++ /dev/null
@@ -1,40 +0,0 @@
-git-annex 4.20130621 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * Supports indirect mode on encfs in paranoia mode, and other
- filesystems that do not support hard links, but do support
- symlinks and other POSIX filesystem features.
- * Android: Add .thumbnails to .gitignore when setting up a camera
- repository.
- * Android: Make the "Open webapp" menu item open the just created
- repository when a new repo is made.
- * webapp: When the user switches to display a different repository,
- that repository becomes the default repository to be displayed next time
- the webapp gets started.
- * glacier: Better handling of the glacier inventory, which avoids
- duplicate uploads to the same glacier repository by `git annex copy`.
- * Direct mode: No longer temporarily remove write permission bit of files
- when adding them.
- * sync: Better support for bare git remotes. Now pushes directly to the
- master branch on such a remote, instead of to synced/master. This
- makes it easier to clone from a bare git remote that has been populated
- with git annex sync or by the assistant.
- * Android: Fix use of cp command to not try to use features present
- only on build system.
- * Windows: Fix hang when adding several files at once.
- * assistant: In direct mode, objects are now only dropped when all
- associated files are unwanted. This avoids a repreated drop/get loop
- of a file that has a copy in an archive directory, and a copy not in an
- archive directory. (Indirect mode still has some buggy behavior in this
- area, since it does not keep track of associated files.)
- Closes: #[712060](http://bugs.debian.org/712060)
- * status: No longer shows dead repositories.
- * annex.debug can now be set to enable debug logging by default.
- The webapp's debugging check box does this.
- * fsck: Avoid getting confused by Windows path separators
- * Windows: Multiple bug fixes, including fixing the data written to the
- git-annex branch.
- * Windows: The test suite now passes on Windows (a few broken parts are
- disabled).
- * assistant: On Linux, the expensive transfer scan is run niced.
- * Enable assistant and WebDAV support on powerpc and sparc architectures,
- which now have the necessary dependencies built."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20130627.mdwn b/doc/news/version_4.20130627.mdwn
deleted file mode 100644
index 85cdf5905..000000000
--- a/doc/news/version_4.20130627.mdwn
+++ /dev/null
@@ -1,17 +0,0 @@
-git-annex 4.20130627 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * assistant --autostart: Automatically ionices the daemons it starts.
- * assistant: Daily sanity check thread is run niced.
- * bup: Handle /~/ in bup remote paths.
- Thanks, Oliver Matthews
- * fsck: Ensures that direct mode is used for files when it's enabled.
- * webapp: Fix bug when setting up a remote ssh repo repeatedly on the same
- server.
- * webapp: Ensure that ssh keys generated for different directories
- on a server are always different.
- * webapp: Fix bug setting up ssh repo if the user enters "~/" at the start
- of the path.
- * assistant: Fix bug that prevented adding files written by gnucash,
- and more generally support adding hard links to files. However,
- other operations on hard links are still unsupported.
- * webapp: Fix bug that caused the webapp to hang when built with yesod 1.2."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20130709.mdwn b/doc/news/version_4.20130709.mdwn
deleted file mode 100644
index a78d3a506..000000000
--- a/doc/news/version_4.20130709.mdwn
+++ /dev/null
@@ -1,35 +0,0 @@
-git-annex 4.20130709 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * --all: New switch that makes git-annex operate on all data stored
- in the git annex, including old versions of files. Supported by
- fsck, get, move, copy.
- * --unused: New switch that makes git-annex operate on all data found
- by the last run of git annex unused. Supported by fsck, get, move, copy.
- * get, move, copy: Can now be run in a bare repository,
- like fsck already could. --all is enabled automatically in this case.
- * merge: Now also merges synced/master or similar branches, which
- makes it useful to put in a post-receive hook to make a repository
- automatically update its working copy when git annex sync or the assistant
- sync with it.
- * webapp: Fix ssh setup with nonstandard port, broken in last release.
- * init: Detect systems on which git commit fails due to not being able to
- determine the FQDN, and put in a workaround so committing to the git-annex
- branch works.
- * addurl --pathdepth: Fix failure when the pathdepth specified is deeper
- than the urls's path.
- * Windows: Look for .exe extension when searching for a command in path.
- * Pass -f to curl when downloading a file with it, so it propigates failure.
- * Windows: Fix url to object when using a http remote.
- * webapp: Fix authorized\_keys line added when setting up a rsync remote
- on a server that also supports git-annex, to not force running
- git-annex-shell.
- * OSX Mountain Lion: Fixed gpg bundled in dmg to not fail due to a missing
- gpg-agent.
- * Android: gpg is built without --enable-minimal, so it interoperates
- better with other gpg builds that may default to using other algorithms
- for encryption.
- * dropunused, addunused: Complain when asked to operate on a number that
- does not correspond to any unused key.
- * fsck: Don't claim to fix direct mode when run on a symlink whose content
- is not present.
- * Make --numcopies override annex.numcopies set in .gitattributes."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20130723.mdwn b/doc/news/version_4.20130723.mdwn
deleted file mode 100644
index b15f1a517..000000000
--- a/doc/news/version_4.20130723.mdwn
+++ /dev/null
@@ -1,36 +0,0 @@
-git-annex 4.20130723 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * Fix data loss bug when adding an (uncompressed) tarball of a
- git-annex repository, or other file that begins with something
- that can be mistaken for a git-annex link. Closes: #[717456](http://bugs.debian.org/717456)
- * New improved version of the git-annex logo, contributed by
- John Lawrence.
- * Rsync.net have committed to support git-annex and offer a special
- discounted rate for git-annex users. Updated the webapp to reflect this.
- http://www.rsync.net/products/git-annex-pricing.html
- * Install XDG desktop icon files.
- * Support unannex and uninit in direct mode.
- * Support import in direct mode.
- * webapp: Better display of added files.
- * fix: Preserve the original mtime of fixed symlinks.
- * uninit: Preserve .git/annex/objects at the end, if it still
- has content, so that old versions of files and deleted files
- are not deleted. Print a message with some suggested actions.
- * When a transfer is already being run by another process,
- proceed on to the next file, rather than dying.
- * Fix checking when content is present in a non-bare repository
- accessed via http.
- * Display byte sizes with more precision.
- * watcher: Fixed a crash that could occur when a directory was renamed
- or deleted before it could be scanned.
- * watcher: Partially worked around a bug in hinotify, no longer crashes
- if hinotify cannot process a directory (but can't detect changes in it)
- * directory special remote: Fix checking that there is enough disk space
- to hold an object, was broken when using encryption.
- * webapp: Differentiate between creating a new S3/Glacier/WebDav remote,
- and initializing an existing remote. When creating a new remote, avoid
- conflicts with other existing (or deleted) remotes with the same name.
- * When an XMPP server has SRV records, try them, but don't then fall
- back to the regular host if they all fail.
- * For long hostnames, use a hash of the hostname to generate the socket
- file for ssh connection caching."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20130802.mdwn b/doc/news/version_4.20130802.mdwn
deleted file mode 100644
index 47605010d..000000000
--- a/doc/news/version_4.20130802.mdwn
+++ /dev/null
@@ -1,44 +0,0 @@
-git-annex 4.20130802 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * dropunused behavior change: Now refuses to drop the last copy of a
- file, unless you use the --force.
- This was the last place in git-annex that could remove data referred
- to by the git history, without being forced.
- Like drop, dropunused checks remotes, and honors the global
- annex.numcopies setting. (However, .gitattributes settings cannot
- apply to unused files.)
- * Fix inverted logic in last release's fix for data loss bug,
- that caused git-annex sync on FAT or other crippled filesystems to add
- symlink standin files to the annex.
- * importfeed can be used to import files from podcast feeds.
- * webapp: When setting up a dedicated ssh key to access the annex
- on a host, set IdentitiesOnly to prevent the ssh-agent from forcing
- use of a different ssh key. That could result in unncessary password
- prompts, or prevent git-annex-shell from being run on the remote host.
- * webapp: Improve handling of remotes whose setup has stalled.
- * Add status message to XMPP presence tag, to identify to others that
- the client is a git-annex client. Closes: #[717652](http://bugs.debian.org/717652)
- * webapp: When creating a repository on a removable drive, set
- core.fsyncobjectfiles, to help prevent data loss when the drive is yanked.
- * Always build with -threaded, to avoid a deadlock when communicating with
- gpg.
- * unused: No longer shows as unused tmp files that are actively being
- transferred.
- * assistant: Fix NetWatcher to not sync with remotes that have
- remote.&lt;name&gt;.annex-sync set to false.
- * assistant: Fix deadlock that could occur when adding a lot of files
- at once in indirect mode.
- * assistant: Fix bug that caused it to stall when adding a very large
- number of files at once (around 5 thousand).
- * OSX: Make git-annex-webapp run in the background, so that the app icon
- can be clicked on the open a new webapp when the assistant is already
- running.
- * Improve test suite on Windows; now tests git annex sync.
- * Fix a few bugs involving filenames that are at or near the filesystem's
- maximum filename length limit.
- * find: Avoid polluting stdout with progress messages. Closes: #[718186](http://bugs.debian.org/718186)
- * Escape ':' in file/directory names to avoid it being treated
- as a pathspec by some git commands. Closes: #[718185](http://bugs.debian.org/718185)
- * Slow and ugly work around for bug #718517 in git 1.8.4~rc0, which broke
- git-cat-file --batch for filenames containing spaces.
- (Will be reverted after next git pre-release fixes the problem.)"""]] \ No newline at end of file
diff --git a/doc/news/version_4.20130827/comment_1_937cbaccf235d6d9118aacd49058bb4f._comment b/doc/news/version_4.20130827/comment_1_937cbaccf235d6d9118aacd49058bb4f._comment
new file mode 100644
index 000000000..293938867
--- /dev/null
+++ b/doc/news/version_4.20130827/comment_1_937cbaccf235d6d9118aacd49058bb4f._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://sunny256.sunbase.org/"
+ nickname="sunny256"
+ subject="Missing from the downloads.kitenet.net annex"
+ date="2013-08-29T18:05:38Z"
+ content="""
+Great release, thanks a lot. It's missing from the annex at downloads.kitenet.net, though.
+
+Cheers,<br />
+Øyvind (sunny256)
+"""]]
diff --git a/doc/news/version_4.20130827/comment_2_faa5cf0645728b4ade850a691fa472db._comment b/doc/news/version_4.20130827/comment_2_faa5cf0645728b4ade850a691fa472db._comment
new file mode 100644
index 000000000..0002e8607
--- /dev/null
+++ b/doc/news/version_4.20130827/comment_2_faa5cf0645728b4ade850a691fa472db._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.7"
+ subject="comment 2"
+ date="2013-08-29T18:26:00Z"
+ content="""
+It seems to be there on downloads.kitenet.net. When I run `git log` in there I see commit 82de1ed1a354e389bc71a15af1a3e67b5bd56f23 which added the release to the annex, and all the files seem to be present. For example, git-annex-standalone-amd64.tar.gz is pointing at the key `SHA256E-s20143752--388c33138185fb2eb5fdb00bf2155a9168e5a76501216887ea1ffa7ada06b776.tar.gz`, which is right.
+
+<pre>
+joey@wren:~>wget http://downloads.kitenet.net/git-annex/linux/current/git-annex-standalone-amd64.tar.gz
+--2013-08-29 14:25:00-- http://downloads.kitenet.net/git-annex/linux/current/git-annex-standalone-amd64.tar.gz
+Resolving downloads.kitenet.net (downloads.kitenet.net)... 2001:41c8:125:49::10, 80.68.85.49
+Connecting to downloads.kitenet.net (downloads.kitenet.net)|2001:41c8:125:49::10|:80... connected.
+HTTP request sent, awaiting response... 200 OK
+Length: 20143752 (19M) [application/x-gzip]
+Saving to: ‘git-annex-standalone-amd64.tar.gz’
+
+100%[======================================>] 20,143,752 48.9MB/s in 0.4s
+
+2013-08-29 14:25:01 (48.9 MB/s) - ‘git-annex-standalone-amd64.tar.gz’ saved [20143752/20143752]
+
+joey@wren:~>sha256sum git-annex-standalone-amd64.tar.gz
+388c33138185fb2eb5fdb00bf2155a9168e5a76501216887ea1ffa7ada06b776 git-annex-standalone-amd64.tar.gz
+</pre>
+"""]]
diff --git a/doc/news/version_4.20130827/comment_3_ad156d6199b525884114ff823d265bf7._comment b/doc/news/version_4.20130827/comment_3_ad156d6199b525884114ff823d265bf7._comment
new file mode 100644
index 000000000..538395f90
--- /dev/null
+++ b/doc/news/version_4.20130827/comment_3_ad156d6199b525884114ff823d265bf7._comment
@@ -0,0 +1,39 @@
+[[!comment format=mdwn
+ username="http://sunny256.sunbase.org/"
+ nickname="sunny256"
+ subject="comment 3"
+ date="2013-08-30T11:43:44Z"
+ content="""
+Hm, commit 82de1ed1a3 doesn't exist here after git-annex sync. This is the output from another computer, running Linux Mint 15:
+
+ $ ga sync
+ commit
+ ok
+ pull linode
+ ok
+ pull kitenet
+ WARNING: gnome-keyring:: couldn't connect to: /run/user/sunny/keyring-WSsS6N/pkcs11: No such file or directory
+ ok
+ push linode
+ Everything up-to-date
+ ok
+ push kitenet
+ WARNING: gnome-keyring:: couldn't connect to: /run/user/sunny/keyring-WSsS6N/pkcs11: No such file or directory
+ WARNING: gnome-keyring:: couldn't connect to: /run/user/sunny/keyring-WSsS6N/pkcs11: No such file or directory
+ error: Cannot access URL http://downloads.kitenet.net/.git/, return code 22
+ fatal: git-http-push failed
+ failed
+ git-annex: sync: 1 failed
+ $ git log -1
+ commit e4d2f03d9b37b2fac9508bf755ff7619bf46590c (HEAD, linode/synced/master, linode/master, linode/HEAD, kitenet/synced/master, kitenet/master, synced/master, master)
+ Author: Joey Hess <joey@kitenet.net>
+ Date: 3 weeks ago
+
+ update
+ 2013-08-30 13:36:37 sunny@passp:~/src/other/annex/downloads.kitenet.net/git-annex (master u=)
+ $ git log 82de1ed1a354e389bc71a15af1a3e67b5bd56f23
+ fatal: bad object 82de1ed1a354e389bc71a15af1a3e67b5bd56f23
+
+There's some warnings from gnome-keyring and a failed push (sorry about that, happens automatically), but the fetch from kitenet seems to succeed.
+
+"""]]
diff --git a/doc/news/version_4.20130827/comment_4_877061eb24d9d9543cc9cd229906bd64._comment b/doc/news/version_4.20130827/comment_4_877061eb24d9d9543cc9cd229906bd64._comment
new file mode 100644
index 000000000..5828a36c7
--- /dev/null
+++ b/doc/news/version_4.20130827/comment_4_877061eb24d9d9543cc9cd229906bd64._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://sunny256.sunbase.org/"
+ nickname="sunny256"
+ subject="comment 4"
+ date="2013-08-30T11:49:20Z"
+ content="""
+And some additional info, I'm using `http://downloads.kitenet.net/.git/` as the address to your annex. Maybe this repo is missing a `git update-server-info` in the `post-update` hook or something.
+"""]]
diff --git a/doc/news/version_4.20130827/comment_5_8991648dda991768e3a58477a4c3c923._comment b/doc/news/version_4.20130827/comment_5_8991648dda991768e3a58477a4c3c923._comment
new file mode 100644
index 000000000..55fa6d10a
--- /dev/null
+++ b/doc/news/version_4.20130827/comment_5_8991648dda991768e3a58477a4c3c923._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.7"
+ subject="sorry for delay.."
+ date="2013-09-03T18:07:34Z"
+ content="""
+That's weird.. I have a post-update hook that runs git-update-server-info, but I reproduced the problem, and manually running that fixed it.
+
+Guess I will need to keep an eye on this at the next release to see if it was a one-off problem..
+"""]]
diff --git a/doc/news/version_4.20130909.mdwn b/doc/news/version_4.20130909.mdwn
new file mode 100644
index 000000000..ead359898
--- /dev/null
+++ b/doc/news/version_4.20130909.mdwn
@@ -0,0 +1,36 @@
+git-annex 4.20130909 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * initremote: Syntax change when setting up an encrypted special remote.
+ Now use keyid=$KEYID rather than the old encryption=$KEYID
+ * forget: New command, causes git-annex branch history to be forgotten
+ in a way that will spread to other clones of the repository.
+ (As long as they're running this version or newer of git-annex.)
+ * forget --drop-dead: Completely removes mentions of repositories that
+ have been marked as dead from the git-annex branch.
+ * sync, assistant: Force push of the git-annex branch. Necessary
+ to ensure it gets pushed to remotes after being rewritten by forget.
+ * Added gcrypt support. This combines a fully encrypted git
+ repository (using git-remote-gcrypt) with an encrypted git-annex special
+ remote.
+ * sync: Support syncing with gcrypt remotes.
+ * importfeed: Also ignore transient problems with downloading content
+ from feeds.
+ * Honor core.sharedrepository when receiving and adding files in direct
+ mode.
+ * enableremote: gpg keys can be removed from those a remote encrypts
+ to by passing "keyid-=$KEYID". keyid+= is also provided.
+ (Thanks, guilhem for the patch.)
+ * Added encryption=pubkey scheme, which encrypts to public keys directly
+ rather than the hybrid approach. See documentation for advantages
+ and disadvantages, but encryption=hybrid is the recommended scheme still.
+ (Thanks, guilhem for the patch.)
+ * Fix Feeds display in build flags.
+ * Remind user when annex-ignore is set for some remotes, if unable to
+ get or drop a file, possibly because it's on an ignored remote.
+ * gpg: Force --no-textmode in case the user has it turned on in config.
+ * webapp: Improve javascript's handling of longpolling connection
+ failures, by reloading the current page in this case.
+ Works around chromium behavior where ajax connections to urls
+ that were already accessed are denied after navigating back to
+ a previous page.
+ * Allow building without quvi support."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20131002.mdwn b/doc/news/version_4.20131002.mdwn
new file mode 100644
index 000000000..90692e4f2
--- /dev/null
+++ b/doc/news/version_4.20131002.mdwn
@@ -0,0 +1,42 @@
+News for git-annex 4.20131002:
+
+ The layout of gcrypt repositories has changed, and
+ if you created one you must manually upgrade it.
+ See /usr/share/doc/git-annex/html/upgrades/gcrypt.html
+
+git-annex 4.20131002 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * Note that the layout of gcrypt repositories has changed, and
+ if you created one you must manually upgrade it.
+ See http://git-annex.branchable.com/upgrades/gcrypt/
+ * webapp: Support setting up and using encrypted git repositories on
+ any ssh server, as well as on rsync.net.
+ * git-annex-shell: Added support for operating inside gcrypt repositories.
+ * Disable receive.denyNonFastForwards when setting up a gcrypt special
+ remote, since gcrypt needs to be able to fast-forward the master branch.
+ * import: Preserve top-level directory structure.
+ * Use cryptohash rather than SHA for hashing when no external hash program
+ is available. This is a significant speedup for SHA256 on OSX, for
+ example.
+ * Added SKEIN256 and SKEIN512 backends.
+ * Android build redone from scratch, many dependencies updated,
+ and entire build can now be done using provided scripts.
+ * assistant: Clear the list of failed transfers when doing a full transfer
+ scan. This prevents repeated retries to download files that are not
+ available, or are not referenced by the current git tree.
+ * indirect, direct: Better behavior when a file is not owned by
+ the user running the conversion.
+ * add, import, assistant: Better preserve the mtime of symlinks,
+ when when adding content that gets deduplicated.
+ * Send a git-annex user-agent when downloading urls.
+ Overridable with --user-agent option.
+ (Not yet done for S3 or WebDAV due to limitations of libraries used.)
+ * webapp: Fixed a bug where when a new remote is added, one file
+ may fail to sync to or from it due to the transferrer process not
+ yet knowing about the new remote.
+ * OSX: Bundled gpg upgraded, now compatible with config files
+ written by MacGPG.
+ * assistant: More robust inotify handling; avoid crashing if a directory
+ cannot be read.
+ * Moved list of backends and remote types from status to version
+ command."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20131024.mdwn b/doc/news/version_4.20131024.mdwn
new file mode 100644
index 000000000..9cd65eb72
--- /dev/null
+++ b/doc/news/version_4.20131024.mdwn
@@ -0,0 +1,43 @@
+git-annex 4.20131024 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * webapp: Fix bug when adding a remote and git-remote-gcrypt
+ is not installed.
+ * The assitant can now run scheduled incremental fsck jobs on the local
+ repository and remotes. These can be configured using vicfg or with the
+ webapp.
+ * repair: New command, which can repair damaged git repositories
+ (even ones not using git-annex).
+ * webapp: When git repository damange is detected, repairs can be
+ done using the webapp UI.
+ * Automatically and safely detect and recover from dangling
+ .git/annex/index.lock files, which would prevent git from
+ committing to the git-annex branch, eg after a crash.
+ * assistant: Detect stale git lock files at startup time, and remove them.
+ * addurl: Better sanitization of generated filenames.
+ * Better sanitization of problem characters when generating URL and WORM
+ keys.
+ * The control socket path passed to ssh needs to be 17 characters
+ shorter than the maximum unix domain socket length, because ssh
+ appends stuff to it to make a temporary filename. Closes: #[725512](http://bugs.debian.org/725512)
+ * status: Fix space leak in local mode, introduced in version 4.20130920.
+ * import: Skip .git directories.
+ * Remove bogus runshell loop check.
+ * addurl: Improve message when adding url with wrong size to existing file.
+ * Fixed handling of URL keys that have no recorded size.
+ * status: Fix a crash if a temp file went away while its size was
+ being checked for status.
+ * Deal with git check-attr -z output format change in git 1.8.5.
+ * Work around sed output difference that led to version containing a newline
+ on OSX.
+ * sync: Fix automatic resolution of merge conflicts where one side is an
+ annexed file, and the other side is a non-annexed file, or a directory.
+ * S3: Try to ensure bucket name is valid for archive.org.
+ * assistant: Bug fix: When run in a subdirectory, files from incoming merges
+ were wrongly added to that subdirectory, and removed from their original
+ locations.
+ * Windows: Deal with strange msysgit 1.8.4 behavior of not understanding
+ DOS formatted paths for --git-dir and --work-tree.
+ * Removed workaround for bug in git 1.8.4r0.
+ * Added git-recover-repository command to git-annex source
+ (not built by default; this needs to move to someplace else).
+ * webapp: Move sidebar to the right hand side of the screen."""]] \ No newline at end of file
diff --git a/doc/news/version_4.20131101.mdwn b/doc/news/version_4.20131101.mdwn
new file mode 100644
index 000000000..2c6bb309d
--- /dev/null
+++ b/doc/news/version_4.20131101.mdwn
@@ -0,0 +1,29 @@
+git-annex 4.20131101 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * The "git annex content" command is renamed to "git annex wanted".
+ * New --want-get and --want-drop options which can be used to
+ test preferred content settings.
+ For example, "git annex find --in . --want-drop"
+ * assistant: When autostarted, wait 5 seconds before running the startup
+ scan, to avoid contending with the user's desktop login process.
+ * webapp: When setting up a bare shared repository, enable non-fast-forward
+ pushes.
+ * sync: Show a hint about receive.denyNonFastForwards when a push fails.
+ * directory, webdav: Fix bug introduced in version 4.20131002 that
+ caused the chunkcount file to not be written. Work around repositories
+ without such a file, so files can still be retreived from them.
+ * assistant: Automatically repair damanged git repository, if it can
+ be done without losing data.
+ * assistant: Support repairing git remotes that are locally accessible
+ (eg, on removable drives).
+ * add: Fix reversion in 4.20130827 when adding unlocked files that have
+ not yet been committed.
+ * unannex: New, much slower, but more safe behavior: Copies files out of
+ the annex. This avoids an unannex of one file breaking other files that
+ link to the same content. Also, it means that the content
+ remains in the annex using up space until cleaned up with
+ "git annex unused".
+ (The behavior of unannex --fast has not changed; it still hard links
+ to content in the annex. --fast was not made the default because it is
+ potentially unsafe; editing such a hard linked file can unexpectedly
+ change content stored in the annex.)"""]] \ No newline at end of file
diff --git a/doc/news/version_4.20131106.mdwn b/doc/news/version_4.20131106.mdwn
new file mode 100644
index 000000000..061d02100
--- /dev/null
+++ b/doc/news/version_4.20131106.mdwn
@@ -0,0 +1,18 @@
+git-annex 4.20131106 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * Improve local pairing behavior when two computers both try to start
+ the pairing process separately.
+ * sync: Work even when the local git repository is new and empty,
+ with no master branch.
+ * gcrypt, bup: Fix bug that prevented using these special remotes
+ with encryption=pubkey.
+ * Fix enabling of gcrypt repository accessed over ssh;
+ git-annex-shell gcryptsetup had a bug that caused it to fail
+ with permission denied.
+ * Fix zombie process that occurred when switching between repository
+ views in the webapp.
+ * map: Work when there are gcrypt remotes.
+ * Fix build w/o webapp.
+ * Fix exception handling bug that could cause .git/annex/index to be used
+ for git commits outside the git-annex branch. Known to affect git-annex
+ when used with the git shipped with Ubuntu 13.10."""]] \ No newline at end of file
diff --git a/doc/polls.mdwn b/doc/polls.mdwn
new file mode 100644
index 000000000..55c779867
--- /dev/null
+++ b/doc/polls.mdwn
@@ -0,0 +1,2 @@
+* [[2013 git-annex user survey|2013]]
+* [[old polls|design/assistant/polls]]
diff --git a/doc/polls/2013.mdwn b/doc/polls/2013.mdwn
new file mode 100644
index 000000000..bda584d64
--- /dev/null
+++ b/doc/polls/2013.mdwn
@@ -0,0 +1,5 @@
+This has moved to a separate site due to load issues.
+
+<http://git-annex-survey.branchable.com/polls/2013/>
+
+Any votes you made here were carried over, so no need to vote twice!
diff --git a/doc/preferred_content.mdwn b/doc/preferred_content.mdwn
index 6e71a5276..6a5364f67 100644
--- a/doc/preferred_content.mdwn
+++ b/doc/preferred_content.mdwn
@@ -7,7 +7,7 @@ this allows `git annex get --auto`, `git annex drop --auto`, etc to do
smarter things.
Preferred content settings can be edited using `git
-annex vicfg`, or viewed and set at the command line with `git annex content`.
+annex vicfg`, or viewed and set at the command line with `git annex wanted`.
Each repository can have its own settings, and other repositories may also
try to honor those settings. So there's no local `.git/config` setting it.
@@ -84,6 +84,16 @@ 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
diff --git a/doc/preferred_content/comment_10_f0bce3c67f293eaba97b92f0942876b6._comment b/doc/preferred_content/comment_10_f0bce3c67f293eaba97b92f0942876b6._comment
new file mode 100644
index 000000000..cd7c36fe4
--- /dev/null
+++ b/doc/preferred_content/comment_10_f0bce3c67f293eaba97b92f0942876b6._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 10"
+ date="2013-10-11T17:12:00Z"
+ content="""
+Georg, `drop --auto` will only drop files that are not preferred content. I'd need to know what preferred content expression you're using to say more.
+"""]]
diff --git a/doc/preferred_content/comment_9_f82538be42428691d7cab60a7add2e74._comment b/doc/preferred_content/comment_9_f82538be42428691d7cab60a7add2e74._comment
new file mode 100644
index 000000000..e1c2d4164
--- /dev/null
+++ b/doc/preferred_content/comment_9_f82538be42428691d7cab60a7add2e74._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkC0W3ZQERUaTkHoks6k68Tsp1tz510nGo"
+ nickname="Georg"
+ subject="drop only files located in archive"
+ date="2013-10-08T17:53:08Z"
+ content="""
+Is there a way to drop only the files that are located in an \"archive\" directory?
+I want to drop all files when calling
+
+ git annex drop --auto
+
+if I move them to the archive. But I want to keep the files that are outside of the archive, even if they are already present in other repos. As far as I have seen and tested, as soon as I have the files in an other repo all files get dropped, also the ones outside the archive directory. Or do I have to increase \"numcopies\" in order to circumvent the \"(not copies=semitrusted+:1)\" case?
+"""]]
diff --git a/doc/related_software.mdwn b/doc/related_software.mdwn
index 4a8bc78ac..024a155e3 100644
--- a/doc/related_software.mdwn
+++ b/doc/related_software.mdwn
@@ -9,3 +9,4 @@ designed to interoperate with it.
is git-annex aware.
* [sizes](http://hackage.haskell.org/package/sizes) is another du-like
utility, with a `-A` switch that enables git-annex support.
+* Emacs Org mode can auto-commit attached files to git-annex.
diff --git a/doc/shortcuts.mdwn b/doc/shortcuts.mdwn
new file mode 100644
index 000000000..d0f647a64
--- /dev/null
+++ b/doc/shortcuts.mdwn
@@ -0,0 +1,12 @@
+[[!if test="enabled(shortcut)"
+ then="This wiki has shortcuts **enabled**."
+ else="This wiki has shortcuts **disabled**."]]
+
+This page controls what shortcut links the wiki supports.
+
+* [[!shortcut name=debbug url="http://bugs.debian.org/%S" desc="Debian bug #%s"]]
+* [[!shortcut name=iki url="http://ikiwiki.info/%S/"]]
+* [[!shortcut name=rfc url="https://www.ietf.org/rfc/rfc%s.txt" desc="RFC %s"]]
+* [[!shortcut name=cve url="https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s"]]
+* [[!shortcut name=hackage url="http://hackage.haskell.org/package/%s"]]
+* [[!shortcut name=commit url="http://source.git-annex.branchable.com/?p=source.git;a=commitdiff;h=%s"]]
diff --git a/doc/special_remotes.mdwn b/doc/special_remotes.mdwn
index 978989503..6878a1f88 100644
--- a/doc/special_remotes.mdwn
+++ b/doc/special_remotes.mdwn
@@ -10,6 +10,7 @@ They cannot be used by other git commands though.
* [[S3]] (Amazon S3, and other compatible services)
* [[Amazon_Glacier|glacier]]
* [[bup]]
+* [[gcrypt]] (encrypted git repositories!)
* [[directory]]
* [[rsync]]
* [[webdav]]
@@ -18,8 +19,16 @@ They cannot be used by other git commands though.
* [[hook]]
The above special remotes can be used to tie git-annex
-into many cloud services. Here are specific instructions
-for various cloud things:
+into many cloud services.
+
+There are many use cases for a special remote. You could use it as a backup. You could use it to archive files offline in a drive with encryption enabled so if the drive is stolen your data is not. You could git annex move --to specialremote large files when your local drive is getting full, and then git annex move the files back when free space is again available. You could have one repository copy files to a special remote, and then git annex get them on another repository, to transfer the files between computers that do not communicate directly.
+
+The git-annex assistant makes it easy to set up rsync remotes using this last scenario, which is referred to as a transfer repository, and arranges to drop files from the transfer repository once they have been transferred to all known clients.
+
+None of these use cases are particular to particular special remote types. Most special remotes can all be used in these and other ways. It largely doesn't matter for your use what underlying transport the special remote uses.
+
+Here are specific instructions
+for using git-annex with various services:
* [[Amazon_S3|tips/using_Amazon_S3]]
* [[Amazon_Glacier|tips/using_Amazon_Glacier]]
@@ -34,6 +43,7 @@ for various cloud things:
* [[Flickr|tips/flickrannex]]
* [[IMAP|forum/special_remote_for_IMAP]]
* [[Usenet|forum/nntp__47__usenet special remote]]
+* [chef-vault](https://github.com/3ofcoins/knife-annex/)
## Unused content on special remotes
diff --git a/doc/special_remotes/S3.mdwn b/doc/special_remotes/S3.mdwn
index e15361f3e..5291a4eb6 100644
--- a/doc/special_remotes/S3.mdwn
+++ b/doc/special_remotes/S3.mdwn
@@ -15,13 +15,10 @@ can read inside the local git repository.
A number of parameters can be passed to `git annex initremote` to configure
the S3 remote.
-* `encryption` - Required. Either "none" to disable encryption (not recommended),
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to access the encrypted data (use with caution).
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `embedcreds` - Optional. Set to "yes" embed the login credentials inside
the git repository, which allows other clones to also access them. This is
diff --git a/doc/special_remotes/S3/comment_15_ceb9048c743135f6beca57a23505f0a3._comment b/doc/special_remotes/S3/comment_15_ceb9048c743135f6beca57a23505f0a3._comment
new file mode 100644
index 000000000..a8b5573e7
--- /dev/null
+++ b/doc/special_remotes/S3/comment_15_ceb9048c743135f6beca57a23505f0a3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawne_amN4fko4p5cRY_9EYwaYuJKNn7LRio"
+ nickname="Tobias"
+ subject="different s3 storage URLs"
+ date="2013-08-23T08:59:32Z"
+ content="""
+Is it possible to change the S3 endpoint hosts? I'm running a radosgw with S3 support which I'd like to define as S3 remote for git-annex
+"""]]
diff --git a/doc/special_remotes/S3/comment_16_7b79f8b5ef88a2775d61b5ac5774d3e0._comment b/doc/special_remotes/S3/comment_16_7b79f8b5ef88a2775d61b5ac5774d3e0._comment
new file mode 100644
index 000000000..508cedca4
--- /dev/null
+++ b/doc/special_remotes/S3/comment_16_7b79f8b5ef88a2775d61b5ac5774d3e0._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 16"
+ date="2013-08-23T17:39:56Z"
+ content="""
+Yes, you can specify the host to use when setting up the remote. It's actually documented earlier on this very page, if ou search for \"host\". Any S3 compatabile host will probably work -- the Internet Archive's S3 does, for example.
+"""]]
diff --git a/doc/special_remotes/bup.mdwn b/doc/special_remotes/bup.mdwn
index f323237b1..f2d465e77 100644
--- a/doc/special_remotes/bup.mdwn
+++ b/doc/special_remotes/bup.mdwn
@@ -19,14 +19,10 @@ for example; or clone bup's git repository to further back it up.
These parameters can be passed to `git annex initremote` to configure bup:
-* `encryption` - Required. Either "none" to disable encryption of content
- stored in bup (ssh will still be used to transport it securely),
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to access the encrypted data (use with caution).
-
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
+
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `buprepo` - Required. This is passed to `bup` as the `--remote`
to use to store data. To create the repository,`bup init` will be run.
diff --git a/doc/special_remotes/directory.mdwn b/doc/special_remotes/directory.mdwn
index d23c1ae26..4d72e8bee 100644
--- a/doc/special_remotes/directory.mdwn
+++ b/doc/special_remotes/directory.mdwn
@@ -5,18 +5,19 @@ you want to use it to sneakernet files between systems (possibly with
[[encrypted|encryption]] contents). Just set up both systems to use
the drive's mountpoint as a directory remote.
+If you just want two copies of your repository with the files "visible"
+in the tree in both, the directory special remote is not what you want.
+Instead, you should use a regular `git clone` of your git-annex repository.
+
## configuration
These parameters can be passed to `git annex initremote` to configure the
remote:
-* `encryption` - Required. Either "none" to disable encryption,
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to decrypt the encrypted data.
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `chunksize` - Avoid storing files larger than the specified size in the
directory. For use on directories on mount points that have file size
diff --git a/doc/special_remotes/gcrypt.mdwn b/doc/special_remotes/gcrypt.mdwn
new file mode 100644
index 000000000..ac98c43bb
--- /dev/null
+++ b/doc/special_remotes/gcrypt.mdwn
@@ -0,0 +1,45 @@
+[git-remote-gcrypt](https://github.com/joeyh/git-remote-gcrypt/)
+adds support for encrypted remotes to git. The git-annex gcrypt special
+remote allows git-annex to also store its files in such repositories.
+Naturally, git-annex encrypts the files it stores too, so everything
+stored on the remote is encrypted.
+
+See [[tips/fully_encrypted_git_repositories_with_gcrypt]] for some examples
+of using gcrypt.
+
+## configuration
+
+These parameters can be passed to `git annex initremote` to configure
+gcrypt:
+
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
+
+* `keyid` - Specifies the gpg key to use for encryption of both the files
+ git-annex stores in the repository, as well as to encrypt the git
+ repository itself. May be repeated when multiple participants
+ should have access to the repository.
+
+* `gitrepo` - Required. The path or url to the git repository
+ for gcrypt to use. This repository should be either empty, or an existing
+ gcrypt repositry.
+
+* `shellescape` - See [[rsync]] for the details of this option.
+
+## notes
+
+For git-annex to store files in a repository on a remote server, you need
+shell access, and `rsync` must be installed. Those are the minimum
+requirements, but it's also recommended to install git-annex on the remote
+server, so that [[git-annex-shell]] can be used.
+
+While you can use git-remote-gcrypt with servers like github, git-annex
+can't store files on them. In such a case, you can just use
+git-remote-gcrypt directly.
+
+If you use encryption=hybrid, you can add more gpg keys that can access
+the files git-annex stored in the gcrypt repository. However, due to the
+way git-remote-gcrypt encrypts the git repository, you will need to somehow
+force it to re-push everything again, so that the encrypted repository can
+be decrypted by the added keys. Probably this can be done by setting
+`GCRYPT_FULL_REPACK` and doing a forced push of branches.
diff --git a/doc/special_remotes/glacier.mdwn b/doc/special_remotes/glacier.mdwn
index d6dbad59a..b55b9adbb 100644
--- a/doc/special_remotes/glacier.mdwn
+++ b/doc/special_remotes/glacier.mdwn
@@ -21,13 +21,10 @@ can read inside the local git repository.
A number of parameters can be passed to `git annex initremote` to configure
the Glacier remote.
-* `encryption` - Required. Either "none" to disable encryption (not recommended),
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to access the encrypted data (use with caution).
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `embedcreds` - Optional. Set to "yes" embed the login credentials inside
the git repository, which allows other clones to also access them. This is
diff --git a/doc/special_remotes/hook.mdwn b/doc/special_remotes/hook.mdwn
index d5c708e0a..eaea940a7 100644
--- a/doc/special_remotes/hook.mdwn
+++ b/doc/special_remotes/hook.mdwn
@@ -25,17 +25,14 @@ Can you spot the potential data loss bugs in the above simple example?
These parameters can be passed to `git annex initremote`:
-* `encryption` - Required. Either "none" to disable encryption,
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to access the encrypted data.
-
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
-
* `hooktype` - Required. This specifies a collection of hooks to use for
this remote.
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
+
+* `keyid` - Specifies the gpg key to use for [[encryption]].
+
## hooks
Each type of hook remote is specified by a collection of hook commands.
diff --git a/doc/special_remotes/rsync.mdwn b/doc/special_remotes/rsync.mdwn
index 581ac6b96..b2a9d23f5 100644
--- a/doc/special_remotes/rsync.mdwn
+++ b/doc/special_remotes/rsync.mdwn
@@ -2,26 +2,22 @@ This special remote type rsyncs file contents to somewhere else.
Setup example:
- # git annex initremote myrsync type=rsync rsyncurl=rsync://rsync.example.com/myrsync encryption=joey@kitenet.net
+ # git annex initremote myrsync type=rsync rsyncurl=rsync://rsync.example.com/myrsync keyid=joey@kitenet.net
# git annex describe myrsync "rsync server"
Or for using rsync over SSH
- # git annex initremote myrsync type=rsync rsyncurl=ssh.example.com:/myrsync encryption=joey@kitenet.net
+ # git annex initremote myrsync type=rsync rsyncurl=ssh.example.com:/myrsync keyid=joey@kitenet.net
# git annex describe myrsync "rsync server"
## configuration
These parameters can be passed to `git annex initremote` to configure rsync:
-* `encryption` - Required. Either "none" to disable encryption of content
- stored on the remote rsync server,
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to decrypt the encrypted data.
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `rsyncurl` - Required. This is the url or `hostname:/directory` to
pass to rsync to tell it where to store content.
diff --git a/doc/special_remotes/rsync/comment_10_43e8fa3517c1f5935f02ad06fbed63dc._comment b/doc/special_remotes/rsync/comment_10_43e8fa3517c1f5935f02ad06fbed63dc._comment
new file mode 100644
index 000000000..185bd97ec
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_10_43e8fa3517c1f5935f02ad06fbed63dc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="comment 10"
+ date="2013-08-25T20:59:41Z"
+ content="""
+@joey I don't understand you last comment where you state that special remotes can act as transfer repositories \"to transfer the files between computers that do not communicate directly\". If there's no communication, ie git pushes or pulls, between the computers then they don't know what file names the files on the special remote map to. They need to somehow communicate the git repo too, don't they?
+"""]]
diff --git a/doc/special_remotes/rsync/comment_11_8cafc1a8b37e6fb056185ec058c0c3e8._comment b/doc/special_remotes/rsync/comment_11_8cafc1a8b37e6fb056185ec058c0c3e8._comment
new file mode 100644
index 000000000..c8fc8831a
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_11_8cafc1a8b37e6fb056185ec058c0c3e8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 11"
+ date="2013-08-26T18:36:03Z"
+ content="""
+@Chris yes in that case you still need, a central git repository (which need not be on a host that supports git-annex), or the assistant can use xmpp to sync the git data.
+"""]]
diff --git a/doc/special_remotes/rsync/comment_7_e122979ea811d9ef835ba05bb936190f._comment b/doc/special_remotes/rsync/comment_7_e122979ea811d9ef835ba05bb936190f._comment
new file mode 100644
index 000000000..8cb1d72b4
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_7_e122979ea811d9ef835ba05bb936190f._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="rsync remote is basically more intended for backups ?"
+ date="2013-08-17T17:40:47Z"
+ content="""
+If I get it correctly, it is mainly useable as a backup, which will accumulate contents of the objects managed by git-annex over time.
+
+It would be great to have a use case illustrating its use in concrete matters. Thanks in advance.
+"""]]
diff --git a/doc/special_remotes/rsync/comment_8_d566113318d0aa7500d76ffe1bd46069._comment b/doc/special_remotes/rsync/comment_8_d566113318d0aa7500d76ffe1bd46069._comment
new file mode 100644
index 000000000..1e6bf8aa4
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_8_d566113318d0aa7500d76ffe1bd46069._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 8"
+ date="2013-08-22T18:02:00Z"
+ content="""
+There are many use cases for a rsync special remote. You could use it as a backup. You could use it to archive files offline in a drive with encryption enabled so if the drive is stolen your data is not. You could `git annex move --to rsyncremote` large files when your local drive is getting full, and then `git annex move` the files back when free space is again available. You could have one repository copy files to a rsync remote, and then `git annex get` them on another repository, to transfer the files between computers that do not communicate directly. The git-annex assistant makes it easy to set up rsync remotes using this last scenario, which is referred to as a transfer repository, and arranges to drop files from the transfer repository once they have been transferred to all known clients.
+
+None of these use cases are particular to rsync remotes. Most special remotes can all be used in these and other ways. It largely doesn't matter for your use what underlying transport the special remote uses.
+"""]]
diff --git a/doc/special_remotes/rsync/comment_9_5dcf10a502b2d4feac46b620d43e9d00._comment b/doc/special_remotes/rsync/comment_9_5dcf10a502b2d4feac46b620d43e9d00._comment
new file mode 100644
index 000000000..b7690cf68
--- /dev/null
+++ b/doc/special_remotes/rsync/comment_9_5dcf10a502b2d4feac46b620d43e9d00._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="Added use cases to &quot;special remotes&quot;"
+ date="2013-08-22T20:23:13Z"
+ content="""
+Thanks @joeyh. I've taken the liberty to add your use case description to [[special remotes]]. Hope this helps.
+"""]]
diff --git a/doc/special_remotes/web/comment_1_0bd570025f6cd551349ea88a4729ac8e._comment b/doc/special_remotes/web/comment_1_0bd570025f6cd551349ea88a4729ac8e._comment
new file mode 100644
index 000000000..d01e17da3
--- /dev/null
+++ b/doc/special_remotes/web/comment_1_0bd570025f6cd551349ea88a4729ac8e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://olivier.berger.myopenid.com/"
+ nickname="obergix"
+ subject="Which URL prefix are supported ?"
+ date="2013-08-17T08:44:05Z"
+ content="""
+It is not clear whether only http:// URLs are supported. Can you list others ?
+"""]]
diff --git a/doc/special_remotes/web/comment_2_333141cc9ec6c26ffd19aa95303a91e3._comment b/doc/special_remotes/web/comment_2_333141cc9ec6c26ffd19aa95303a91e3._comment
new file mode 100644
index 000000000..ff2018117
--- /dev/null
+++ b/doc/special_remotes/web/comment_2_333141cc9ec6c26ffd19aa95303a91e3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 2"
+ date="2013-08-17T08:59:11Z"
+ content="""
+When it says \"arbitrary urls\", it means it. The only requirement is that the url be well formed and that wget or whatever command you have it configured to use via annex.web-download-command knows how to download it.
+"""]]
diff --git a/doc/special_remotes/webdav.mdwn b/doc/special_remotes/webdav.mdwn
index 383fddf75..251075b09 100644
--- a/doc/special_remotes/webdav.mdwn
+++ b/doc/special_remotes/webdav.mdwn
@@ -10,13 +10,10 @@ can read inside the local git repository.
A number of parameters can be passed to `git annex initremote` to configure
the webdav remote.
-* `encryption` - Required. Either "none" to disable encryption (not recommended),
- or a value that can be looked up (using gpg -k) to find a gpg encryption
- key that will be given access to the remote, or "shared" which allows
- every clone of the repository to access the encrypted data (use with caution).
+* `encryption` - One of "none", "hybrid", "shared", or "pubkey".
+ See [[encryption]].
- Note that additional gpg keys can be given access to a remote by
- running enableremote with the new key id. See [[encryption]].
+* `keyid` - Specifies the gpg key to use for [[encryption]].
* `embedcreds` - Optional. Set to "yes" embed the login credentials inside
the git repository, which allows other clones to also access them. This is
@@ -42,4 +39,4 @@ the webdav remote.
Setup example:
- # WEBDAV_USERNAME=joey@kitenet.net WEBDAV_PASSWORD=xxxxxxx git annex initremote box.com type=webdav url=https://www.box.com/dav/git-annex chunksize=75mb encryption=joey@kitenet.net
+ # WEBDAV_USERNAME=joey@kitenet.net WEBDAV_PASSWORD=xxxxxxx git annex initremote box.com type=webdav url=https://www.box.com/dav/git-annex chunksize=75mb keyid=joey@kitenet.net
diff --git a/doc/special_remotes/xmpp.mdwn b/doc/special_remotes/xmpp.mdwn
index ef5e85511..33fa1a081 100644
--- a/doc/special_remotes/xmpp.mdwn
+++ b/doc/special_remotes/xmpp.mdwn
@@ -21,4 +21,19 @@ any other git remote. Since XMPP requires a client that is continually running
to see incoming pushes, the XMPP remote cannot be used with git at the
command line.
+## XMPP server support status
+[[!table data="""
+Provider|Status|Type|Notes
+[[Gmail|http://gmail.com]]|Working|?|Google apps users will have to configure `.git/annex/creds/xmpp` manually
+[[Coderollers|http://www.coderollers.com/xmpp-server/]]|Working|[[Openfire|http://www.igniterealtime.org/projects/openfire/]]
+[[jabber.me|http://jabber.me/]]|Working|[[Tigase|http://www.tigase.org/]]
+[[xmpp.ru.net|https://www.xmpp.ru.net]]|Working|[[jabberd2|http://jabberd2.org/]]
+[[jabber.org|http://jabber.org]]|Working|[[Isode M-Link|http://www.isode.com/products/m-link.html]]
+-|Working|[[Prosody|http://prosody.im/]]|No providers tested.
+-|Working|[[Metronome|http://www.lightwitch.org/]]|No providers tested.
+-|[[Failing|http://git-annex.branchable.com/forum/XMPP_authentication_failure/]]|ejabberd|[[Authentication bug|https://support.process-one.net/browse/EJAB-1632]]: Fixed in debian unstable with version 2.1.10-5
+-|[[Failing|http://git-annex.branchable.com/forum/XMPP_authentication_failure/#comment-4ce5aeabd12ca3016290b3d8255f6ef1]]|jabberd14|No further information
+"""]]
+List of providers: [[http://xmpp.net/]]
+
See also: [[xmpp_protocol_design_notes|design/assistant/xmpp]]
diff --git a/doc/special_remotes/xmpp/comment_3_48ddbba1402d89acaea07cff747c48e0._comment b/doc/special_remotes/xmpp/comment_3_48ddbba1402d89acaea07cff747c48e0._comment
new file mode 100644
index 000000000..7643d4d7d
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_3_48ddbba1402d89acaea07cff747c48e0._comment
@@ -0,0 +1,28 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="46.19.143.203"
+ subject="Missing prerequisites for XMPP syncing?"
+ date="2013-09-17T06:53:59Z"
+ content="""
+I set up two fresh annexes that can talk via XMPP and no other way. After I fire up the assistants I expect them to sync their metadata, but nothing happens. One log gives me an 'XMPPClient: received: [\"Unknown message\"]' message every two minutes. The other one doesn't contain the string XMPP at all, not once. So my suspicion is that this particular version of git-annex doesn't support XMPP, which is weird because:
+
+ $ git annex version
+ git-annex version: 4.20130909
+ build flags: Assistant Pairing Testsuite S3 Inotify XMPP DNS Feeds
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+This is the version output from the other machine:
+
+ $ git annex version
+ git-annex version: 4.20130827
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV Inotify DBus XMPP
+ local repository version: 3
+ default repository version: 3
+ supported repository versions: 3 4
+ upgrade supported from repository versions: 0 1 2
+
+What am I missing? Are there more build flags for XMPP than the one called XMPP? (Also, no, I can't just copy versions between machines b/c the architectures are different. And yep, the one giving me trouble is ARM.)
+"""]]
diff --git a/doc/special_remotes/xmpp/comment_4_59857879abaae22bde444a215e00bf18._comment b/doc/special_remotes/xmpp/comment_4_59857879abaae22bde444a215e00bf18._comment
new file mode 100644
index 000000000..db217cff9
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_4_59857879abaae22bde444a215e00bf18._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 4"
+ date="2013-09-19T21:07:35Z"
+ content="""
+If you have the XMPP flag in your git-annex build, it will support XMPP. Are you sure you set up the xmpp creds file and the xmpp special remote correctly on the ARM machine? (I assume it has no webapp, so you had to set that up manually..)
+
+Here's how you can do that manually:
+
+1. Run git-annex on a machine with the webapp, set up XMPP, and copy the .git/annex/creds/xmpp to the machine without the webapp.
+2. On the machine without the webapp, add a git remote that has its \"url = xmpp::loginname@xmppserver.com\" and its annex-uuid set to the annex.uuid of the repository on the first machine.
+3. Run git-annex assistant on the machine without the webapp.
+"""]]
diff --git a/doc/special_remotes/xmpp/comment_5_583ee374bd34fcc9ae26c2fd690e8c47._comment b/doc/special_remotes/xmpp/comment_5_583ee374bd34fcc9ae26c2fd690e8c47._comment
new file mode 100644
index 000000000..298c4392a
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_5_583ee374bd34fcc9ae26c2fd690e8c47._comment
@@ -0,0 +1,73 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="37.221.161.234"
+ subject="Nope"
+ date="2013-09-24T22:05:55Z"
+ content="""
+Your guess is right, Joey, I'm configuring by hand as the ARM machine has no webapp. And yes, I'm mostly sure I set up everything correctly. The XMPP account is working, and my configuration of git-annex is all but identical to your example.
+
+Here's what I do. First on the machine with the webapp:
+
+ mkdir ~/test
+ cd ~/test
+ git init
+ git annex init
+ git annex webapp
+
+I set up XMPP from within the webapp. The file ~/test/.git/annex/creds/xmpp is created with the correct credentials. (BTW: The file's default permissions are 620 instead of 600 - is that a bug?)
+
+I add a file or two to the annex for good measure. Then, on the ARM machine:
+
+ mkdir ~/test
+ cd ~/test
+ git init
+ git annex init
+ mkdir .git/annex/creds
+ scp -2 webappmachine:~/test/.git/annex/creds/xmpp .git/annex/creds
+ chmod 600 .git/annex/creds/xmpp
+ git remote add webappmachine xmpp::login@server
+
+The final step is to edit .git/config on the ARM machine. The [remote] section now looks like this:
+
+ [remote \"webappmachine\"]
+ url = xmpp::login@server
+ fetch = +refs/heads/*:refs/remotes/webappmachine/*
+ annex-uuid = aaaaaaaa-bbbb-cccc-dddddddddddd
+
+where aaaaaaaa-bbbb-cccc-dddddddddddd is the return value of `git config --get annex.uuid` on the webapp machine.
+
+I then run `git annex assistant` on the ARM machine and expect the two machines to synchronize their metadata, e.g. the number of knownn annex keys in the repo. But it doesn't happen.
+
+So I set `debug = true`, restart the assistants and check the log. This is what I get on the webapp machine:
+
+ [2013-09-24 17:45:41 EDT] XMPPClient: connected a5/25577ac4-3248-4c83-8391-bd93708bcf2b
+ [2013-09-24 17:45:41 EDT] XMPPClient: received: [\"Presence from a5/dc9bcde8-fe18-47de-807c-c620019279f2 Just (Element {elementName = Name {nameLocalName = \\"git-annex\\", nameNamespace = Just \\"git-annex\\", namePrefix = Nothing}, elementAttributes = [(Name {nameLocalName = \\"query\\", nameNamespace = Nothing, namePrefix = Nothing},[ContentText \\"\\"])], elementNodes = []})\",\"QueryPresence\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Presence from a5/900e3b6e-a7f4-4a6a-8d12-ed94de429258 Just (Element {elementName = Name {nameLocalName = \\"git-annex\\", nameNamespace = Just \\"git-annex\\", namePrefix = Nothing}, elementAttributes = [(Name {nameLocalName = \\"push\\", nameNamespace = Nothing, namePrefix = Nothing},[ContentText \\"43357474-abbb-4667-a334-e4615ea6d4a2\\"])], elementNodes = []})\",\"NotifyPush [UUID \\"43357474-abbb-4667-a334-e4615ea6d4a2\\"]\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: push notification for
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"symbolic-ref\",\"HEAD\"]
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"show-ref\",\"refs/heads/master\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Pushing \\"a59\\" (CanPush (UUID \\"d50c4cc9-e7c0-4ef0-84c6-f11012051eb9\\") [34f875cc7fa1198414f93990af9ab78e6cee893e,6fad42234060361435d6cf2ab4bd40e438c2d05c])\"]
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"show-ref\",\"git-annex\"]
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"show-ref\",\"--hash\",\"refs/heads/git-annex\"]
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"log\",\"refs/heads/git-annex..6fad42234060361435d6cf2ab4bd40e438c2d05c\",\"--oneline\",\"-n1\"]
+ [2013-09-24 17:45:42 EDT] chat: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"cat-file\",\"--batch\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Ignorable Presence from a5/25577ac4-3248-4c83-8391-bd93708bcf2b Just (Element {elementName = Name {nameLocalName = \\"git-annex\\", nameNamespace = Just \\"git-annex\\", namePrefix = Nothing}, elementAttributes = [], elementNodes = []})\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Unknown message\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Pushing \\"a59\\" (PushRequest (UUID \\"d50c4cc9-e7c0-4ef0-84c6-f11012051eb9\\"))\"]
+ [2013-09-24 17:45:42 EDT] XMPPSendPack: started running push Pushing \"a59\" (PushRequest (UUID \"d50c4cc9-e7c0-4ef0-84c6-f11012051eb9\"))
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"symbolic-ref\",\"HEAD\"]
+ [2013-09-24 17:45:42 EDT] XMPPClient: received: [\"Ignorable Presence from a5/25577ac4-3248-4c83-8391-bd93708bcf2b Just (Element {elementName = Name {nameLocalName = \\"git-annex\\", nameNamespace = Just \\"git-annex\\", namePrefix = Nothing}, elementAttributes = [], elementNodes = []})\"]
+ [2013-09-24 17:45:42 EDT] read: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"show-ref\",\"refs/heads/master\"]
+ [2013-09-24 17:45:42 EDT] call: git [\"--git-dir=/home/pi/test/.git\",\"--work-tree=/home/pi/test\",\"branch\",\"-f\",\"synced/master\"]
+ [2013-09-24 17:45:42 EDT] XMPPSendPack: finished running push Pushing \"a59\" (PushRequest (UUID \"d50c4cc9-e7c0-4ef0-84c6-f11012051eb9\")) False
+
+And from then on, in two-minute intervals:
+
+ [2013-09-24 17:47:42 EDT] XMPPClient: received: [\"Unknown message\"]
+ [2013-09-24 17:49:42 EDT] XMPPClient: received: [\"Unknown message\"]
+ [2013-09-24 17:51:42 EDT] XMPPClient: received: [\"Unknown message\"]
+
+The log on the ARM machine is rather unhelpful. Actually it doesn't even contain the string \"XMPP\". This looks to me like the webapp machine tries to communicate via Jabber but doesn't get any intelligible answer. And this is the reason I wondered whether the problem lies with my self-compiled ARM git-annex binary. I actually spent a while compiling 4.20130909 with all flags but webapp and webdav, but the result is still the same.
+
+Any other ideas what I'm doing wrong here?
+"""]]
diff --git a/doc/special_remotes/xmpp/comment_6_8f0b5bba1271d031a67e7f0c175d67d5._comment b/doc/special_remotes/xmpp/comment_6_8f0b5bba1271d031a67e7f0c175d67d5._comment
new file mode 100644
index 000000000..750e0874a
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_6_8f0b5bba1271d031a67e7f0c175d67d5._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 6"
+ date="2013-09-25T18:13:24Z"
+ content="""
+If you're not getting an \"XMPPClient: connected\", then my guess would be that your git-annex build's XMPP is screwed up somehow. For example, if it hung forever when connecting to the XMPP server, it would never get as far as printing that message. (If it tried and failed to connect, you'd get a message about the connection having failed.)
+"""]]
diff --git a/doc/special_remotes/xmpp/comment_7_ac7acbded03325b015959d82ae77faf1._comment b/doc/special_remotes/xmpp/comment_7_ac7acbded03325b015959d82ae77faf1._comment
new file mode 100644
index 000000000..0ad65336b
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_7_ac7acbded03325b015959d82ae77faf1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="RaspberryPie"
+ ip="46.165.221.166"
+ subject="comment 7"
+ date="2013-09-26T03:46:18Z"
+ content="""
+I see. Is there a way to check whether the build is corrupt? The build logs gave me nothing.
+
+Anyway, XMPP is not the most important feature to me. It still bugs me though that it doesn't work when it should.
+"""]]
diff --git a/doc/special_remotes/xmpp/comment_8_81a9636a1e8a36a58185468a26f8633d._comment b/doc/special_remotes/xmpp/comment_8_81a9636a1e8a36a58185468a26f8633d._comment
new file mode 100644
index 000000000..79dd2892b
--- /dev/null
+++ b/doc/special_remotes/xmpp/comment_8_81a9636a1e8a36a58185468a26f8633d._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnZEanlyzay_QlEAL0CWpyZcRTyN7vay8U"
+ nickname="Carlo"
+ subject="comment 8"
+ date="2013-10-22T14:30:58Z"
+ content="""
+Same setup, same problem... no log output on raspberry pi.
+"""]]
diff --git a/doc/sync/comment_5_18c396c59907147bb2bf713e55392b6b._comment b/doc/sync/comment_5_18c396c59907147bb2bf713e55392b6b._comment
new file mode 100644
index 000000000..dd7be6f45
--- /dev/null
+++ b/doc/sync/comment_5_18c396c59907147bb2bf713e55392b6b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://elmimmo.myopenid.com/"
+ nickname="chocolate.camera"
+ subject="How to sync content with git-annex, not assistant"
+ date="2013-10-11T09:58:12Z"
+ content="""
+Sure assistant can sync git-annex data across remotes. But how do I tell a repo to sync git-annex data, but not so manually as to having to know what exactly needs to be copied from/to where?
+"""]]
diff --git a/doc/testimonials/comment_1_2bf439f7a3bc3d6fab91849017946182._comment b/doc/testimonials/comment_1_2bf439f7a3bc3d6fab91849017946182._comment
new file mode 100644
index 000000000..2c5facd1f
--- /dev/null
+++ b/doc/testimonials/comment_1_2bf439f7a3bc3d6fab91849017946182._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gjost"
+ ip="108.205.152.179"
+ subject="distributed digital repository"
+ date="2013-11-14T00:39:49Z"
+ content="""
+I am in the process of building a distributed digital repository using Git and git-annex as a foundation. Our project is to collect and preserve archival-quality audio and video from multiple bandwidth-challenged remote sites. We're using git-annex to help us sneakernet the metadata and binaries around and to maintain multiple copies in geographically separate locations. Git very neatly addresses the problem of tracking changes, while git-annex makes it possible to track the flow of information through a network of distributed repositories.
+"""]]
diff --git a/doc/tips/Decentralized_repository_behind_a_Firewall.mdwn b/doc/tips/Decentralized_repository_behind_a_Firewall.mdwn
index 5dbc8d71a..9e347c73f 100644
--- a/doc/tips/Decentralized_repository_behind_a_Firewall.mdwn
+++ b/doc/tips/Decentralized_repository_behind_a_Firewall.mdwn
@@ -10,22 +10,22 @@ First, install *openssh-server* on your *on-the-go* computer
Then, log into your *home* computer, with *port forwarding*:
- ssh me@myhome.no-ip.org L 2201:localhost:22
+ ssh me@myhome.no-ip.org -R 2201:localhost:22
Your *home* computer can now ssh into your *on-the-go* computer, as long as you keep the above shell running.
You can now add your *on-the-go* computer as a remote on your *home* computer. Use the port forwarding shell you just connected with the command above, if you like.
ssh-keygen -t rsa
- ssh-copy-id me@localhost -p 2201
+ ssh-copy-id "me@localhost -p 2201"
cd ~/annex
- git annex remote add on-the-go ssh://me@localhost:2201/home/myuser/annex
+ git remote add on-the-go ssh://me@localhost:2201/home/myuser/annex
Now you can run normal annex operations, as long as the port forwarding shell is running³.
git annex sync
git annex get on-the-go some/big/file
- git annex status
+ git annex info
You can add more computers by repeating with a different port, e.g. 2202 or 2203 (or any other).
diff --git a/doc/tips/Git_annex_and_Calibre.mdwn b/doc/tips/Git_annex_and_Calibre.mdwn
new file mode 100644
index 000000000..71f955656
--- /dev/null
+++ b/doc/tips/Git_annex_and_Calibre.mdwn
@@ -0,0 +1,120 @@
+The problem
+===========
+
+[Calibre](http://calibre-ebook.com/) is a ebook manager that is
+available in [debian](http://packages.debian.org/sid/calibre). I use
+it to maintain my library, but also to dowload every day an epub
+version of a French newspaper and then put it on my kobo.
+
+Configuring git annex for this
+==============================
+
+I wanted to use git-annex, so
+
+ $ git init
+ $ git annex init "some useful name"
+
+But I don't want every thing in annex, because Calibre use some text
+file to save some metadata, so I used:
+
+ $ git config annex.largefiles "include=* exclude=*.opf exclude=*.json"
+
+then lets add everything
+
+ $ git annex add *
+ $ git add *
+ $ git commit -m "first commit"
+
+Calibre need read and write access on the its database, so let unlock it:
+
+ $ git annex unlock metadata.db
+
+On my other computer I only need to do
+
+ $ git clone $user@$host:Calibre\ library
+ $ cd Calibre\ library
+ $ git annex init "another useful name"
+ $ git annex get .
+ $ git annex unlock metadata.db
+
+The problem is that every time you will `git annex sync`, git annex
+will lock again the metadata.db, so lets unlock it automatically. I
+use git hooks, in `.git/hooks/post-commit` I have
+
+ #!/bin/bash
+
+ git annex edit metadata.db
+
+don't forget to make this file executable
+
+ $ chmod a+x .git/hooks/post-commit
+
+Day to day operation
+====================
+
+ $ git annex add .
+
+Will put new file into the annex
+
+ $ git add .
+
+Will take care of the files that should no go into annex
+
+ $ git annex sync
+
+Will make the repositories exchange informations about all this, and
+make remote change local
+
+ $ git annex get .
+
+Will make remote book locally available
+
+Merge conflict
+--------------
+You should not run calibre on the two computer simultaneously, or
+without syncing before it. If you do, you will have a conflict that
+git-annex will automatically *solve* by rename both of the file.
+
+You can then either:
+
+ - Choose one. If no books have been changed or added on one of the
+ computer, to use the other `metadata.db` will not make you loose
+ any information
+ - rebuild it. `calibredb restore_database` won't do it, but will tell
+ you how to do it.
+
+Checking the library
+--------------------
+You can use `calibredb check_library` to check you library is
+correct. If you use git for it, it will always tell you that it is not
+correct: there is this author ".git" it doesn't know about. Just don't
+care about it.
+
+Maybe this can be solved by using `vcsh` but apparently
+`vcsh`+`git annex` it not well tested yet.
+
+Automatic stuff
+---------------
+I use `mr` to automatically run all this, but some config could be
+done (I believe) to have `git annex copy --auto` do what it should.
+
+There are also the git annex assistant for this kind of automatic
+synchronizations of contents, but I don't know if my automatic
+unlocking of one file will break this.
+
+It might be interesting to find someway to unlock and lock the library
+only when running calibre, a simple script to launch calibre will do
+that. Note that each time you will lock and unlock, you will have a
+new commit in git.
+
+Another solution
+===================
+You could also use direct mode in place of the auto unlock feature
+
+ git annex direct
+
+The remove the `post-commit` git hook (or do not add it). Its a
+simpler solution, but remember that interaction between git annex direct
+repositories and plain git are complex and sometimes downright dangerous. See [[direct mode]] for details.
+
+In particular, do *not* called `git add *` in the above steps, as that will commit all books into git.
diff --git a/doc/tips/Internet_Archive_via_S3.mdwn b/doc/tips/Internet_Archive_via_S3.mdwn
index d7893693f..eba28961d 100644
--- a/doc/tips/Internet_Archive_via_S3.mdwn
+++ b/doc/tips/Internet_Archive_via_S3.mdwn
@@ -30,12 +30,6 @@ rather than having git-annex pick a random one; and you can optionally
specify `x-archive-meta*` headers to add metadata as explained in their
[documentation](http://www.archive.org/help/abouts3.txt).
-[[!template id=note text="""
-/!\ There seems to be a bug in either hS3 or the archive that breaks
-authentication when the bucket name contains spaces or upper-case letters..
-use all lowercase and no spaces when making the bucket with `initremote`.
-"""]]
-
# git annex initremote archive-panama type=S3 \
host=s3.us.archive.org bucket=panama-canal-lock-blueprints \
x-archive-meta-mediatype=texts x-archive-meta-language=eng \
@@ -51,8 +45,14 @@ Then you can annex files and copy them to the remote as usual:
# git annex copy photo1.jpeg --fast --to archive-panama
copy (to archive-panama...) ok
-Note the use of the SHA1E [[backend|backends]]. It makes most sense
-to use the WORM or SHA1E backend for files that will be stored in
-the Internet Archive, since the key name will be exposed as the filename
-there, and since the Archive does special processing of files based on
-their extension.
+Once a file has been stored on archive.org, it cannot be (easily) removed
+from it. Also, git-annex whereis will tell you a public url for the file
+on archive.org. (It may take a while for archive.org to make the file
+publically visibile.)
+
+Note the use of the SHA1E [[backend|backends]] when adding files. That is
+the default backend used by git-annex, but even if you don't normally use
+it, it makes most sense to use the WORM or SHA1E backend for files that
+will be stored in the Internet Archive, since the key name will be exposed
+as the filename there, and since the Archive does special processing of
+files based on their extension.
diff --git a/doc/tips/Internet_Archive_via_S3/comment_1_d53a3848c20dce61867283fc03c2adaa._comment b/doc/tips/Internet_Archive_via_S3/comment_1_d53a3848c20dce61867283fc03c2adaa._comment
new file mode 100644
index 000000000..7c2ce48fc
--- /dev/null
+++ b/doc/tips/Internet_Archive_via_S3/comment_1_d53a3848c20dce61867283fc03c2adaa._comment
@@ -0,0 +1,34 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="how to use with simply addurl?"
+ date="2013-10-09T22:27:27Z"
+ content="""
+It doesn't seem like git annex addurl by itself supports the archive.org urls...
+
+[[!format txt \"\"\"
+anarcat@marcos:presentations$ git annex addurl --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+ failed to verify url exists: http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+failed
+git-annex: addurl: 1 failed
+\"\"\"]]
+
+I also tried the \"details\" url (<http://archive.org/details/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia>) - but that just downloads the webpage, not the video either...
+
+Even the ultimate video URL doesn't work:
+
+[[!format txt \"\"\"
+anarcat@marcos:presentations$ git annex addurl --debug --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+[2013-10-09 18:26:30 EDT] call: quvi [\"-v\",\"mute\",\"--support\",\"http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm\"]
+addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm [2013-10-09 18:26:30 EDT] read: curl [\"-s\",\"--head\",\"-L\",\"http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm\",\"-w\",\"%{http_code}\"]
+
+ failed to verify url exists: http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
+failed
+git-annex: addurl: 1 failed
+\"\"\"]]
+
+... even though that URL actually gives out a proper 200 OK response code.
+
+Any ideas? --[[anarcat]]
+"""]]
diff --git a/doc/tips/Internet_Archive_via_S3/comment_2_91c1472da27b00e5d682d22bc1ef04e0._comment b/doc/tips/Internet_Archive_via_S3/comment_2_91c1472da27b00e5d682d22bc1ef04e0._comment
new file mode 100644
index 000000000..9b4ac58b2
--- /dev/null
+++ b/doc/tips/Internet_Archive_via_S3/comment_2_91c1472da27b00e5d682d22bc1ef04e0._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.4.22"
+ subject="comment 2"
+ date="2013-10-11T17:08:27Z"
+ content="""
+This was a misleading error message. The url you are trying to add to the file does not match the size recorded for the file already in the annex. (Or possibly the file's key has no recorded size). If you really want to add the url to the file despite it being a different encoding, you can use --relaxed, although fsck may not like the result if you ever end up downloading that url..
+
+(Please file bug reports for problems in the future, rather than posting comments on only vaguely related pages which as we can see here can turn out to be entirely offtopic.)
+"""]]
diff --git a/doc/tips/Internet_Archive_via_S3/comment_3_e23cf781c532f80d47d52265f2b2c87e._comment b/doc/tips/Internet_Archive_via_S3/comment_3_e23cf781c532f80d47d52265f2b2c87e._comment
new file mode 100644
index 000000000..3745d544c
--- /dev/null
+++ b/doc/tips/Internet_Archive_via_S3/comment_3_e23cf781c532f80d47d52265f2b2c87e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="still a bug, filed separately!"
+ date="2013-10-11T18:49:06Z"
+ content="""
+Aaah, of course, sorry for the noise here. It turns out that this is *not* because the filesize (or even the checksum, for that matter) are different, so there's clearly a bug there, and i filed it in [[bugs/addurl_fails_on_the_internet_archive]]. Thanks!
+"""]]
diff --git a/doc/tips/assume-unstaged.mdwn b/doc/tips/assume-unstaged.mdwn
index 536772c89..63f5f820a 100644
--- a/doc/tips/assume-unstaged.mdwn
+++ b/doc/tips/assume-unstaged.mdwn
@@ -11,7 +11,7 @@ annoyingly slow, you can turn it on:
git config core.ignoreStat true
-When git mv and git rm are used, those changes *do* get noticed, even
+When `git mv` and `git rm` are used, those changes *do* get noticed, even
on assume-unchanged files. When new files are added, eg by `git annex add`,
they are also noticed.
diff --git a/doc/tips/assume-unstaged/comment_2_5b589f37cfc03bf7be33a51826cc4dba._comment b/doc/tips/assume-unstaged/comment_2_5b589f37cfc03bf7be33a51826cc4dba._comment
new file mode 100644
index 000000000..474d7b399
--- /dev/null
+++ b/doc/tips/assume-unstaged/comment_2_5b589f37cfc03bf7be33a51826cc4dba._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnxlx1UrzVhdy6_gFjzmF42x6QXxBUxg00"
+ nickname="Jakukyo"
+ subject="comment 2"
+ date="2013-09-05T12:14:42Z"
+ content="""
+> There are two gotchas...
+
+So just always run `git annex add` after editing a file
+and `git update-index --really-refresh` after migrating
+backend?
+
+"""]]
diff --git a/doc/tips/beware_of_SSD_wear_when_doing_fsck_on_large_special_remotes/comment_3_72d222020af4a9c6c753eb1ee7e1f1cf._comment b/doc/tips/beware_of_SSD_wear_when_doing_fsck_on_large_special_remotes/comment_3_72d222020af4a9c6c753eb1ee7e1f1cf._comment
new file mode 100644
index 000000000..2624a4fd3
--- /dev/null
+++ b/doc/tips/beware_of_SSD_wear_when_doing_fsck_on_large_special_remotes/comment_3_72d222020af4a9c6c753eb1ee7e1f1cf._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="46.239.117.180"
+ subject="comment 3"
+ date="2013-08-19T01:05:40Z"
+ content="""
+A nice feature would be to perform the `fsck` on the (encrypted) remote itself, as it would avoid to clutter either the network or the tmpdir. However, that requires some changes in git-annex's backend. Indeed it would no longer be enough to store a single digest per (plain) file: a new digest needs to be stored for each encrypted copy. It is not necessarily a big deal, but the backend would need to be reorganized carefully.
+"""]]
diff --git a/doc/tips/centralized_git_repository_tutorial/comment_1_9072ebc0c61446d7b151fcfab616fea9._comment b/doc/tips/centralized_git_repository_tutorial/comment_1_9072ebc0c61446d7b151fcfab616fea9._comment
new file mode 100644
index 000000000..c509d7579
--- /dev/null
+++ b/doc/tips/centralized_git_repository_tutorial/comment_1_9072ebc0c61446d7b151fcfab616fea9._comment
@@ -0,0 +1,33 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkC0W3ZQERUaTkHoks6k68Tsp1tz510nGo"
+ nickname="Georg"
+ subject="sync, push, pull with/to/from centralized bare repository"
+ date="2013-10-07T06:45:19Z"
+ content="""
+Hi Joey,
+
+thanks for tutorial with the centralized repo. I am currently trying to set up a central bare repo for two clients (they cannot communicate directly with each other). I am not sure if I am pushing/pulling the right way.
+
+On the server I did:
+
+ git init --bare
+ git annex init origin
+
+On Cĺient Alice (I want to give Bob a chance get call \"git annex get\" from \"origin\"):
+
+ git clone ssh://tktest@192.168.56.104/~/annex .
+ git annex init Alice
+ git annex merge
+ git annex add .
+ git commit -a -m \"Added tutorial\"
+ git push origin master git-annex
+ git annex copy . --to origin
+
+On Client Bob I have called \"clone, init, merge, add, push, copy\" also.
+
+Now the tricky part - do I have to call \"git annex sync\" at Alice's side to get the updates from Bob over origin?
+I ran into troubles if I called \"copy --to origin\" before \"git push origin master git-annex\". How can I resolve a non-fast-forware on the git-annex branch?
+Some notes about how to sync over a central bare repo would be nice here =)
+
+Thanks a lot, Georg
+"""]]
diff --git a/doc/tips/centralized_git_repository_tutorial/comment_2_528e92b21f0551fde4adb956654953ae._comment b/doc/tips/centralized_git_repository_tutorial/comment_2_528e92b21f0551fde4adb956654953ae._comment
new file mode 100644
index 000000000..21b286fff
--- /dev/null
+++ b/doc/tips/centralized_git_repository_tutorial/comment_2_528e92b21f0551fde4adb956654953ae._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.253.80"
+ subject="How can I resolve a non-fast-forware on the git-annex branch?"
+ date="2013-10-07T17:08:32Z"
+ content="""
+By either running `git annex sync`, or if you want to pull and push yourself, by running `git annex merge` before pushing.
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_11_d8d77048c7e2524968c188e1ad517873._comment b/doc/tips/downloading_podcasts/comment_11_d8d77048c7e2524968c188e1ad517873._comment
new file mode 100644
index 000000000..fd3459926
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_11_d8d77048c7e2524968c188e1ad517873._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="220.244.41.108"
+ subject="comment 11"
+ date="2013-08-06T04:20:16Z"
+ content="""
+ $ cabal install feed
+ Resolving dependencies...
+ All the requested packages are already installed:
+ feed-0.3.9.1
+ Use --reinstall if you want to reinstall anyway.
+
+Then I reinstalled `git-annex` but it still doesn't find the feeds flag.
+
+ $ git annex version
+ git-annex version: 4.20130802
+ build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS
+
+Do I need to do something like:
+
+ cabal install git-annex --bindir=$HOME/bin -f\"-assistant -webapp -webdav -pairing -xmpp -dns -feed\"
+
+...but what are the default flags to include in addition to `-feed`
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_12_0859317471b43c88744dd3df95c879f7._comment b/doc/tips/downloading_podcasts/comment_12_0859317471b43c88744dd3df95c879f7._comment
new file mode 100644
index 000000000..e75a44a8c
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_12_0859317471b43c88744dd3df95c879f7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 12"
+ date="2013-08-06T04:24:10Z"
+ content="""
+-f-Feed will disable the feature. -fFeed will try to force it on.
+
+You can probably work out what's going wrong using cabal install -v3
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_13_e8c3c97282d17e2a1d47fb9d5e2b2f7b._comment b/doc/tips/downloading_podcasts/comment_13_e8c3c97282d17e2a1d47fb9d5e2b2f7b._comment
new file mode 100644
index 000000000..8d1242818
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_13_e8c3c97282d17e2a1d47fb9d5e2b2f7b._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="http://a-or-b.myopenid.com/"
+ ip="220.244.41.108"
+ subject="comment 13"
+ date="2013-08-06T05:42:45Z"
+ content="""
+So I ran `cabal install -v3` and looked at the output,
+
+ Flags chosen: feed=True, tdfa=True, testsuite=True, android=False,
+ production=True, dns=True, xmpp=True, pairing=True, webapp=True,
+ assistant=True, dbus=True, inotify=True, webdav=True, s3=True
+
+This looks like feed should be on.
+
+There doesn't appear to be any errors in the compile either.
+
+Is it as simple as a bug where this flag just doesn't show in the `git annex version` command?
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_14_05a3694052de36848fbbad6eeeada895._comment b/doc/tips/downloading_podcasts/comment_14_05a3694052de36848fbbad6eeeada895._comment
new file mode 100644
index 000000000..4bc831f7f
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_14_05a3694052de36848fbbad6eeeada895._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 14"
+ date="2013-08-07T16:03:12Z"
+ content="""
+Yes, it did turn out to be as simple as my having forgotten that I have to manually add features to the version list.
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_15_21028bed8858c2dae1ac9c2d014fd2a1._comment b/doc/tips/downloading_podcasts/comment_15_21028bed8858c2dae1ac9c2d014fd2a1._comment
new file mode 100644
index 000000000..0f998d066
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_15_21028bed8858c2dae1ac9c2d014fd2a1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://23.gs/"
+ ip="46.165.197.5"
+ subject="No file extension?"
+ date="2013-08-12T13:21:50Z"
+ content="""
+It seems git-annex is a bit overzealous when sanitizing the file extension, currently I get: \"Nerdkunde/Let_s_go_to_the_D_M_C_A_m4a\" from http://www.nerdkunde.de/episodes.m4a.rss with the default template and only \"Nerdkunde/Let_s_go_to_the_D_M_C_A._m4a\" if I add the \".\" in the template myself...
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_16_4869fb5c9f896acc477c44de06c36ca7._comment b/doc/tips/downloading_podcasts/comment_16_4869fb5c9f896acc477c44de06c36ca7._comment
new file mode 100644
index 000000000..4419d02a8
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_16_4869fb5c9f896acc477c44de06c36ca7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="arand"
+ ip="130.243.226.21"
+ subject="comment 16"
+ date="2013-08-12T13:32:46Z"
+ content="""
+The filename extension is a known issue and already fixed in the development version, see <http://git-annex.branchable.com/bugs/importfeed_uses___34____95__foo__34___as_extension/>
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_17_2e278ff200c1c15efd27c46a3e0aed40._comment b/doc/tips/downloading_podcasts/comment_17_2e278ff200c1c15efd27c46a3e0aed40._comment
new file mode 100644
index 000000000..bc49e5dd0
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_17_2e278ff200c1c15efd27c46a3e0aed40._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlpKmTa1OPwy5Jk24pOoD8Vlo2jahzTPnw"
+ nickname="Stephen"
+ subject="rss authentication"
+ date="2013-08-13T13:32:52Z"
+ content="""
+If a podcast requires authentication, is there a way to pass credentials through? I tried `http://user:pass@site.com/rss.xml` but it didn't work.
+
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_18_382f2b970738d9b1af577955c3083e90._comment b/doc/tips/downloading_podcasts/comment_18_382f2b970738d9b1af577955c3083e90._comment
new file mode 100644
index 000000000..9e3244315
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_18_382f2b970738d9b1af577955c3083e90._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://www.joachim-breitner.de/"
+ nickname="nomeata"
+ subject="--fast and --relaxed"
+ date="2013-08-16T07:27:59Z"
+ content="""
+Hi,
+
+the explanations to --fast and --relaxed on this page could be extended a bit. I looked it up in the man page, but it is not yet clear to me when I would use one or the other with feeds. Also, does “Next time you run git annex addurl it will only fetch any new items.” really only apply to --relaxed, and not --fast?
+
+Furthermore, it would be good if there were a template variable `itemnum` that I can use to ensure that `ls` prints the casts in the right order, even when the titles of the items are not helpful.
+
+Greetings,
+Joachim
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_19_f76fc6835e5787b0156380bf09fd81ca._comment b/doc/tips/downloading_podcasts/comment_19_f76fc6835e5787b0156380bf09fd81ca._comment
new file mode 100644
index 000000000..41313a87d
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_19_f76fc6835e5787b0156380bf09fd81ca._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 19"
+ date="2013-08-22T15:25:02Z"
+ content="""
+I would expect user:pass@site.com to work if the site is using http basic auth. `importfeed` just runs `wget` (or `curl`) to do all downloads, and wget's documentation says that works. It also says you can use ~/.netrc to store the password for a site.
+"""]]
diff --git a/doc/tips/downloading_podcasts/comment_20_65ebf3a3bbf0a2aebd2b69640b757e16._comment b/doc/tips/downloading_podcasts/comment_20_65ebf3a3bbf0a2aebd2b69640b757e16._comment
new file mode 100644
index 000000000..6060be655
--- /dev/null
+++ b/doc/tips/downloading_podcasts/comment_20_65ebf3a3bbf0a2aebd2b69640b757e16._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 20"
+ date="2013-08-22T15:29:11Z"
+ content="""
+The git-annex man page has a bit more to say about --relaxed and --fast. Their behavior when used with `importfeed` is the same as with `addurl`.
+
+If the podcast feed provides an `itemid`, you can use that in the filename template. I don't know how common that is. Due to the way `importfeed` works, it cannot keep track of eg, an incrementing item number itself.
+"""]]
diff --git a/doc/tips/finding_duplicate_files/comment_10_2ed5aa8c632048b13e01d358883fa383._comment b/doc/tips/finding_duplicate_files/comment_10_2ed5aa8c632048b13e01d358883fa383._comment
new file mode 100644
index 000000000..77a308b90
--- /dev/null
+++ b/doc/tips/finding_duplicate_files/comment_10_2ed5aa8c632048b13e01d358883fa383._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmTNrhkVQ26GBLaLD5-zNuEiR8syTj4mI8"
+ nickname="Juan"
+ subject="comment 10"
+ date="2013-08-31T18:20:58Z"
+ content="""
+I'm already spreading the word. Handling scientific papers, data, simulations and code has been quite a challenge during my academic career. While code was solved long ago, the three first items remained a huge problem.
+I'm sure many of my colleagues will be happy to use it.
+Is there any hashtag or twitter account? I've seen that you collected some of my tweets, but I don't know how you did it. Did you search for git-annex?
+Best,
+ Juan
+"""]]
diff --git a/doc/tips/finding_duplicate_files/comment_8_3af51722da0980b724facb184f0f66e9._comment b/doc/tips/finding_duplicate_files/comment_8_3af51722da0980b724facb184f0f66e9._comment
new file mode 100644
index 000000000..26c34fcfa
--- /dev/null
+++ b/doc/tips/finding_duplicate_files/comment_8_3af51722da0980b724facb184f0f66e9._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmTNrhkVQ26GBLaLD5-zNuEiR8syTj4mI8"
+ nickname="Juan"
+ subject="This is an awesome feature"
+ date="2013-08-28T13:40:23Z"
+ content="""
+Thanks. I have quite a lot of papers in PDF formats. Now I'm saving space, have them controlled, synchronized with many devices and found more than 200 duplicates.
+Is there a way to donate to the project? You really deserve it.
+Thanks.
+"""]]
diff --git a/doc/tips/finding_duplicate_files/comment_9_7b4b78a5cd253abfe4f6001049bf64f3._comment b/doc/tips/finding_duplicate_files/comment_9_7b4b78a5cd253abfe4f6001049bf64f3._comment
new file mode 100644
index 000000000..a20ca16ed
--- /dev/null
+++ b/doc/tips/finding_duplicate_files/comment_9_7b4b78a5cd253abfe4f6001049bf64f3._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.8.7"
+ subject="comment 9"
+ date="2013-08-28T20:25:20Z"
+ content="""
+@Juan the best thing to do is tell people about git-annex, help them use it, and file bug reports. Just generally be part of the git-annex community.
+
+(If you really want to donate to me, <http://campaign.joeyh.name/> is still open.)
+"""]]
diff --git a/doc/tips/flickrannex.mdwn b/doc/tips/flickrannex.mdwn
index 47d834177..d8e54b4c3 100644
--- a/doc/tips/flickrannex.mdwn
+++ b/doc/tips/flickrannex.mdwn
@@ -1,3 +1,4 @@
+# Latest version 0.1.10
Hook program for gitannex to use flickr as backend.
This allows storing any type of file on flickr, not only images and movies.
@@ -10,7 +11,7 @@ Credit for the flickr api interface goes to: <http://stuvel.eu/flickrapi>
Credit for the png library goes to: <https://github.com/drj11/pypng>
Credit for the png tEXt patch goes to: <https://code.google.com/p/pypng/issues/detail?id=65>
-## Install
+# Install
Clone the git repository in your home folder.
@@ -18,7 +19,7 @@ Clone the git repository in your home folder.
This should make a ~/flickrannex folder
-## Setup
+# Setup
Run the program once to set it up.
@@ -26,24 +27,36 @@ Run the program once to set it up.
After the setup has finished, it will print the git-annex configure lines.
-## Configuring git-annex
+# Configuring git-annex
git config annex.flickr-hook '/usr/bin/python2 ~/flickrannex/flickrannex.py'
git annex initremote flickr type=hook hooktype=flickr encryption=shared
git annex describe flickr "the flickr library"
-## Notes
+# Notes
-### Unencrypted mode
+## Unencrypted mode
+The photo name on flickr is currently the GPGHMACSHA1 version.
-The photo name on flickr is currently the [[key|backends]] used by git-annex.
+Run the following command in your annex directory
+ git annex wanted flickr uuid include=*.jpg or include=*.jpeg or include=*.gif or include=*.png
-### Encrypted mode
+## Encrypted mode
+The current version base64 encodes all the data, which results in ~35% larger filesize.
-The current version base64 encodes all the data, which results in ~35%
-larger filesize.
+I might look into yyenc instead. I'm not sure if it will work in the tEXt field.
-I might look into yyenc instead. I'm not sure if it will work in the tEXt
-field.
+Run the following command in your annex directory
+ git annex wanted flickr exclude=largerthan=30mb
--- Tobias
+## Including directories as tags
+Get get each of the directories below the top level git directory added as tags to uploads:
+
+ git config annex.flickr-hook 'GIT_TOP_LEVEL=`git rev-parse --show-toplevel` /usr/bin/python2 %s/flickrannex.py'
+
+In this case the image:
+ /home/me/annex-photos/holidays/2013/Greenland/img001.jpg
+would get the following tags: "holidays" "2013" "Greenland"
+(assuming "/home/me/annex-photos" is the top level in the annex...)
+
+Caveat Emptor - Tags will *always* be NULL for indirect repos - we don't (easily) know the human-readable file name.
diff --git a/doc/tips/flickrannex/comment_13_1596e70dca71c853fd1d6fc9bde02b18._comment b/doc/tips/flickrannex/comment_13_1596e70dca71c853fd1d6fc9bde02b18._comment
new file mode 100644
index 000000000..19faa585e
--- /dev/null
+++ b/doc/tips/flickrannex/comment_13_1596e70dca71c853fd1d6fc9bde02b18._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="Version 0.1.10 pushed"
+ date="2013-09-11T20:31:25Z"
+ content="""
+Since the initial release of this hook a lot of issues have been fixed, and a few features added.
+
+I would highly suggest that everyone who is using this hook update to the latest version as i would consider one of the bugs to be fairly major.
+
+
+"""]]
diff --git a/doc/tips/flickrannex/comment_13_cf9dad91ee7d334c720adb3310aa0003._comment b/doc/tips/flickrannex/comment_13_cf9dad91ee7d334c720adb3310aa0003._comment
deleted file mode 100644
index 71d44aff5..000000000
--- a/doc/tips/flickrannex/comment_13_cf9dad91ee7d334c720adb3310aa0003._comment
+++ /dev/null
@@ -1,130 +0,0 @@
-[[!comment format=mdwn
- username="https://www.google.com/accounts/o8/id?id=AItOawnaH44G3QbxBAYyDwy0PbvL0ls60XoaR3Y"
- nickname="Nigel"
- subject="re: git annex get failed -- debug"
- date="2013-08-02T15:28:41Z"
- content="""
-With debug turned on.
-
-[[!format bash \"\"\"
-
-initremote flickr (encryption setup) (shared cipher) ok
-(Recording state in git...)
-describe flickr ok
-(Recording state in git...)
-/home/nrb/repos/annex/laptop-annex
-fsck walkthrough.sh (checksum...) ok
-fsck walkthrough.sh~ (checksum...) ok
-/home/nrb/repos/annex/laptop-annex
-copy walkthrough.sh (gpg) (checking flickr...) 16:18:52 [flickrannex-0.1.5] <module> : 'START'
-16:18:52 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=checkpresent ANNEX_KEY=GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 ANNEX_HASH_1=kQ ANNEX_HASH_2=0P /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:18:52 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:18:52 [flickrannex-0.1.5] readFile : 'Done'
-16:18:52 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:18:54 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:18:54 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:18:55 [flickrannex-0.1.5] main : 'Error. found nothing:{'pages': '1', 'cancreate': '1', 'total': '0', 'page': '1', 'perpage': '0'}'
-16:18:55 [flickrannex-0.1.5] checkFile : 'GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 - u'gitannex' - '8086216@N08''
-16:18:55 [flickrannex-0.1.5] checkFile : 'No set exists, thus no files exists'
-16:18:55 [flickrannex-0.1.5] <module> : 'STOP: 2s'
-(to flickr...)
-16:18:55 [flickrannex-0.1.5] <module> : 'START'
-16:18:55 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=store ANNEX_KEY=GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 ANNEX_HASH_1=kQ ANNEX_HASH_2=0P ANNEX_FILE=/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:18:55 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:18:55 [flickrannex-0.1.5] readFile : 'Done'
-16:18:55 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:18:57 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:18:58 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:18:58 [flickrannex-0.1.5] main : 'Error. found nothing:{'pages': '1', 'cancreate': '1', 'total': '0', 'page': '1', 'perpage': '0'}'
-16:18:58 [flickrannex-0.1.5] postFile : '/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 to u'gitannex' - GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0'
-16:18:58 [flickrannex-0.1.5] postFile : 'pre /home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 size: 1047 more than 40234050.'
-16:18:58 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0' - 'rb''
-16:18:58 [flickrannex-0.1.5] readFile : 'Done'
-16:18:58 [flickrannex-0.1.5] postFile : 'Uploading: /home/nrb/repos/gits/flickrannex/temp/encoded-GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0'
-/home/nrb/repos/gits/flickrannex/flickrannex.py:92: FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
- if res:
-/home/nrb/repos/gits/flickrannex/flickrannex.py:100: FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
- if res:
-16:19:01 [flickrannex-0.1.5] postFile : 'Done: <Element 'rsp' at 0x8726b0c>'
-16:19:01 [flickrannex-0.1.5] <module> : 'STOP: 5s'
-ok
-copy walkthrough.sh~ (checking flickr...) 16:19:01 [flickrannex-0.1.5] <module> : 'START'
-16:19:01 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=checkpresent ANNEX_KEY=GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 ANNEX_HASH_1=m5 ANNEX_HASH_2=kz /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:19:01 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:19:01 [flickrannex-0.1.5] readFile : 'Done'
-16:19:01 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:19:03 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:19:03 [flickrannex-0.1.5] main : 'Photoset gitannex found: <Element 'photoset' at 0x98264ec>'
-16:19:03 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:19:03 [flickrannex-0.1.5] checkFile : 'GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 - 72157634897264995L - '8086216@N08''
-16:19:03 [flickrannex-0.1.5] checkFile : 'No set exists, thus no files exists'
-16:19:03 [flickrannex-0.1.5] <module> : 'STOP: 1s'
-(to flickr...)
-16:19:03 [flickrannex-0.1.5] <module> : 'START'
-16:19:03 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=store ANNEX_KEY=GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 ANNEX_HASH_1=m5 ANNEX_HASH_2=kz ANNEX_FILE=/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:19:03 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:19:03 [flickrannex-0.1.5] readFile : 'Done'
-16:19:03 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:19:05 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:19:05 [flickrannex-0.1.5] main : 'Photoset gitannex found: <Element 'photoset' at 0x913a54c>'
-16:19:05 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:19:05 [flickrannex-0.1.5] postFile : '/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 to 72157634897264995L - GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9'
-16:19:05 [flickrannex-0.1.5] postFile : 'pre /home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 size: 1044 more than 40234050.'
-16:19:05 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/annex/laptop-annex/.git/annex/tmp/GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9' - 'rb''
-16:19:05 [flickrannex-0.1.5] readFile : 'Done'
-16:19:05 [flickrannex-0.1.5] postFile : 'Uploading: /home/nrb/repos/gits/flickrannex/temp/encoded-GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9'
-/home/nrb/repos/gits/flickrannex/flickrannex.py:92: FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
- if res:
-/home/nrb/repos/gits/flickrannex/flickrannex.py:100: FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
- if res:
-16:19:08 [flickrannex-0.1.5] postFile : 'Done: <Element 'rsp' at 0x913f0cc>'
-16:19:08 [flickrannex-0.1.5] <module> : 'STOP: 4s'
-ok
-(Recording state in git...)
-nrb@nrb-ThinkPad-T61:~/repos/annex/laptop-annex$ git annex whereis
-whereis walkthrough.sh (3 copies)
- 86491ded-899c-425d-9470-bf446cb06db1 -- flickr (the flickr library)
- 8e766014-7154-4f4f-a04b-9d1b3d333db1 -- here (my laptop)
- eed7055b-743b-4ab6-a390-29cfd326005d -- usbdrive (portable USB drive)
-ok
-whereis walkthrough.sh~ (3 copies)
- 86491ded-899c-425d-9470-bf446cb06db1 -- flickr (the flickr library)
- 8e766014-7154-4f4f-a04b-9d1b3d333db1 -- here (my laptop)
- eed7055b-743b-4ab6-a390-29cfd326005d -- usbdrive (portable USB drive)
-ok
-nrb@nrb-ThinkPad-T61:~/repos/annex/laptop-annex$ git annex fsck --from flickr
-fsck walkthrough.sh (gpg) (checking flickr...) 16:22:57 [flickrannex-0.1.5] <module> : 'START'
-16:22:57 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=checkpresent ANNEX_KEY=GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 ANNEX_HASH_1=kQ ANNEX_HASH_2=0P /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:22:57 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:22:57 [flickrannex-0.1.5] readFile : 'Done'
-16:22:57 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:22:58 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:22:59 [flickrannex-0.1.5] main : 'Photoset gitannex found: <Element 'photoset' at 0x896d92c>'
-16:22:59 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:22:59 [flickrannex-0.1.5] checkFile : 'GPGHMACSHA1--280dd2d5003ad3962b1ecaa52ba45fdd44381fd0 - 72157634897264995L - '8086216@N08''
-16:22:59 [flickrannex-0.1.5] checkFile : 'No set exists, thus no files exists'
-16:22:59 [flickrannex-0.1.5] <module> : 'STOP: 2s'
-(fixing location log)
- ** Based on the location log, walkthrough.sh
- ** was expected to be present, but its content is missing.
-failed
-fsck walkthrough.sh~ (checking flickr...) 16:22:59 [flickrannex-0.1.5] <module> : 'START'
-16:22:59 [flickrannex-0.1.5] main : 'ARGS: 'ANNEX_ACTION=checkpresent ANNEX_KEY=GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 ANNEX_HASH_1=m5 ANNEX_HASH_2=kz /home/nrb/repos/gits/flickrannex/flickrannex.py --dbglevel 1 --stderr''
-16:22:59 [flickrannex-0.1.5] readFile : ''/home/nrb/repos/gits/flickrannex/flickrannex.conf' - 'r''
-16:22:59 [flickrannex-0.1.5] readFile : 'Done'
-16:22:59 [flickrannex-0.1.5] login : 'nrbray@yahoo.com'
-16:23:01 [flickrannex-0.1.5] login : 'Done: '72157633920418017-5c0274bd421d7bb1' - None - '8086216@N08''
-16:23:01 [flickrannex-0.1.5] main : 'Photoset gitannex found: <Element 'photoset' at 0x869992c>'
-16:23:01 [flickrannex-0.1.5] main : 'Trying page: 1'
-16:23:01 [flickrannex-0.1.5] checkFile : 'GPGHMACSHA1--131f95d3bc932d23ef6af47cf49db3c04be4f0f9 - 72157634897264995L - '8086216@N08''
-16:23:01 [flickrannex-0.1.5] checkFile : 'No set exists, thus no files exists'
-16:23:01 [flickrannex-0.1.5] <module> : 'STOP: 1s'
-(fixing location log)
- ** Based on the location log, walkthrough.sh~
- ** was expected to be present, but its content is missing.
-failed
-(Recording state in git...)
-git-annex: fsck: 2 failed
-
-\"\"\" ]]
-"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt.mdwn b/doc/tips/fully_encrypted_git_repositories_with_gcrypt.mdwn
new file mode 100644
index 000000000..5934747f0
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt.mdwn
@@ -0,0 +1,127 @@
+[git-remote-gcrypt](https://github.com/joeyh/git-remote-gcrypt/)
+adds support for encrypted remotes to git. The git-annex
+[[gcrypt special remote|special_remotes/gcrypt]] allows git-annex to
+also store its files in such repositories. Naturally, git-annex encrypts
+the files it stores too, so everything stored on the remote is encrypted.
+
+Here are some ways you can use this awesome stuff..
+
+[[!toc ]]
+
+This page will show how to set it up at the command line, but the git-annex
+[[assistant]] can also be used to help you set up encrypted git
+repositories.
+
+## prerequisites
+
+* Install
+[git-remote-gcrypt](https://github.com/joeyh/git-remote-gcrypt/)
+* Install git-annex version 4.20130909 or newer.
+
+## encrypted backup drive
+
+Let's make a USB drive into an encrypted backup repository. It will contain
+both the full contents of your git repository, and all the files you
+instruct git-annex to store on it, and everything will be encrypted so that
+only you can see it.
+
+First, you need to set up a gpg key. You might consider generating a
+special purpose key just for this use case, since you may end up wanting to
+put the key on multiple machines that you would not trust with your
+main gpg key.
+
+You need to tell git-annex the keyid of the key when setting up the
+encrypted repository:
+
+ git init --bare /mnt/encryptedbackup
+ git annex initremote encryptedbackup type=gcrypt gitrepo=/mnt/encryptedbackup keyid=$mykey
+ git annex sync encryptedbackup
+
+Now you can copy (or even move) files to the repository. After
+sending files to it, you'll probably want to do a sync, which pushes
+the git repository changes to it as well.
+
+ git annex copy --to encryptedbackup ...
+ git annex sync encryptedbackup
+
+Note that if you lose your gpg key, it will be *impossible* to get the
+data out of your encrypted backup. You need to find a secure way to store a
+backup of your gpg key. Printing it out and storing it in a safe deposit box,
+for example.
+
+You can actually specifiy keyid= as many times as you like to allow any one
+of a set of gpg keys to access this repository. So you could add a friend's
+key, or another gpg key you have.
+
+To restore from the backup, just plug the drive into any machine that has
+the gpg key used to encrypt it, and then:
+
+ git clone gcrypt::/mnt/encryptedbackup restored
+ cd restored
+ git annex enableremote encryptedbackup gitrepo=/mnt/encryptedbackup
+ git annex get --from encryptedbackup
+
+## encrypted git-annex repository on a ssh server
+
+If you have a ssh server that has rsync installed, you can set up an
+encrypted repository there. Works just like the encrypted drive except
+without the cable.
+
+First, on the server, run:
+
+ git init --bare encryptedrepo
+
+(Also, install git-annex on the server if it's possible & easy to do so.
+While this will work without git-annex being installed on the server, it
+is recommended to have it installed.)
+
+Now, in your existing git-annex repository, set up the encrypted remote:
+
+ git annex initremote encryptedrepo type=gcrypt gitrepo=ssh://my.server/home/me/encryptedrepo keyid=$mykey
+ git annex sync encryptedrepo
+
+If you're going to be sharing this repository with others, be sure to also
+include their keyids, by specifying keyid= repeatedly.
+
+Now you can copy (or even move) files to the repository. After
+sending files to it, you'll probably want to do a sync, which pushes
+the git repository changes to it as well.
+
+ git annex copy --to encryptedrepo ...
+ git annex sync encryptedbackup
+
+Anyone who has access to the repo it and has one of the keys
+used to encrypt it can check it out:
+
+ git clone gcrypt::ssh://my.server/home/me/encryptedrepo myrepo
+ cd myrepo
+ git annex enableremote encryptedrepo gitrepo=ssh://my.server/home/me/encryptedrepo
+ git annex get --from encryptedrepo
+
+## private encrypted git remote on hosting site
+
+You can use gcrypt to store your git repository in encrypted form on any
+hosting site that supports git. Only you can decrypt its contents.
+Using it this way, git-annex does not store large files on the hosting site; it's
+only used to store your git repository itself.
+
+ git remote add encrypted gcrypt::ssh://hostingsite/myrepo.git
+ git push encrypted master git-annex
+
+Now you can carry on using git-annex with your new repository. For example,
+`git annex sync` will sync with it.
+
+To check out the repository from the hosting site, use the same gcrypt::
+url you used when setting it up:
+
+ git clone gcrypt::ssh://hostingsite/myrepo.git
+
+## multiuser encrypted git remote on hosting site
+
+Suppose two users want to share an encrypted git remote. Both of you
+need to set up the remote, and configure gcrypt to encrypt it so that both
+of you can see it.
+
+ git remote add sharedencrypted gcrypt::ssh://hostingsite/myrepo.git
+ git config remote.sharedencrypted.gcryt-participants "$mykey $friendkey"
+ git config git push sharedencrypted master git-annex
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_10_4440a80d64c60c7312d5c405d54e607a._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_10_4440a80d64c60c7312d5c405d54e607a._comment
new file mode 100644
index 000000000..4ee70bcd7
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_10_4440a80d64c60c7312d5c405d54e607a._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="tanen"
+ ip="83.128.159.25"
+ subject="comment 10"
+ date="2013-11-04T17:58:36Z"
+ content="""
+> \"We could symetrically encrypt the repository with a keyfile that's stored in the repository itself\"
+> Then you would need to decrypt the repository in order get the key you need to decrypt the repository. The impossibility of this design is why I didn't do that!
+
+Sorry, I ment that the file containing the symmetric encryption key should obviously not be used to encrypt itself, it would be stored in the repository \"unencrypted\" (but protected with a passphrase)
+
+> store a non-encrypted gpg key alongside the repsitory encrypted with it, but then you have to rely on a passphrase for all your security.
+
+Exactly. I think such a mode be a great addition. It might not be as secure as encryption based on a private key - depending on the passphrase strength -, but it would certainly be a lot more convenient and portable (and still much more secure than the shared encryption method).
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_1_5c54690586f2a781905ea4b25aa1147f._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_1_5c54690586f2a781905ea4b25aa1147f._comment
new file mode 100644
index 000000000..71305e650
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_1_5c54690586f2a781905ea4b25aa1147f._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="Is there a way to specify a preferred pgp key?"
+ date="2013-11-01T18:57:38Z"
+ content="""
+Hi,
+
+I think the current behavior of the special remote is a bit annoying when one has several pgp keys.
+
+Indeed, I've followed the encrypted backup drive example specifying the id of a dedicated key in the initremote step, so far so good. Doing that, I was prompted for my key phrase by the gnome keyring daemon, as expected.
+
+The annoying part starts right at the git annex sync step. Indeed, when git-remote-gcrypt tries to decrypt the manifest from the encrypted remote, rather than trying only the key specified during the initremote step, it tries all my (secret) keys. This means that I get prompted for the key phrase of all those keys (minus the correct one which is already unlocked...).
+
+In the future, this might possible to avoid by allowing gcrypt to fetch a preferred key from git config and to use with the --try-secret-key option available gnupg 2.1.x. But for 1.x or 2.0.x, the simpler option --default-key does not seem to alter the order in which keys are tried to decrypt the manifest. Also, it does not seem to be a problem of the gnome keyring daemon, but rather a gpg problem as when the daemon is replaced by the standard gpg-agent, the same problem occurs.
+
+Meanwhile, is there any way to avoid this problem?
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_2_07feedb4348f8c31176cc744c19368a1._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_2_07feedb4348f8c31176cc744c19368a1._comment
new file mode 100644
index 000000000..b154263fe
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_2_07feedb4348f8c31176cc744c19368a1._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="A possible solution"
+ date="2013-11-02T14:22:13Z"
+ content="""
+I'm answering to myself :-). A possible solution to the annoying pass phrase asking with current gnupg is to use a specialized secret keyring. One first exports the secret key used for this repository in a specific keyring as follows:
+
+`gpg --export-secret-keys keyid | gpg --import --no-default-keyring --secret-keyring mygitannexsecret.gpg`
+
+This will create a keyring in $HOME/.gnupg with only the specific key.
+
+Then, in the git-remote-gcrypt shell script, gpg should be called as follows
+
+`gpg --no-default-keyring --secret-keyring mygitannexsecret.gpg -q -d ...`
+
+when decrypting the manifest in order to try only the specific key. This behavior can be easily triggered via some git configuration variable.
+
+Any comment?
+
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_3_c2f873dffa015f1d72ad0c3921909316._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_3_c2f873dffa015f1d72ad0c3921909316._comment
new file mode 100644
index 000000000..0ce74d767
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_3_c2f873dffa015f1d72ad0c3921909316._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-02T17:32:28Z"
+ content="""
+Fabrice, I've filed a bug report about this: <https://github.com/blake2-ppc/git-remote-gcrypt/issues/9>
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_4_f8a6e4415f4fe6da14f6a3b7334bc952._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_4_f8a6e4415f4fe6da14f6a3b7334bc952._comment
new file mode 100644
index 000000000..9b1307df4
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_4_f8a6e4415f4fe6da14f6a3b7334bc952._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="tanen"
+ ip="83.128.159.25"
+ subject="comment 4"
+ date="2013-11-03T22:35:07Z"
+ content="""
+The way I would want to setup git-annex (assistant) is \"Wuala/Spideroak style\": two computers with a full checkout of the repository, changes automatically being synced between them, even if the two computers are never online simultaneously, and encryption should be done locally: the (special) remote should not be able to view file listings or content.
+
+Do I understand it correctly that the gcrypt remote is the only way to make this happen? I tried to create such a setup via the webapp but failed. Adding the repository and remote (via \"Encrypt with GnuPG key\") on the first computer went OK*, but trying to enable that remote on the other computer fails: clicking enable asks me for the SSH password, but after that I just get redirected to a blank screen, with nothing to see in the logfile after the succesful call to ssh-keygen. No entry for the second computer is being added to authorized_keys on the remote.
+
+Perhaps this is because at this point the assistant is unable to actually parse the content of the encrypted repository? I tried importing the private key that was used while creating the repository on the other computer, but that made no difference.
+
+Thinking about this for a while, I believe gpg keys aren't actually particularly suited for this usecase. Even without the bug above, one would either have to awkwardly copy a private key to all hosts that are syncing to the repository; or, every time a new (or reinstalled) host wants to sync the repository, you would manually have to add the new keyid to the config and do the forced push + GCRYPT_FULL_REPACK, presumably having to reupload your entire history. Apart from this, having to backup a private key (outside of your git-annex based backups!) would be quite inconvenient.
+
+How would you feel about adding a new mode of operation where encryption is simply based on a passphrase? We could symetrically encrypt the repository with a keyfile that's stored in the repository itself, protecting the keyfile with a passphrase which - if stored at all - would be stored on the individual computers, outside of the repository.
+
+*although it erroneously used \"E0D2F776E7F674E3\" as key-id while the actual id is E7F674E3; where did that other half come from?
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_5_11b8e82d2a234f65b58b823e71c6d6a2._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_5_11b8e82d2a234f65b58b823e71c6d6a2._comment
new file mode 100644
index 000000000..8e767254c
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_5_11b8e82d2a234f65b58b823e71c6d6a2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 5"
+ date="2013-11-04T04:40:53Z"
+ content="""
+> How would you feel about adding a new mode of operation where encryption is simply based on a passphrase? We could symetrically encrypt the repository with a keyfile that's stored in the repository itself, protecting the keyfile with a passphrase which - if stored at all - would be stored on the individual computers, outside of the repository.
+
+Isn't that what the regular shared-encryption remote already does? Except it doesn't put a passphrase on the key, because anyone who has access to the local repo wouldn't need access to the remote one anyway.
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_6_3e41948e1beffcf279bb05ef8e61cc07._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_6_3e41948e1beffcf279bb05ef8e61cc07._comment
new file mode 100644
index 000000000..1a5d7f6e1
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_6_3e41948e1beffcf279bb05ef8e61cc07._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="comment 6"
+ date="2013-11-04T07:39:21Z"
+ content="""
+> _How would you feel about adding a new mode of operation where encryption is simply based on a passphrase? We could symetrically encrypt the repository with a keyfile that's stored in the repository itself, protecting the keyfile with a passphrase which - if stored at all - would be stored on the individual computers, outside of the repository._
+
+As Adam wrote, without a passphrase, this is the shared encryption method. With an encrypted key, this is more or less the hybrid (default) scheme. The thing is that you have to share a secret to have a encrypted remote. I don't use the webapp, so I don't know what's happening in your case, but this is how it should work with the command line tools. First Alice create the encrypted remote with her pgp key. As far as I understand, git annex creates (via gpg) a key for a symmetric cypher which is stored in the repository, encrypted with Alice public key. If Alice wants to share the repository with Bob, she must either give a key pair (so the private key also, of course) to Bob or ask Bob for his public key. In the first case, Bob can clone the repository directly (upon reception of the key pair), while in the second case, Alice has to active Bob's public key (with `git annex enableremote myremote keyid+=bobsId`). In this case, again as far as I understand, the symmetric key is reencrypted for both Alice and Bob in the repo.
+
+I understand that you tried the first case with the webapp and that it did not work. I had a similar problem documented in this [http://git-annex.branchable.com/bugs/git-annex-shell:_gcryptsetup_permission_denied](bug). Maybe you could had some comments to this bug description?
+
+> _*although it erroneously used \"E0D2F776E7F674E3\" as key-id while the actual id is E7F674E3; where did that other half come from?_
+
+This is the long id of your pgp key (16 characters as opposed to 8 for the short id).
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_7_4ce0b26b25b336f07b2e27246cdfba3e._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_7_4ce0b26b25b336f07b2e27246cdfba3e._comment
new file mode 100644
index 000000000..dfb2a3b92
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_7_4ce0b26b25b336f07b2e27246cdfba3e._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="tanen"
+ ip="83.128.159.25"
+ subject="comment 7"
+ date="2013-11-04T09:01:13Z"
+ content="""
+Thanks for the responses. Please correct me if I'm wrong, but the way I understood it, using the shared encryption scheme creates a conflict between \"changes being synced between them, even if the two computers are never online simultaneously\" and \"encryption should be done locally: the (special) remote should not be able to view file listings or content.\"
+
+- If I use shared encryption \"the webapp way\", only the file contents will be rsynced to the remote, not the repository itself. This means that different hosts are unable to sync unless they are online simultaneously, so that commit data can be sent directly between them via XMPP. In practice, this would mean my hosts are never synced (because I don't keep my home computer running when I leave for work, and vice versa)
+
+- If I use shared encryption and additionally put the repository itself on a remote, that remote would have the keys to fully decrypt the repository, that's not acceptable.
+
+Reading through the docs again, the hybrid scheme actually seems to be closer to what I want than the shared scheme, but it still has a major downside: the encryption only applies to the files itself, so in order to get \"offline sync\" there still has to be a 'remote' for the repository itself, which will contain all your metadata unencrypted. And also it would depend on the user being able to manually setup and backup a set of gpg keys instead of just memorizing a secure passphrase.
+
+@Fabrice Looks like the bug you found could very well be the cause of the problem I had; I'll try it again when a new version is available.
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_8_49aa34d75d24a2066baa8a585bc9c2e9._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_8_49aa34d75d24a2066baa8a585bc9c2e9._comment
new file mode 100644
index 000000000..86f3f5cad
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_8_49aa34d75d24a2066baa8a585bc9c2e9._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkbpbjP5j8MqWt_K4NASwv0WvB8T4rQ-pM"
+ nickname="Fabrice"
+ subject="comment 8"
+ date="2013-11-04T10:31:56Z"
+ content="""
+I think you are (at least partially) right. Of course, the only way to sync completely computers that are not on together is to use either a usb drive or a third always on computer. (I've to confess I did not understand first when I read git annex docs, shame on me ;-) If you don't want to trust completely this computer (I don't, for instance), you must :
+
+* use an encrypted git repository on this computer;
+
+* and use either hybrid or pubkey encryption.
+
+But contrarily to what you seem to imply (I hope I understand you correctly), if you do that, the third computer can still figure out a few things (usage patterns, such as where connections come from), but that's all. You've got full sync and everything is encrypted, both the git part and the files handled by the annex. This applied only to encrypted git special remotes as other remotes do not store the git part.
+"""]]
diff --git a/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_9_3784e0c828cd60b6a9075c2d32d070cc._comment b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_9_3784e0c828cd60b6a9075c2d32d070cc._comment
new file mode 100644
index 000000000..15f807616
--- /dev/null
+++ b/doc/tips/fully_encrypted_git_repositories_with_gcrypt/comment_9_3784e0c828cd60b6a9075c2d32d070cc._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 9"
+ date="2013-11-04T17:07:55Z"
+ content="""
+\"We could symetrically encrypt the repository with a keyfile that's stored in the repository itself\"
+
+Then you would need to decrypt the repository in order get the key you need to decrypt the repository. The impossibility of this design is why I didn't do that!
+
+It would certianly be possible to store a non-encrypted gpg key alongside the repsitory encrypted with it, but then you have to rely on a passphrase for all your security.
+
+You should file a bug report for the bug you saw..
+"""]]
diff --git a/doc/tips/imapannex.mdwn b/doc/tips/imapannex.mdwn
new file mode 100644
index 000000000..e9963df34
--- /dev/null
+++ b/doc/tips/imapannex.mdwn
@@ -0,0 +1,27 @@
+imapannex
+=========
+
+Hook program for gitannex to use imap as backend
+
+# Requirements:
+
+ python2
+
+# Install
+Clone the git repository in your home folder.
+
+ git clone git://github.com/TobiasTheViking/imapannex.git
+
+This should make a ~/imapannex folder
+
+# Setup
+Run the program once to set it up.
+
+ cd ~/imapannex; python2 imapannex.py
+
+# Commands for gitannex:
+
+ git config annex.imap-hook '/usr/bin/python2 ~/imapannex/imapannex.py'
+ git annex initremote imap type=hook hooktype=imap encryption=shared
+ git annex describe imap "the imap library"
+ git annex wanted imap exclude=largerthan=30mb
diff --git a/doc/tips/migrating_two_seperate_disconnected_directories_to_git_annex.mdwn b/doc/tips/migrating_two_seperate_disconnected_directories_to_git_annex.mdwn
new file mode 100644
index 000000000..1209d1217
--- /dev/null
+++ b/doc/tips/migrating_two_seperate_disconnected_directories_to_git_annex.mdwn
@@ -0,0 +1,77 @@
+Scenario
+--------
+
+You are a new git-annex user. You have already files spread around many computers and wish to migrate those into git-annex, without having to recopy all files all over the place.
+
+Let's say, for example, you have a server, named `marcos` and a workstation named `angela`. You have your audio collection stored in `/srv/mp3` in `marcos` and `~/mp3` on `angela`, but only `marcos` has all the files, and `angela` only has a subset.
+
+We also assume that `marcos` has an SSH server.
+
+How do you add all this stuff to git-annex?
+
+Create the biggest git-annex repository
+---------------------------------------
+
+Start with `marcos`, with the complete directory:
+
+ cd /srv/mp3
+ git init
+ git annex init
+ git annex add .
+ git commit -m"git annex yay"
+
+This will checksum all files and add them to the `git-annex` branch of the git repository. Wait for this process to complete.
+
+Create the smaller repo and synchronise
+---------------------------------------
+
+On `angela`, we want to synchronise the git annex metadata with `marcos`. We need to initialize a git repo with `marcos` as a remote:
+
+ cd ~/mp3
+ git init
+ git remote add marcos marcos.example.com:/srv/mp3
+ git fetch marcos
+ git annex info # this should display the two repos
+ git annex add .
+
+This will, again, checksum all files and add them to git annex. Once that is done, you can verify that the files are really the same as marcos with `whereis`:
+
+ git annex whereis
+
+This should display something like:
+
+ whereis Orange Seeds/I remember.wav (2 copies)
+ b7802161-c984-4c9f-8d05-787a29c41cfe -- marcos (anarcat@marcos:/srv/mp3)
+ c2ca4a13-9a5f-461b-a44b-53255ed3e2f9 -- here (anarcat@angela)
+ ok
+
+Once you are sure things went on okay, you can synchronise this with `marcos`:
+
+ git annex sync
+
+This will push the metadata information to marcos, so it knows which files are available on `angela`. From there on, you can freely get and move files between the two repos!
+
+Importing files from a third directory
+--------------------------------------
+
+Say that some files on `angela` are actually spread out outside of the `~/mp3` directory. You can use the `git annex import` command to add those extra directories:
+
+ cd ~/mp3
+ git annex import ~/music/
+
+(!) Be careful that `~/music` is not a git-annex repository, or this will [[destroy it!|bugs/git annex import destroys a fellow git annex repository]].
+
+Deleting deleted files
+----------------------
+
+It is quite possible some files were removed (or renamed!) on `marcos` but not on `angela`, since it was synchronised only some time ago. A good way to find out about those files is to use the `--not --in` argument, for example, on `angela`:
+
+ git annex whereis --in here --not --in marcos
+
+This will show files that are on `angela` and not on `marcos`. They could be new files that were only added on `angela`, so be careful! A manual analysis is necessary, but let's say you are certain those files are not relevant anymore, you can delete them from `angela`:
+
+ git annex drop <file>
+
+If the file is a renamed or modified version from the original, you may need to use `--force`, but be careful! If you delete the wrong file, it will be lost forever!
+
+> (!) Maybe this wouldn't happen with [[direct mode]] and an fsck? --[[anarcat]]
diff --git a/doc/tips/offline_archive_drives.mdwn b/doc/tips/offline_archive_drives.mdwn
new file mode 100644
index 000000000..eff123e8b
--- /dev/null
+++ b/doc/tips/offline_archive_drives.mdwn
@@ -0,0 +1,69 @@
+After you've used git-annex for a while, you will have data in your repository
+that you don't want to keep in the limited disk space of a laptop or a server,
+but that you don't want to entirely delete.
+
+This is where git-annex's support for offline archive drives shines.
+You can move old files to an archive drive, which can be kept offline if
+it's not practical to keep it spinning. Better, you can move old files to
+two or more archive drives, in case one of them later fails to spin up.
+(One consideration when [[future_proofing]] your archive.)
+
+To set up an archive drive, you can take any removable drive, format
+it with a filesystem you'll be able to read some years later, and then follow
+the [[walkthrough]] to set up a repository on it that is a git remote of
+the repository in your computer you want to archive. In short:
+
+ cd /media/archive
+ git clone ~/annex
+ cd ~/annex
+ git remote add archivedrive /media/archive/annex
+ git annex sync archivedrive
+
+Don't forget to tell git-annex this is an archive drive (or perhaps a backup
+drive). Also, give the drive a description that matches something you write on
+its label, so you can find it later:
+
+ git annex group archivedrive archive
+ git annex wanted archivedrive standard
+ git annex describe archivedrive "my first archive drive (SATA)"
+
+Or you can use the assistant to set up the drive for you.
+(Nice video tutorial here: [[videos/git-annex_assistant_archiving]])
+
+(Keeping the archive drive in an offsite location? Consider encrypting
+it! See [[fully_encrypted_git_repositories_with_gcrypt]].)
+
+Then, when the archive drive is plugged in, you can easily copy files to
+it:
+
+ cd ~/annex
+ git-annex copy --auto --to archivedrive
+
+Or, if you're using the assistant, it will automatically notice when the drive
+gets plugged in and copy files that need to be archived.
+
+When you want to get rid of the local file, leaving only the copy on the
+archive, you can just:
+
+ git annex drop file
+
+The archive drive has to be plugged in for this to work, so git-annex
+can verify it still has the file. If you had configured git-annex to
+always store 2 [[copies]], it will need 2 archive drives plugged in.
+You may find it useful to configure a [[trust]] setting for the drive to
+avoid needing to haul it out of storage to drop a file.
+
+Now the really nice thing. When your archive drive gets filled up, you
+can simply remove it, store it somewhere safe, and replace it with a new
+drive, which can be mounted at the same location for simplicity. Set up
+the new drive the same way described above, and use it to archive even more
+files.
+
+Finally, when you want to access one of the files you archived, you can
+just ask for it:
+
+ git annex get file
+
+If necessary git-annex will tell you which archive drive you need to
+pull out of storage to get the file back. This is where the description
+you entered earlier comes in handy.
diff --git a/doc/tips/offline_archive_drives/comment_1_3d4fdf42191a9d81434d00f51c3609ff._comment b/doc/tips/offline_archive_drives/comment_1_3d4fdf42191a9d81434d00f51c3609ff._comment
new file mode 100644
index 000000000..5855b0f7a
--- /dev/null
+++ b/doc/tips/offline_archive_drives/comment_1_3d4fdf42191a9d81434d00f51c3609ff._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkC0W3ZQERUaTkHoks6k68Tsp1tz510nGo"
+ nickname="Georg"
+ subject="git annex sync"
+ date="2013-10-06T08:59:24Z"
+ content="""
+Shouldn't it be
+git annex sync archivedrive
+instead of
+git annex sync archive
+in the first examples. As the name of the remote is \"archivedrive\", IMO \"sync\" should be called with the name of the remote.
+"""]]
diff --git a/doc/tips/offline_archive_drives/comment_2_864c752aa8d064791a4b14dbbe2e6882._comment b/doc/tips/offline_archive_drives/comment_2_864c752aa8d064791a4b14dbbe2e6882._comment
new file mode 100644
index 000000000..3ff074ff3
--- /dev/null
+++ b/doc/tips/offline_archive_drives/comment_2_864c752aa8d064791a4b14dbbe2e6882._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkC0W3ZQERUaTkHoks6k68Tsp1tz510nGo"
+ nickname="Georg"
+ subject="git annex copy not working"
+ date="2013-10-06T10:18:10Z"
+ content="""
+Is the feature \"git-annex copy --auto --to usb\" working?
+I have created a backup repo on my usb drive but when I call \"git-annex copy --auto --to usb\" nothing happens.
+
+I have called \"git annex group usb backup\" and \"git annex sync usb\" to set up the repo.
+
+What is the correct way to get the data out to the backup repo?
+
+Best regards, Georg
+"""]]
diff --git a/doc/tips/offline_archive_drives/comment_3_7be2ccaf70c9ecfc9a34384e0e31f490._comment b/doc/tips/offline_archive_drives/comment_3_7be2ccaf70c9ecfc9a34384e0e31f490._comment
new file mode 100644
index 000000000..cd5888009
--- /dev/null
+++ b/doc/tips/offline_archive_drives/comment_3_7be2ccaf70c9ecfc9a34384e0e31f490._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.243"
+ subject="thanks for your checking.."
+ date="2013-10-06T17:04:24Z"
+ content="""
+The example was missing a preferred content setting, without which --auto doesn't copy anything unless needed to satisfy numcopies:
+
+git annex wanted archivedrive standard
+"""]]
diff --git a/doc/tips/powerful_file_matching.mdwn b/doc/tips/powerful_file_matching.mdwn
index d5d29377c..47f8c8a64 100644
--- a/doc/tips/powerful_file_matching.mdwn
+++ b/doc/tips/powerful_file_matching.mdwn
@@ -1,4 +1,4 @@
-git-annex has a powerful syntax for making it act on only certian files.
+git-annex has a powerful syntax for making it act on only certain files.
The simplest thing is to exclude some files, using wild cards:
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository.mdwn b/doc/tips/recovering_from_a_corrupt_git_repository.mdwn
new file mode 100644
index 000000000..084f76852
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository.mdwn
@@ -0,0 +1,17 @@
+I have found this the most reliable way to recover from a corrupt git repository. I have had a lot of them lately, there might be a regression in btrfs in Ubuntu's Linux 3.8.0-33 (!).
+
+1. Create a clone of a known good repository.
+2. Add the clone as an object alternate to the broken repository.
+3. Do a `git-repack -a -d` to lift the external objects into repo-local packs.
+4. Remove the clone
+
+[[!format sh """
+$ cd /tmp/
+$ git clone good-host:/path/to/good-repo
+$ cd /home/user/broken-repo
+$ echo /tmp/good-repo/.git/objects/ > .git/objects/info/alternates
+$ git repack -a -d
+$ rm -rf /tmp/good-repo
+"""]]
+
+... and push early, push often. ;-)
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_1_f5827be97f78dbae113a5ba0c9ced896._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_1_f5827be97f78dbae113a5ba0c9ced896._comment
new file mode 100644
index 000000000..d212e23f3
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_1_f5827be97f78dbae113a5ba0c9ced896._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 1"
+ date="2013-11-11T16:01:59Z"
+ content="""
+Better, since version 4.20131024, `git annex repair` can be run to automatically do this, and more. (Including recovering data in corrupt git repositories that you forgot to push!)
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_2_e98df7275bb032308bb87e3607bdde32._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_2_e98df7275bb032308bb87e3607bdde32._comment
new file mode 100644
index 000000000..c018c4ca5
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_2_e98df7275bb032308bb87e3607bdde32._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 2"
+ date="2013-11-12T16:14:50Z"
+ content="""
+I am using git-annex 20131106 and I tried `git annex repair` first. It seems git is making assumptions that if I have object A then I must have object B that A depends on. Or maybe it freaks out because the object is not missing, just full of zeroes. I haven't done any analysis on exactly what situation causes this. When I have time, I will.
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_3_11bece6dfac090edbcd783b266c482a3._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_3_11bece6dfac090edbcd783b266c482a3._comment
new file mode 100644
index 000000000..63f443a31
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_3_11bece6dfac090edbcd783b266c482a3._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 3"
+ date="2013-11-12T16:17:42Z"
+ content="""
+Luckily, so far the objects getting corrupted have been in past commits (maybe only in packfiles?), not the latest ones, so I have been able to recover even though HEAD has been unique to the local repo.
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_4_86e99017f7585ac2f76753051214637e._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_4_86e99017f7585ac2f76753051214637e._comment
new file mode 100644
index 000000000..8d454fc3e
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_4_86e99017f7585ac2f76753051214637e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 4"
+ date="2013-11-12T17:10:06Z"
+ content="""
+Hm. This is bad. My hunch that btrfs was the culprit seems to have been wrong. After having switched things around, along with lots of `git annex sync` in various places, I now have a corrupt repo on ext4. It must be git or git-annex that does something wrong.
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_c8953732ce353cdf0c4fb81ddc98c04a._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_c8953732ce353cdf0c4fb81ddc98c04a._comment
new file mode 100644
index 000000000..eeb3ceef2
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_c8953732ce353cdf0c4fb81ddc98c04a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 6"
+ date="2013-11-12T18:10:21Z"
+ content="""
+If you can reliably corrupt a git repository, it's highly likely your hardware (disk or memory) is broken.
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_d0da84df0241dc6ccf0aa0c7598917df._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_d0da84df0241dc6ccf0aa0c7598917df._comment
new file mode 100644
index 000000000..16b2329b9
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_6_d0da84df0241dc6ccf0aa0c7598917df._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 6"
+ date="2013-11-12T17:22:01Z"
+ content="""
+This is my symptom too: [[forum/Git annex 'corrupting' itself]]
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_7_addf49556e4c33d55a41c393f519d0a4._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_7_addf49556e4c33d55a41c393f519d0a4._comment
new file mode 100644
index 000000000..5047bcca4
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_7_addf49556e4c33d55a41c393f519d0a4._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.246"
+ subject="comment 7"
+ date="2013-11-12T18:12:49Z"
+ content="""
+> I tried git annex repair first. It seems git is making assumptions that if I have object A then I must have object B that A depends on. Or maybe it freaks out because the object is not missing
+
+`git annex repair` is supposed to deal with these situations. If it fails to fix such a broken repository, please file a detailed bug report, ideally with a link to a copy of the repository.
+"""]]
diff --git a/doc/tips/recovering_from_a_corrupt_git_repository/comment_8_505a2fc2b841fe8eb419801f923ef35f._comment b/doc/tips/recovering_from_a_corrupt_git_repository/comment_8_505a2fc2b841fe8eb419801f923ef35f._comment
new file mode 100644
index 000000000..78144b893
--- /dev/null
+++ b/doc/tips/recovering_from_a_corrupt_git_repository/comment_8_505a2fc2b841fe8eb419801f923ef35f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://id.clacke.se/"
+ nickname="clacke"
+ subject="comment 8"
+ date="2013-11-14T10:00:20Z"
+ content="""
+Several machines started showing this behavior around 4.20131106 or 4.20131101. I will find a way to reproduce when I can find the time.
+"""]]
diff --git a/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_6_6a5d6af107b297afd008b021f73d787b._comment b/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_6_6a5d6af107b297afd008b021f73d787b._comment
new file mode 100644
index 000000000..bd2212ffb
--- /dev/null
+++ b/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_6_6a5d6af107b297afd008b021f73d787b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnPOttrEmm9CQYxzWrmgGN7LXy98gDkrlM"
+ nickname="binet"
+ subject="annex.largefiles and direct mode"
+ date="2013-09-16T22:50:48Z"
+ content="""
+I was wondering if the annex.largefiles feature was compatible with direct mode?
+"""]]
diff --git a/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_7_74d57cf503a86d8f7ace2d769dbb58be._comment b/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_7_74d57cf503a86d8f7ace2d769dbb58be._comment
new file mode 100644
index 000000000..2144b0ec8
--- /dev/null
+++ b/doc/tips/replacing_Sparkleshare_or_dvcs-autosync_with_the_assistant/comment_7_74d57cf503a86d8f7ace2d769dbb58be._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 7"
+ date="2013-09-19T18:03:29Z"
+ content="""
+annex.largefiles does not support mime types. I agree it would be a useful addition.
+
+annex.largefiles can be used with direct mode. I would only recommending using it this way using the assistant, which will keep straight which files are which and commit them appropriately.
+"""]]
diff --git a/doc/tips/setup_a_public_repository_on_a_web_site.mdwn b/doc/tips/setup_a_public_repository_on_a_web_site.mdwn
index e1fbd1e47..8251cabf6 100644
--- a/doc/tips/setup_a_public_repository_on_a_web_site.mdwn
+++ b/doc/tips/setup_a_public_repository_on_a_web_site.mdwn
@@ -9,23 +9,47 @@ Here's how I set it up. --[[Joey]]
1. Set up a web site. I used Apache, and configured it to follow symlinks.
`Options FollowSymLinks`
2. Put some files on the website. Make sure it works.
-4. `git init; git annex init`
-3. We want users to be able to clone the git repository over http, because
+3. `git init; git annex init`
+4. `git config core.sharedrepository world` (Makes sure files
+ are always added with permissions that allow everyone to read them.)
+5. We want users to be able to clone the git repository over http, because
git-annex can download files from it over http as well. For this to
work, `git update-server-info` needs to get run after commits. The
git `post-update` hook will take care of this, you just need to enable
the hook. `chmod +x .git/hooks/post-update`
-5. `git annex add; git commit -m added`
-6. Make sure users can still download files from the site directly.
-7. Instruct advanced users to clone a http url that ends with the "/.git/"
+6. `git annex add; git commit -m added`
+7. Make sure users can still download files from the site directly.
+8. Instruct advanced users to clone a http url that ends with the "/.git/"
directory. For example, for downloads.kitenet.net, the clone url
is `https://downloads.kitenet.net/.git/`
-8. Set up a git `post-receive` hook that runs `git annex merge`, and
- the repository's working tree will automatically be updated when
- you run `git annex sync` in a clone that can push to the repository.
- (Needs git-annex version 4.20130703 or newer; older versions
- can use `git annex sync` in the post-receive hook instead.)
+9. Set up a git `post-receive` hook to update the repository's working tree
+ when changes are pushed to it. See below for details.
When users clone over http, and run git-annex, it will
automatically learn all about your repository and be able to download files
right out of it, also using http.
+
+## post-receive hook
+
+If you have git-annex 4.20130703, the post-receive hook mentioned above
+in step 8 just needs to run `git annex merge`.
+
+With older versions of git-annex, you can instead use `git annex sync`.
+
+There are two gotchas with some versions of git to be aware of when writing
+this post-receive hook.
+
+1. The hook may be run with the current directory set to the `.git`
+ directory, and not the top of your work tree. So you need to `cd ..` or
+ similar in the hook.
+2. `GIT_DIR` may be set to `.`, which will not be right after changing
+ directory. So you will probably want to unset it.
+
+Here's a post-receive hook that takes these problems into account:
+
+<pre>
+#!/bin/sh
+unset GIT_DIR
+cd ..
+git annex merge
+</pre>
diff --git a/doc/tips/shared_git_annex_directory_between_multiple_users.mdwn b/doc/tips/shared_git_annex_directory_between_multiple_users.mdwn
new file mode 100644
index 000000000..5ca3b45ec
--- /dev/null
+++ b/doc/tips/shared_git_annex_directory_between_multiple_users.mdwn
@@ -0,0 +1,39 @@
+Scenario
+========
+
+You have a server where you want to welcome other people to push files, say for a family photo album. People have their own user account, so by default they will not be able to read/write from each other's repositories, due to git-annex strict restrictions.
+
+Solution
+========
+
+Setup a shared git repository:
+
+ git init shared ; cd shared # you can also do this on an existing git annex repo
+ git config core.sharedrepository group
+ chmod g+rwX -R .
+ chown -R :media .
+
+The idea here is to use the new (since [[news/version 4.20130909]]) support for git's `sharedRepository` configuration and restrict access to a specific group (instead of the default, a single user). You can also this to make the files accessible to all users on the system:
+
+ git config core.sharedrepository world
+ chmod a+rwX -R .
+
+This will make sure that you anyone can operate that git annex repository remotely.
+
+Third party applications
+------------------------
+
+Now if another application that is not aware of git's `sharedRepository` configuration (say a [[bittorrent]] daemon) writes files there, you may want to make sure that the files created are also writable by everyone. This is more tricky, but one way of doing this is with the [[!wikipedia setgid]] bit:
+
+ find -type d -exec chmod g+s {} \;
+
+You will also need to start the process with a proper [[!wikipedia umask]] (`002` instead of `022`).
+
+(!) I haven't actually tested this part. --[[anarcat]]
+
+See also
+========
+
+ * [[tips/setup a public repository on a web site]]
+ * [[news/version 4.20130909]]
+ * [[bugs/acl not honoured in rsync remote]]: why this does not work on encrypted remotes
diff --git a/doc/tips/using_Amazon_Glacier.mdwn b/doc/tips/using_Amazon_Glacier.mdwn
index 5e7131eeb..5aac7fa91 100644
--- a/doc/tips/using_Amazon_Glacier.mdwn
+++ b/doc/tips/using_Amazon_Glacier.mdwn
@@ -16,7 +16,7 @@ like "2512E3C7"
Next, create the Glacier remote.
- # git annex initremote glacier type=glacier encryption=2512E3C7
+ # git annex initremote glacier type=glacier keyid=2512E3C7
initremote glacier (encryption setup with gpg key C910D9222512E3C7) (gpg) ok
The configuration for the Glacier remote is stored in git. So to make another
diff --git a/doc/tips/using_Amazon_S3.mdwn b/doc/tips/using_Amazon_S3.mdwn
index 19997d026..0c68c7387 100644
--- a/doc/tips/using_Amazon_S3.mdwn
+++ b/doc/tips/using_Amazon_S3.mdwn
@@ -14,7 +14,7 @@ like "2512E3C7"
Next, create the S3 remote, and describe it.
- # git annex initremote cloud type=S3 encryption=2512E3C7
+ # git annex initremote cloud type=S3 keyid=2512E3C7
initremote cloud (encryption setup with gpg key C910D9222512E3C7) (checking bucket) (creating bucket in US) (gpg) ok
# git annex describe cloud "at Amazon's US datacenter"
describe cloud ok
diff --git a/doc/tips/using_box.com_as_a_special_remote.mdwn b/doc/tips/using_box.com_as_a_special_remote.mdwn
index 6616d0a1e..254d0a554 100644
--- a/doc/tips/using_box.com_as_a_special_remote.mdwn
+++ b/doc/tips/using_box.com_as_a_special_remote.mdwn
@@ -5,7 +5,7 @@ for providing 50 gb of free storage if you sign up with its Android client.
git-annex can use Box as a [[special remote|special_remotes]].
Recent versions of git-annex make this very easy to set up:
- WEBDAV_USERNAME=you@example.com WEBDAV_PASSWORD=xxxxxxx git annex initremote box.com type=webdav url=https://www.box.com/dav/git-annex chunksize=75mb encryption=you@example.com
+ WEBDAV_USERNAME=you@example.com WEBDAV_PASSWORD=xxxxxxx git annex initremote box.com type=webdav url=https://www.box.com/dav/git-annex chunksize=75mb encryption=shared
Note the use of chunksize; Box has a 100 mb maximum file size, and this
breaks up large files into chunks before that limit is reached.
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_13_75218b7409c0e281cb01c9b2791e8cdf._comment b/doc/tips/using_gitolite_with_git-annex/comment_13_75218b7409c0e281cb01c9b2791e8cdf._comment
new file mode 100644
index 000000000..bc674a592
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_13_75218b7409c0e281cb01c9b2791e8cdf._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm9tgeFE5v-arAYYftSv3yUTI5Q4qB2C9M"
+ nickname="Khaije"
+ subject="git-annex with gitolite FTW"
+ date="2013-08-13T15:13:07Z"
+ content="""
+The steps to activate git-annex integration have changed/simplified for v3.
+
+
+1) during install, be sure to use the 'git-annex' branch, rather than master[fn:1].
+
+2) to enable git-annex-shell, open ~/.gitolite.rc and insert 'git-annex-shell' => 'ua' into the hash list in the COMMANDS array.[fn:2]
+#'git-annex-shell' => 'ua',
+
+
+
+
+[fn:1] We'd like to have this feature-branch merged to master, so please send Sitaram feedback, positive and negative, based on your experiences.
+[fn:2] There is no GL_ADC_PATH and no \"ua\" subdirectory here, and nothing to \"install\"; the command now comes with gitolite.
+"""]]
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_14_7d4d4515218d1259d32be3baeb5ee56e._comment b/doc/tips/using_gitolite_with_git-annex/comment_14_7d4d4515218d1259d32be3baeb5ee56e._comment
new file mode 100644
index 000000000..048dfa698
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_14_7d4d4515218d1259d32be3baeb5ee56e._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawkSbvo_NbY-ev1VKtzwo7nEqUmvRO6rXGA"
+ nickname="François"
+ subject="comment 14"
+ date="2013-09-22T18:30:45Z"
+ content="""
+@khaije
+
+Could you paste your config file? Here is mine: http://paste.debian.net/44856/
+I don't have any COMMANDS array. Could you elaborate your modifications please?
+
+Thanks.
+"""]]
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_15_dc6f21b5a3d5931c8d949a9753411b9e._comment b/doc/tips/using_gitolite_with_git-annex/comment_15_dc6f21b5a3d5931c8d949a9753411b9e._comment
new file mode 100644
index 000000000..f07116983
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_15_dc6f21b5a3d5931c8d949a9753411b9e._comment
@@ -0,0 +1,29 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnRaueN1AcM8pIMofH5-wQ1Kr4T0GBe8sA"
+ nickname="wayne"
+ subject="git-annex with gitolite-rc"
+ date="2013-10-19T17:03:32Z"
+ content="""
+@François
+
+The proper array in .gitolite.rc seems to be the \"ENABLE\" array, which it appears is parsed into the COMMANDS array in src/lib/Gitolite/Rc.pm
+
+@Khaije
+
+Using 'git-annex-shell' => 'ua' doesn't seem to work for me. The program still fails in src/gitolite-shell around line 163 (gitolite repo version b1d3c05):
+
+ _die \"suspicious characters loitering about '$soc'\"
+ if $rc{COMMANDS}{ words[0] } ne 'ua' and $soc !~ $REMOTE_COMMAND_PATT;
+
+When I insert $rc{COMMANDS}{ words[0] } into the _die message, it shows up as \"1\" instead of \"ua\" as I was expecting.
+
+When I manually set $rc{COMMANDS}{ words[0] } to 'ua' slightly earlier in the script, the git-annex-shell command gets run but it seems to fail to parse the result of the configlist command properly because then I get
+
+ Failed to get annex.uuid configuration of repository origin
+
+ Instead, got: \"annex.uuid=\ncore.gcrypt=\n\"
+
+
+I am actually about to give up on the notion of using git-annex and gitolite together. Maybe. I am interested to know if anyone else is having similar problems.
+
+"""]]
diff --git a/doc/tips/using_gitolite_with_git-annex/comment_16_8e5039e6655fc80dc863b6cdf44ef02a._comment b/doc/tips/using_gitolite_with_git-annex/comment_16_8e5039e6655fc80dc863b6cdf44ef02a._comment
new file mode 100644
index 000000000..5e0e6acd6
--- /dev/null
+++ b/doc/tips/using_gitolite_with_git-annex/comment_16_8e5039e6655fc80dc863b6cdf44ef02a._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmbo-yMzW_lkBrS4ICNn5XMr8saYtI1_WY"
+ nickname="Douglas"
+ subject="Any further info regarding gitolite support?"
+ date="2013-11-14T03:20:31Z"
+ content="""
+We have reached the same point as the previous poster from 25 days ago.
+$ git annex copy --to origin
+FATAL: suspicious characters loitering about 'git-annex-shell 'configlist' '/~/testing''
+
+ Remote origin does not have git-annex installed; setting remote.origin.annex-ignore
+git-annex: cannot determine uuid for origin
+
+Anyone actually have this working?
+"""]]
diff --git a/doc/tips/using_the_web_as_a_special_remote.mdwn b/doc/tips/using_the_web_as_a_special_remote.mdwn
index 3ce02a56a..e04ba800d 100644
--- a/doc/tips/using_the_web_as_a_special_remote.mdwn
+++ b/doc/tips/using_the_web_as_a_special_remote.mdwn
@@ -8,10 +8,16 @@ The web can be used as a [[special_remote|special_remotes]] too.
Now the file is downloaded, and has been added to the annex like any other
file. So it can be renamed, copied to other repositories, and so on.
+To add a lot of urls at once, just list them all as parameters to
+`git annex addurl`.
+
+## trust issues
+
Note that git-annex assumes that, if the web site does not 404, and has the
right file size, the file is still present on the web, and this counts as
-one [[copy|copies]] of the file. So it will let you remove your last copy,
-trusting it can be downloaded again:
+one [[copy|copies]] of the file. If the file still seems to be present
+on the web, it will let you remove your last copy, trusting it can be
+downloaded again:
# git annex drop example.com_video.mpeg
drop example.com_video.mpeg (checking http://example.com/video.mpeg) ok
@@ -31,7 +37,9 @@ With the result that it will hang onto files:
(Use --force to override this check, or adjust annex.numcopies.)
failed
-You can also add urls to any file already in the annex:
+## attaching urls to existing files
+
+You can also attach urls to any file already in the annex:
# git annex addurl --file my_cool_big_file http://example.com/cool_big_file
addurl my_cool_big_file ok
@@ -40,8 +48,10 @@ You can also add urls to any file already in the annex:
00000000-0000-0000-0000-000000000001 -- web
27a9510c-760a-11e1-b9a0-c731d2b77df9 -- here
-To add a lot of urls at once, just list them all as parameters to
-`git annex addurl`.
+## configuring filenames
+
+By default, `addurl` will generate a filename for you. You can use
+`--file=` to specify the filename to use.
If you're adding a bunch of related files to a directory, or just don't
like the default filenames generated by `addurl`, you can use `--pathdepth`
@@ -55,3 +65,37 @@ number takes that many paths from the end.
addurl 2012_01_video.mpeg (downloading http://example.com/videos/2012/01/video.mpeg)
# git annex addurl http://example.com/videos/2012/01/video.mpeg --pathdepth=-2
addurl 01_video.mpeg (downloading http://example.com/videos/2012/01/video.mpeg)
+
+## videos
+
+<a name=quvi></a>
+
+There's support for downloading videos from sites like YouTube, Vimeo,
+and many more. This relies on [quvi](http://quvi.sourceforge.net/) to find
+urls to the actual videos files.
+
+When you have quvi installed, you can just
+`git annex addurl http://youtube.com/foo` and it will detect that
+it is a video and download the video content for offline viewing.
+
+Later, in another clone of the repository, you can run `git annex get` on
+the file and it will also be downloaded with the help of quvi. This works
+even if the video host has transcoded or otherwise changed the video
+in the meantime; the assumption is that these video files are equivilant.
+
+There is an `annex.quvi-options` configuration setting that can be used
+to pass parameters to quvi. For example, you could set `git config
+annex.quvi-options "--format low"` to configure it to download low
+quality videos from YouTube.
+
+Note that for performance reasons, the url is not checked for redirects,
+so some shortened urls will not be detected. You can
+either load the short url in a browser to get the full url, or you
+can force use of quvi with redirect detection, by prepending "quvi:" to the
+url.
+
+Downloading whole YouTube playlists is not currently supported by quvi.
+
+## podcasts
+
+This is done using `git annex importfeed`. See [[downloading podcasts]].
diff --git a/doc/tips/yet_another_simple_disk_usage_like_utility/comment_1_41b212bde8bc88d2a5dea93bd0dc75f1._comment b/doc/tips/yet_another_simple_disk_usage_like_utility/comment_1_41b212bde8bc88d2a5dea93bd0dc75f1._comment
index 3a88e855e..4c3e3c22b 100644
--- a/doc/tips/yet_another_simple_disk_usage_like_utility/comment_1_41b212bde8bc88d2a5dea93bd0dc75f1._comment
+++ b/doc/tips/yet_another_simple_disk_usage_like_utility/comment_1_41b212bde8bc88d2a5dea93bd0dc75f1._comment
@@ -4,6 +4,6 @@
subject="comment 1"
date="2013-07-12T19:36:28Z"
content="""
-Ah, I just found that git annex status can do the same :)
+Ah, I just found that git annex info can do the same :)
Disregard this.
"""]]
diff --git a/doc/tips/yet_another_simple_disk_usage_like_utility/comment_2_73698913837bfd5a58cf15721211e43e._comment b/doc/tips/yet_another_simple_disk_usage_like_utility/comment_2_73698913837bfd5a58cf15721211e43e._comment
new file mode 100644
index 000000000..fe4b3d0d2
--- /dev/null
+++ b/doc/tips/yet_another_simple_disk_usage_like_utility/comment_2_73698913837bfd5a58cf15721211e43e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://me.yahoo.com/a/2grhJvAC049fJnvALDXek.6MRZMTlg--#eec89"
+ nickname="John"
+ subject="comment 2"
+ date="2013-08-30T06:09:29Z"
+ content="""
+You may want to try my `sizes` tool on Hackage. Just pass `-A` and it will be aware of the annex and report sizes as if no files were annexed. The only downside is that it reports file usage for replicated content multiple times, as if you'd copied the data out of the annex rather than hardlinked all duplicate copies (although, this may be exactly the behavior some people want).
+"""]]
diff --git a/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_5_677e958c3f2effec7528b484aeb6478d._comment b/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_5_677e958c3f2effec7528b484aeb6478d._comment
new file mode 100644
index 000000000..07b001c2e
--- /dev/null
+++ b/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_5_677e958c3f2effec7528b484aeb6478d._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm5iosFbL2By7UFeViqkc6v-hoAtqILeDA"
+ nickname="Laszlo"
+ subject="comment 5"
+ date="2013-08-25T07:48:18Z"
+ content="""
+What is the problem with bittorrent protocol in general?
+It is some technicality or purely philosophical?
+
+Best,
+ Laszlo
+
+"""]]
diff --git a/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_6_56e53803fdede895cba717e6b6e9a1bb._comment b/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_6_56e53803fdede895cba717e6b6e9a1bb._comment
new file mode 100644
index 000000000..41e1bda78
--- /dev/null
+++ b/doc/todo/A_really_simple_way_to_pair_devices_like_bittorent_sync/comment_6_56e53803fdede895cba717e6b6e9a1bb._comment
@@ -0,0 +1,23 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmkBwMWvNKZZCge_YqobCSILPMeK6xbFw8"
+ nickname="develop"
+ subject="comment 6"
+ date="2013-08-25T08:39:15Z"
+ content="""
+I just did a cursory search on haskell torrent support. And the required pieces do seem to be be there.
+https://github.com/jlouis/combinatorrent or https://github.com/astro/haskell-torrent for downloading. i'm not sure if either supports DHT, but that exists here https://github.com/aninhumer/haskell-dht
+
+That said, i think implementing this would require some quite major overhauls in the system. It probably won't be trivial to implement.
+
+Note: This is for straight \"bittorrent\", not for \"bittorrent sync\". Bittorrent sync is closed source, and while an API might come at some point, it doesn't currently exist.
+
+I do seem to recall joeyh talking about supporting further transport protocols(perhaps through hooks). So I'm adding the above links for future reference if this does get implemented.
+
+But IMHO, this doesn't seem like a trivial feature to add. It might have to take some refactoring of some core git-annex parts. Certain things have to be changed quite a bit.
+
+Currently a git-annex client doesn't really require anything(except rsync) to sync from a remote. With bittorrent with DHT support to share between clients, suddenly git-annex will have to maintain a constant bittorrent thread(maybe multiple) that constantly seeds all the files in the git-annex repository, while waiting for a potential remote to request data.
+
+So even if this happens, it is probably gonna take some time.
+
+Just my 2cents.
+"""]]
diff --git a/doc/todo/Bittorrent-like_features.mdwn b/doc/todo/Bittorrent-like_features.mdwn
index 4ec991a65..41988a422 100644
--- a/doc/todo/Bittorrent-like_features.mdwn
+++ b/doc/todo/Bittorrent-like_features.mdwn
@@ -1,31 +1,45 @@
-I made an oops and created a wishlist thread in the forum regarding bittorrent-like behaviour. Sorry, my bad.
+There are two different possible ways git-annex could use bittorrent:
-Here's the original thread:
-http://git-annex.branchable.com/forum/Wishlist:_Bittorrent-like_transfers/
+Let's describe those one by one.
-I think I summed up pretty well what bittorrent-like features could be added to git-annex in one of the posts, so I'll copy and paste some of it here (with slight clarifications added in).
+[[!toc]]
->Disclaimer: I'm thinking out loud of what could make git-annex even more awesome. I don't expect this to be implemented any time soon. Please pardon any dumbassery.
+Downloading files from multiple git-annex sources simultaneously
+================================================================
->Having your remotes (optionally!) act like a swarm would be an awesome feature to have because you bring in a lot of new features that optimize storage, bandwidth, and overall traffic usage. This would be made a lot easier if parts of it were implemented in small steps that added a nifty feature. The best part is, each of these could be implemented by themselves, and they're all features that would be really useful.
->
->Step 1. Concurrent downloads of a file from remotes.
->
->This would make sense to have, it saves upload traffic on your remotes, and you also get faster DL speeds on the receiving end.
->
->Step 2. Implementing part of the super-seeding capabilities.
->
->You upload pieces of a file to different remotes from your laptop, and on your desktop you can download all those pieces and put them together again to get a complete file. If you really wanted to get fancy, you could build in redundancy (ala RAID) so if a remote or two gets lost, you don't lose the entire file. This would be a very efficient use of storage if you have a bunch of free cloud storage accounts (~1GB each) and some big files you want to back up.
->
->Step 3. Setting it up so that those remotes could talk to one another and share those pieces.
->
->This is where it gets more like bittorrent. Useful because you upload 1 copy and in a few hours, have say, 5 complete copies on 5 different remotes. You could add or remove remotes from a swarm locally, and push those changes to those remotes, which then adapt themselves to suit the new rules and share those with other remotes in the swarm (rules should be GPG-signed as a safety precaution). Also, if/when deltas get implemented, you could push that delta to the swarm and have all the remotes adopt it. This is cooler than regular bittorrent because the shared file can be updated. As a safety precaution, the delta could be GPG signed so a corrupt file doesn't contaminate the entire swarm. Each remote could have bandwidth/storage limits set in a dotfile.
->
->This is a high-level idea of how it might work, and it's also a HUGE set of features to add, but if implemented, you'd be saving a ton of resources, adding new use cases, and making git-annex more flexible.
+Having your remotes (optionally!) act like a swarm would be an awesome feature to have because you bring in a lot of new features that optimize storage, bandwidth, and overall traffic usage. This would be made a lot easier if parts of it were implemented in small steps that added a nifty feature. The best part is, each of these could be implemented by themselves, and they're all features that would be really useful.
-And this:
+ 1. Concurrent downloads of a file from remotes.
->Obviously, Step 3 would only work on remotes that you have control of processes on, but if given login credentials to cloud storage remotes (potentially dangerous!) they could read/write to something like dropbox or rsync.
->
->Another thing, this would be completely trackerless. You just use remote groups (or create swarm definitions) and share those with your remotes. **It's completely decentralized!**
+ This would make sense to have, it saves upload traffic on your remotes, and you also get faster DL speeds on the receiving end.
+ 2. Implementing part of the super-seeding capabilities.
+
+ You upload pieces of a file to different remotes from your laptop, and on your desktop you can download all those pieces and put them together again to get a complete file. If you really wanted to get fancy, you could build in redundancy (ala RAID) so if a remote or two gets lost, you don't lose the entire file. This would be a very efficient use of storage if you have a bunch of free cloud storage accounts (~1GB each) and some big files you want to back up.
+
+ 3. Setting it up so that those remotes could talk to one another and share those pieces.
+
+ This is where it gets more like bittorrent. Useful because you upload 1 copy and in a few hours, have say, 5 complete copies on 5 different remotes. You could add or remove remotes from a swarm locally, and push those changes to those remotes, which then adapt themselves to suit the new rules and share those with other remotes in the swarm (rules should be GPG-signed as a safety precaution). Also, if/when deltas get implemented, you could push that delta to the swarm and have all the remotes adopt it. This is cooler than regular bittorrent because the shared file can be updated. As a safety precaution, the delta could be GPG signed so a corrupt file doesn't contaminate the entire swarm. Each remote could have bandwidth/storage limits set in a dotfile.
+
+This is a high-level idea of how it might work, and it's also a HUGE set of features to add, but if implemented, you'd be saving a ton of resources, adding new use cases, and making git-annex more flexible.
+
+Obviously, Step 3 would only work on remotes that you have control of processes on, but if given login credentials to cloud storage remotes (potentially dangerous!) they could read/write to something like dropbox or rsync.
+
+Another thing, this would be completely trackerless. You just use remote groups (or create swarm definitions) and share those with your remotes. **It's completely decentralized!**
+
+This was originally posted [[as a forum post|forum/Wishlist:_Bittorrent-like_transfers]] by [[users/GLITTAH]].
+
+Using an external client (addurl torrent support)
+=================================================
+
+The alternative to this would be to add `addurl` support for bittorrent files. The same way we can now add Youtube videos to a git-annex repository thanks to [[quvi]], we could also simply do:
+
+ git annex addtorrent debian-live-7.0.0-amd64-standard.iso.torrent
+
+or even better:
+
+ git annex addurl http://cdimage.debian.org/debian-cd/current-live/amd64/bt-hybrid/debian-live-7.0.0-amd64-standard.iso.torrent
+
+This way, a torrent would just become another source for a specific file. When we `get` the file, it fires up `$YOUR_FAVORITE_TORRENT_CLIENT` to download the file.
+
+That way we avoid the implementation complexity of shoving a complete bittorrent client within the assistant. The `get` operation would block until the torrent is downloaded, i guess... --[[anarcat]]
diff --git a/doc/todo/Bittorrent-like_features/comment_1_f4c110ef35ebf4fd89f06edf2c4f0c48._comment b/doc/todo/Bittorrent-like_features/comment_1_f4c110ef35ebf4fd89f06edf2c4f0c48._comment
new file mode 100644
index 000000000..eba291af9
--- /dev/null
+++ b/doc/todo/Bittorrent-like_features/comment_1_f4c110ef35ebf4fd89f06edf2c4f0c48._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="Gastlag"
+ ip="109.190.97.30"
+ subject="Gittorrent"
+ date="2013-08-28T21:49:56Z"
+ content="""
+May this could interest you : few years ago somes tried to mix Git and Bittorrent.
+
+http://www.advogato.org/article/994.html
+http://utsl.gen.nz/gittorrent/rfc.html
+http://code.google.com/p/gittorrent/
+https://git.wiki.kernel.org/index.php/SoC2010Application#Did_your_organization_participate_in_past_GSoCs.3F_If_so.2C_please_summarize_your_involvement_and_the_successes_and_challenges_of_your_participation
+"""]]
diff --git a/doc/todo/Build_for_Synology_DSM/comment_13_314255fd503d125b5aeae2f62acfd592._comment b/doc/todo/Build_for_Synology_DSM/comment_13_314255fd503d125b5aeae2f62acfd592._comment
new file mode 100644
index 000000000..3c54a9271
--- /dev/null
+++ b/doc/todo/Build_for_Synology_DSM/comment_13_314255fd503d125b5aeae2f62acfd592._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnrP-0DGtHDJbWSXeiyk0swNkK1aejoN3c"
+ nickname="sebastien"
+ subject="comment 13"
+ date="2013-08-06T12:18:35Z"
+ content="""
+I post an issue to github synocommunity for that, i hope somenone have some time to package this great features.
+"""]]
diff --git a/doc/todo/Build_for_Synology_DSM/comment_15_9525cd0d75ff4c15182d10a855774b69._comment b/doc/todo/Build_for_Synology_DSM/comment_15_9525cd0d75ff4c15182d10a855774b69._comment
new file mode 100644
index 000000000..c3edf99e2
--- /dev/null
+++ b/doc/todo/Build_for_Synology_DSM/comment_15_9525cd0d75ff4c15182d10a855774b69._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="lorenzo"
+ ip="84.75.27.69"
+ subject="Running Debian squeeze binaries on libc 2.5 based NAS"
+ date="2013-10-27T23:56:26Z"
+ content="""
+Following the suggestions in this page I tried to run the binaries that debian provides on my Lacie NetworkSpace which is another one of these NAS devices with old libc. After uploading the binaries and required libraries and using `LD_LIBRARY_PATH` to force the loader to use the version I uploaded of the libraries I was still having a segfault (similar to what Franck was experiencing) while running git-annex in a chroot was working.
+
+It turns out that it is possible to solve the problem without having to use chroot by not loading the binary directly but by substituting it with a script that calls the correct `ld-linux.so.3`. Assume you have uncompressed the files from the deb packages in `/opt/git-annex`.
+
+First create a directory `/opt/git-annex/usr/bin/git-annex.exec` and copy the executable `/opt/git-annex/usr/bin/git-annex` there.
+
+Then create script `/opt/git-annex/usr/bin/git-annex` with the following contents:
+
+ #!/bin/bash
+
+ PREFIX=/opt/git-annex
+
+ export GCONV_PATH=$PREFIX/usr/lib/gconv
+
+ exec $PREFIX/lib/ld-linux.so.3 --library-path $PREFIX/lib/:$PREFIX/usr/lib/ $PREFIX/usr/bin/git-annex.exec/git-annex \"$@\"
+
+The `GCONV_PATH` setting is important to prevent the app from failing with the message:
+
+ git-annex.exec: mkTextEncoding: invalid argument (Invalid argument)
+
+The original executable is moved to a different directory instead of being simply renamed to make sure that `$0` is correct when the executable starts. The parameter for the linker `--library-path` is used instead of the environment variable `LD_LIBRARY_PATH` to make sure that the programs exec'ed by git-annex do not have the variable set.
+
+Some more info about the approach: [[http://www.novell.com/coolsolutions/feature/11775.html]]
+"""]]
diff --git a/doc/todo/Deleting_Unused_Files_by_Age.mdwn b/doc/todo/Deleting_Unused_Files_by_Age.mdwn
new file mode 100644
index 000000000..b72768bca
--- /dev/null
+++ b/doc/todo/Deleting_Unused_Files_by_Age.mdwn
@@ -0,0 +1,13 @@
+I periodically move unused files to one of my servers. What I would like to
+do is drop any unused file that has been unused for say more than 6 months?
+I would like to not drop all unused files.
+
+> It strikes me that this is quite similar to how git handles deleting
+> stale refs with the reflog. So, if `git annex unused` were changed to
+> also look at the reflog, it would keep all files referred to by all refs
+> in the reflog, until the reflog expires. You could then set reflog expiry
+> to 6 months, and be done.
+>
+> However, I think that many users expect git annex unused to be able to
+> immediately find and remove a file after it's been deleted. So this
+> probably needs to be a configurable behavior. --[[Joey]]
diff --git a/doc/todo/Option_for_browser_to_launch_webapp_with.mdwn b/doc/todo/Option_for_browser_to_launch_webapp_with.mdwn
new file mode 100644
index 000000000..dae601169
--- /dev/null
+++ b/doc/todo/Option_for_browser_to_launch_webapp_with.mdwn
@@ -0,0 +1,7 @@
+Firefox is my default browser, but as we all know, it doesn't load quickly. If I don't have Firefox running but I want to access the git-annex webapp, I'd rather launch the webapp in some small, quick browser like QupZilla than wait for Firefox to load.
+
+Could git-annex have a setting, maybe a "webapp --browser" option and/or a setting in the config file, to specify the browser to launch?
+
+> git-annex uses the standard `git config web.browser` if you set it.
+> [[done]]
+> --[[Joey]]
diff --git a/doc/todo/Show_repo_type_in_repo_list.mdwn b/doc/todo/Show_repo_type_in_repo_list.mdwn
new file mode 100644
index 000000000..40fbe6537
--- /dev/null
+++ b/doc/todo/Show_repo_type_in_repo_list.mdwn
@@ -0,0 +1 @@
+It would be helpful to show each repo's type in the list.
diff --git a/doc/todo/Show_repo_type_in_repo_list/comment_1_ac6eb1072ef902a094b79dd8e0917c4d._comment b/doc/todo/Show_repo_type_in_repo_list/comment_1_ac6eb1072ef902a094b79dd8e0917c4d._comment
new file mode 100644
index 000000000..10c0c17df
--- /dev/null
+++ b/doc/todo/Show_repo_type_in_repo_list/comment_1_ac6eb1072ef902a094b79dd8e0917c4d._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-02T23:45:39Z"
+ content="""
+Currently if you go to the edit page for the repository, it shows some information about it, including its type and often its location, at the bottom of the page.
+
+I tend to feel that putting anything else in the repo list would result in it being too cluttered.
+"""]]
diff --git a/doc/todo/Show_repo_type_in_repo_list/comment_2_6979c487f707a724a048d20e2e5744e6._comment b/doc/todo/Show_repo_type_in_repo_list/comment_2_6979c487f707a724a048d20e2e5744e6._comment
new file mode 100644
index 000000000..7d4a36324
--- /dev/null
+++ b/doc/todo/Show_repo_type_in_repo_list/comment_2_6979c487f707a724a048d20e2e5744e6._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmNu4V5fvpLlBhaCUfXXOB0MI5NXwh8SkU"
+ nickname="Adam"
+ subject="comment 2"
+ date="2013-11-02T23:59:16Z"
+ content="""
+I understand. Well, here's what I'm looking at right now. :)
+
+[[http://alphapapa.net/outbox/view.png]]
+
+I just think it would be very useful to say \"Client\" or \"Transfer\" or \"Full Backup\" next to each one, and there's often plenty of room, depending on the size of the window. Especially when one's trying to wrap one's head around git-annex, being reminded what each repo is for would help a lot. Otherwise you basically have to put it in the name or description yourself...so why not just go ahead and show it? :)
+
+Another option might be to have an icon for each type.
+"""]]
diff --git a/doc/todo/Show_repo_type_in_repo_list/comment_3_529254a6cc20de7259d60a3cbc5ccaf7._comment b/doc/todo/Show_repo_type_in_repo_list/comment_3_529254a6cc20de7259d60a3cbc5ccaf7._comment
new file mode 100644
index 000000000..3f8b82695
--- /dev/null
+++ b/doc/todo/Show_repo_type_in_repo_list/comment_3_529254a6cc20de7259d60a3cbc5ccaf7._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 3"
+ date="2013-11-03T00:19:34Z"
+ content="""
+I'd be happy to put in some icons if someone finds some good (and suitably licensed) ones that cover the different types of repositories.
+"""]]
diff --git a/doc/todo/Sync_repo_names__63__.mdwn b/doc/todo/Sync_repo_names__63__.mdwn
new file mode 100644
index 000000000..d3bb59f04
--- /dev/null
+++ b/doc/todo/Sync_repo_names__63__.mdwn
@@ -0,0 +1,10 @@
+It's very confusing to me that the same repo viewed from different client systems can have different names and descriptions. This implies that making changes to a remote repo from one system only affects how that system sees the repo, but it seems to affect how the entire git-annex "pair" or "network of repos" sees it.
+
+I think it would be good if the names and descriptions of repos were synced across clients.
+
+> The descriptions of repositories are synced. (They're stored in git-annex:uuid.log)
+>
+> git allows for the same repository to be referred to using as many different remote names as you want to set up. git-annex inherits this,
+> and I can't see this changing; there are very good reasons for remotes to
+> have this flexability. [[done]]
+> --[[Joey]]
diff --git a/doc/todo/Wishlist:_additional_environment_variables_for_hooks.mdwn b/doc/todo/Wishlist:_additional_environment_variables_for_hooks.mdwn
new file mode 100644
index 000000000..6e852b9f2
--- /dev/null
+++ b/doc/todo/Wishlist:_additional_environment_variables_for_hooks.mdwn
@@ -0,0 +1,14 @@
+It would be nice if a couple of additional environment variables to be set for hook uses.
+
+In particular:
+
+ GIT_ANNEX_DIRECT=`git config annex.direct`
+
+and
+
+ GIT_TOP_LEVEL=`git rev-parse --show-toplevel`
+
+
+I've made some changes to flickrannex to allow the sub-directories above the uploaded image to be added as tags. This change has been merged into trunk: [[https://github.com/TobiasTheViking/flickrannex]]
+
+What I needed was both the environment variables mentioned above. One is set as part of the annex-hook and the other I guestimate from the file path. If it was set in git-annex it would be much cleaner (and accurate). So...I think this info would be useful for other hook.
diff --git a/doc/todo/Wishlist:_sanitychecker_fix_wrong_UUID__47__duplicate_remote.mdwn b/doc/todo/Wishlist:_sanitychecker_fix_wrong_UUID__47__duplicate_remote.mdwn
new file mode 100644
index 000000000..ff7773d3e
--- /dev/null
+++ b/doc/todo/Wishlist:_sanitychecker_fix_wrong_UUID__47__duplicate_remote.mdwn
@@ -0,0 +1,7 @@
+In certain situations different client annexes might get the same remote repository added, but before being synced.
+
+Once the two clients sync they will both have two remotes with the same name. But only one UUID will have any content(Assuming only one client pushed).
+
+It would be nice to have some (automatic?) way to resolve this conflict.
+
+Not sure if anything sane can be done if both clients have pushed?
diff --git a/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex.mdwn b/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex.mdwn
index c3f681685..996c03461 100644
--- a/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex.mdwn
+++ b/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex.mdwn
@@ -24,3 +24,6 @@ As per IRC
01:04:31 < RichiH> thus i would rather see this upstream and not hacked locally
The only failure mode I see in the above is "file has been dropped elsewhere, numcopies not fulfilled, but that info is not synched to the local repo, yet" -- This could be worked around by always importing the data.
+
+> [[done]] as `git annex import --deduplicate`.
+> --[[Joey]]
diff --git a/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex/comment_1_0cc16eb17151309113cec6d1cccf203d._comment b/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex/comment_1_0cc16eb17151309113cec6d1cccf203d._comment
new file mode 100644
index 000000000..0b4e22e7c
--- /dev/null
+++ b/doc/todo/__96__git_annex_import_--lazy__96___--_Delete_everything_that__39__s_in_the_source_directory_and_also_in_the_target_annex/comment_1_0cc16eb17151309113cec6d1cccf203d._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 1"
+ date="2013-08-06T14:22:03Z"
+ content="""
+To expand a bit on the use case:
+
+I have several migration directories which I simply moved to new systems or disks with the help of `cp -ax` or `rsync`.
+As I don't _need_ the data per se and merely want to hold on to it in case I ever happen to need it again and as disk space is laughably cheap, I have a lot of duplicates.
+While I can at least detect bit flips with the help of checksum lists, cleaning those duplicates of duplicated duplicates is quite some effort.
+To make things worse, photos, music, videos, letter and whatnot are thrown into the same container directories.
+
+All in all, getting data out of those data dumps and into a clean structure is quite an effort.
+`git annex import --lazy` would help with this effort as I could start with the first directory, sort stuff by hand, and annex it.
+As soon as data lives in any of my annexes, I could simply run `git annex import --lazy` to get rid of all duplicates while retaining the unannexed files.
+Iterating through this process a few times, I will be left with clean annexes on the one hand and stuff I can simply delete on the other hand.
+
+I could script all this by hand on my own machine, but I am _certain_ that others would find easy, integrated, and unit tested support for whittling down data dumps over time useful.
+"""]]
diff --git a/doc/todo/__96__git_annex_status__47__version__96___should_print_the_local_OS.mdwn b/doc/todo/__96__git_annex_status__47__version__96___should_print_the_local_OS.mdwn
new file mode 100644
index 000000000..9c2afecb4
--- /dev/null
+++ b/doc/todo/__96__git_annex_status__47__version__96___should_print_the_local_OS.mdwn
@@ -0,0 +1,6 @@
+That would make assessing weird reports like [[bugs/Should_UUID__39__s_for_Remotes_be_case_sensitive__63__/]] easier and quicker.
+
+> No, if people want to file a bug report, it's up to them to tell me
+> relevant details about their OS. I'm not going down the rathole
+> of making git-annex muck about trying to gather such information.
+> [[done]] --[[Joey]]
diff --git a/doc/todo/__96__git_annex_sync_--auto__96___or___96__git_annex_auto__96___--_synchronize_symlinks__44___tracking_info__44___and_actual_data.mdwn b/doc/todo/__96__git_annex_sync_--auto__96___or___96__git_annex_auto__96___--_synchronize_symlinks__44___tracking_info__44___and_actual_data.mdwn
new file mode 100644
index 000000000..d48b4426f
--- /dev/null
+++ b/doc/todo/__96__git_annex_sync_--auto__96___or___96__git_annex_auto__96___--_synchronize_symlinks__44___tracking_info__44___and_actual_data.mdwn
@@ -0,0 +1,3 @@
+As per DebConf13: Introduce a one-shot command to synchronize everything, including data, with the other remotes.
+
+Especially useful for the debconf annex.
diff --git a/doc/todo/add_metadata_to_annexed_files.mdwn b/doc/todo/add_metadata_to_annexed_files.mdwn
new file mode 100644
index 000000000..0fc3e8953
--- /dev/null
+++ b/doc/todo/add_metadata_to_annexed_files.mdwn
@@ -0,0 +1,5 @@
+I would like to attach metadata to annexed files (objects) without cluttering the workdir with files containing this metadata. A common use case would be to add titles to my photo collection that could than end up in a generated photo album.
+
+Depending on the implementation it might also be possible to use the metadata facility for a threaded commenting system.
+
+The first question is whether the metadata is attached to the objects and thus shared by all paths pointing to the same data object or to paths in the worktree. I've no preference here at this point.
diff --git a/doc/todo/add_metadata_to_annexed_files/comment_1_38af9b352020194e9ace34d7dde188cf._comment b/doc/todo/add_metadata_to_annexed_files/comment_1_38af9b352020194e9ace34d7dde188cf._comment
new file mode 100644
index 000000000..8460300a7
--- /dev/null
+++ b/doc/todo/add_metadata_to_annexed_files/comment_1_38af9b352020194e9ace34d7dde188cf._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T19:58:54Z"
+ content="""
+I don't know if git-annex is the right vehicle to fix this. It seems that a more generic fix that would work in non-git-annex repos would be better.
+
+I can answer your question though: The metadata such as urls and locations that git-annex stores in the git-annex branch is attached to objects, and not to work tree paths.
+"""]]
diff --git a/doc/todo/checksum_verification_on_transfer.mdwn b/doc/todo/checksum_verification_on_transfer.mdwn
new file mode 100644
index 000000000..e87907d56
--- /dev/null
+++ b/doc/todo/checksum_verification_on_transfer.mdwn
@@ -0,0 +1,7 @@
+Since most file transfers, particularly to/from encrypted special remotes involve git-annex streaming through the contents of the file anyway, it should be possible to add a verification of the checksum nearly for free. The main thing needed is probably a faster haskell checksum library than Data.Digest.Pure.Sha, which is probably slow enough to be annoying.
+
+I have not verified if an upload could be aborted before sending the data to the remote if a checksum failure is detected. It may be dependent on the individual special remote implementations. Some probably stream the encrypted data directly out the wire, while others need to set up a temp file to run a command on. It would certianly be possible to at least make the upload abort and fail if a bad checksum was detected.
+
+Doing the same for downloads is less useful, because the data is there locally to be fscked. The real advantage would be doing the check for uploads, to ensure that hard-to-detect corrupted files don't reach special remotes.
+
+--[[Joey]]
diff --git a/doc/todo/checksum_verification_on_transfer/comment_1_30f77e631608b9751f9032f97d58cc30._comment b/doc/todo/checksum_verification_on_transfer/comment_1_30f77e631608b9751f9032f97d58cc30._comment
new file mode 100644
index 000000000..5de1251da
--- /dev/null
+++ b/doc/todo/checksum_verification_on_transfer/comment_1_30f77e631608b9751f9032f97d58cc30._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 1"
+ date="2013-09-09T11:50:05Z"
+ content="""
+Doing this during downloads would still be nice.
+
+While the files are easier to fsck, users will need to actually do this. If it happenend automatically, it would increase safety and reduce disk i/o.
+
+Of course, this will not detect degradation during/after writing.
+
+If you don't make it the default, please at least make it optional for us bordering on OCD when it comes to data storage.
+
+
+Richard
+"""]]
diff --git a/doc/todo/direct_mode_guard.mdwn b/doc/todo/direct_mode_guard.mdwn
index 7322cec63..bb7f90897 100644
--- a/doc/todo/direct_mode_guard.mdwn
+++ b/doc/todo/direct_mode_guard.mdwn
@@ -20,3 +20,86 @@ add`. The git wrapper could instead be another program, or it could be
something like `git annex git add`
--[[Joey]]
+
+----
+
+Or, no git wrapper could be provided. Limit the commands to only git-annex
+commands. This should be all that is needed to manage a direct mode
+repository simply, and if the user is doing something complicated that
+needs git access, they can set `GIT_DIR=.git-annex` and be careful not to
+shoot off their foot. (Or can just switch to indirect mode!)
+
+This wins on simplicity, and if it's the wrong choice a git wrapper
+can be added later. --[[Joey]]
+
+---
+
+Implementation: Pretty simple really. Already did the hard lifting to
+support `GIT_DIR`, so only need to override the default git directory
+in direct mode when that's not set to `.git-annex`.
+
+A few things hardcode ".git", including Assistant.Threads.Watcher.ignored
+and `Seek.withPathContents`, and parts of `Git.Construct`.
+
+---
+
+Transition: git-annex should detect when it's in a direct mode repository
+with a .git directory and no .git-annex directory, and transparently
+do the move to transition to the new scheme. (And remember that `git annex
+indirect` needs to move it back.)
+
+# alternative approach: move index
+
+Rather than moving .git, maybe move .git/index?
+
+This would cause git to think that all files in the tree were deleted.
+So git commit -a would make a commit that removes them from git history.
+But, the files in the work tree are not touched by this.
+
+Also, git checkout, git merge, and other things that manipulate the work
+tree refuse to do anything if they'd change a file that they think is
+untracked.
+
+Hmm, this does't solve the user accidentially running git add on an annexed
+file; the whole file still gets added.
+
+# alternative approach: fake bare repo
+
+Set core.bare to true. This prevents all work tree operations,
+so prevents any foot shooting. It still lets the user run commands like
+git log, even on files in the tree, and git fetch, and push, and git
+config, etc.
+
+Even better, it integrates with other tools, like `mr`, so they know
+it's a git repo.
+
+This seems really promising. But of course, git-annex has its own set of
+behaviors in a bare repo, so will need to recognise that this repo is not
+really bare, and avoid them.
+
+> [[done]]!! --[[Joey]]
+
+(Git may also have some bare repo behaviors that are unwanted. One example
+is that git allows pushes to the current branch in a bare repo,
+even when `receive.denyCurrentBranch` is set.)
+
+> This is indeed a problem. Indeed, `git annex sync` successfully
+> pushes changes to the master branch of a fake bare direct mode repo.
+>
+> And then, syncing in the repo that was pushed to causes the changes
+> that were pushed to the master branch to get reverted! This happens
+> because sync commits; commit sees that files are staged in index
+> differing from the (pushed) master, and commits the "changes"
+> which revert it.
+>
+> Could fix this using an update hook, to reject the updated of the master
+> branch. However, won't work on crippled filesystems! (No +x bit)
+>
+> Could make git annex sync detect this. It could reset the master
+> branch to the last one committed, before committing. Seems very racy
+> and hard to get right!
+>
+> Could make direct mode operate on a different branch, like
+> `annex/direct/master` rather than `master`. Avoid pushing to that
+> branch (`git annex sync` can map back from it to `master` and push there
+> instead). A bit clumsy, but works.
diff --git a/doc/todo/direct_mode_guard/comment_2_85bdb9dc601b87bd7c77150d7b0a5cde._comment b/doc/todo/direct_mode_guard/comment_2_85bdb9dc601b87bd7c77150d7b0a5cde._comment
new file mode 100644
index 000000000..7cf37a917
--- /dev/null
+++ b/doc/todo/direct_mode_guard/comment_2_85bdb9dc601b87bd7c77150d7b0a5cde._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawm7AuSfii_tCkLyspL6Mr0ATlO6OxLNYOo"
+ nickname="Georg"
+ subject="comment 2"
+ date="2013-09-20T11:29:04Z"
+ content="""
+Maybe make a git sub-namespace of commands. Yeah, I know, something like git annex git-add sounds a bit on the verbose side, but it would allow access to possibly all git commands regardless of name clashes.
+"""]]
diff --git a/doc/todo/faster_gnupg_cipher.mdwn b/doc/todo/faster_gnupg_cipher.mdwn
index a1cfd428d..f5ff062d2 100644
--- a/doc/todo/faster_gnupg_cipher.mdwn
+++ b/doc/todo/faster_gnupg_cipher.mdwn
@@ -1 +1,9 @@
-Apparently newer gnupg has support for hardware-accelerated AES-NI. It would be good to have an option to use that. I also wonder if using the same symmetric key for many files presents a security issues (and whether using GPG keys directly would be more secure).
+Apparently newer gnupg has support for hardware-accelerated AES-NI. It
+would be good to have an option to use that. I also wonder if using the
+same symmetric key for many files presents a security issues (and whether
+using GPG keys directly would be more secure).
+
+> [[done]]; you can now use encryption=pubkey when setting up a special
+> remote to use pure public keys without the hybrid symmetric key scheme.
+> Which you choose is up to you. Also, annex.gnupg-options can configure
+> the ciphers used. --[[Joey]]
diff --git a/doc/todo/faster_gnupg_cipher/comment_3_bd0c975494333dfe558de048d888ace8._comment b/doc/todo/faster_gnupg_cipher/comment_3_bd0c975494333dfe558de048d888ace8._comment
new file mode 100644
index 000000000..d0b98b7f6
--- /dev/null
+++ b/doc/todo/faster_gnupg_cipher/comment_3_bd0c975494333dfe558de048d888ace8._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 3"
+ date="2013-08-19T13:44:35Z"
+ content="""
+AES-NI acceleration will be used by default providing you're using
+the new modularized GnuPG (v2.x) and libgcrypt ≥ 1.5.0. Of course it
+only speeds up AES encryption, while GnuPG uses CAST by default; you can
+either set `personal-cipher-preferences` to AES or AES256 in your
+`gpg.conf` or, as joeyh hinted at, set `remote.<name>.annex-gnupg-options`
+as described in the manpage.
+
+By the way, I observed a significant speed up when using `--compress-algo none`.
+Image, music and video files are typically hard to compress further, and it seems
+that's where gpg spent most of its time, at least on the few files I benchmarked.
+"""]]
diff --git a/doc/todo/faster_rsync_remotes.mdwn b/doc/todo/faster_rsync_remotes.mdwn
index 5ece25008..8c40b2816 100644
--- a/doc/todo/faster_rsync_remotes.mdwn
+++ b/doc/todo/faster_rsync_remotes.mdwn
@@ -1 +1,4 @@
Using an rsync remote is currently very slow when there are a lot of files, since rsync appears to be called for each file copied. It would be awesome if each call to rsync was amortized to copy many files; rsync is very good at copying many small files quickly.
+
+> [[done]]; bug submitter was apparently not using a version
+> with rsync connection caching. --[[Joey]]
diff --git a/doc/todo/http_git_annex_404_retry.mdwn b/doc/todo/http_git_annex_404_retry.mdwn
new file mode 100644
index 000000000..38ab860bb
--- /dev/null
+++ b/doc/todo/http_git_annex_404_retry.mdwn
@@ -0,0 +1,16 @@
+A repository like http://annex.debconf.org/debconf-share/ has a git repo
+published via http. When getting files from such a repo, git-annex tries
+two urls. One url would be used by a bare repo, and the other by a non-bare
+repo. (This is due to the directory hashing change.) Result is every file
+download from a non-bare http repo starts with a 404 and then it retries
+with the right url.
+
+Since git-annex already downloads the .git/config to find the uuid of the
+http repo, it could also look at it to see if the repo is bare. If not,
+set a flag, and try the two urls in reverse order, which would almost
+always avoid this 404 problem.
+
+(The real solution is probably to flag day and get rid of the old-style
+directory hashing, but that's been discussed elsewhere.)
+
+--[[Joey]]
diff --git a/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template.mdwn b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template.mdwn
new file mode 100644
index 000000000..46d9de34f
--- /dev/null
+++ b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template.mdwn
@@ -0,0 +1,5 @@
+It would be great to be able to use the pubDate of the entries with the --template option of importfeed.
+
+Text.Feed.Query has a getItemPublishDate (and a getFeedPubDate, if we want some kind of ${feeddate}).
+
+The best would be to allow a reformating of the date(s) with (for example) %Y-%m-%D
diff --git a/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_1_62752c760fc12eca0c34d67d58753d00._comment b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_1_62752c760fc12eca0c34d67d58753d00._comment
new file mode 100644
index 000000000..cc3d85faf
--- /dev/null
+++ b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_1_62752c760fc12eca0c34d67d58753d00._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="gueux"
+ ip="2a01:240:fe6d:0:7986:3659:a8bd:64f1"
+ subject="syntax"
+ date="2013-09-12T14:05:16Z"
+ content="""
+use \"itemdate\" and \"feeddate\" as names?
+
+use ${itemdate=%Y-%m-%D} syntax option?
+"""]]
diff --git a/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_2_21672360060f48bc2eacfa535ff4c94d._comment b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_2_21672360060f48bc2eacfa535ff4c94d._comment
new file mode 100644
index 000000000..c8770ec6e
--- /dev/null
+++ b/doc/todo/importfeed:_allow___36____123__itemdate__125___with_--template/comment_2_21672360060f48bc2eacfa535ff4c94d._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.2.134"
+ subject="comment 2"
+ date="2013-09-13T19:53:52Z"
+ content="""
+getItemPublishDate returns a String, which can contain any of several date formats. Deferred until the feed library has something more sane.
+Upstream bug: <https://github.com/sof/feed/issues/6>
+
+As for how to format the date in the feed, I would be ok with having itemdate (YYYYMMDD), itemyear (YYYY), itemmonth (MM) and itemday (DD). Full date formatting seems like overkill here.
+"""]]
diff --git a/doc/todo/keep_annexed_files_for_a_while.mdwn b/doc/todo/keep_annexed_files_for_a_while.mdwn
new file mode 100644
index 000000000..cf85b11f3
--- /dev/null
+++ b/doc/todo/keep_annexed_files_for_a_while.mdwn
@@ -0,0 +1,8 @@
+I don't want files that I dropped to immediately disappear from my local or all of my remotes repos on the next sync. Especially in situations where changes to the git-annex repo get automatically and immediately replicated to remote repos, I want a configurable "grace" period before files in .git/annex/objects get really deleted.
+
+This has similarities to the "trash" on a desktop. It might also be nice to
+
+* configure a maximum amount of space of the "trash"
+* have a way to see the contents of the trash to easily recover deleted files
+
+Maybe it would make sense to just move dropped files to the desktops trash? "git annex trash" as an alternative to drop?
diff --git a/doc/todo/makefile:_respect___36__PREFIX.mdwn b/doc/todo/makefile:_respect___36__PREFIX.mdwn
new file mode 100644
index 000000000..12d7274b9
--- /dev/null
+++ b/doc/todo/makefile:_respect___36__PREFIX.mdwn
@@ -0,0 +1,25 @@
+The `Makefile` should respect a `PREFIX` passed on the commandline so git-annex can be installed in (say) `$HOME`.
+
+Simple patch:
+
+[[!format diff """
+diff --git a/Makefile b/Makefile
+index b8995b2..5b1a6d4 100644
+--- a/Makefile
++++ b/Makefile
+@@ -3,7 +3,7 @@ all=git-annex $(mans) docs
+
+ GHC?=ghc
+ GHCMAKE=$(GHC) $(GHCFLAGS) --make
+-PREFIX=/usr
++PREFIX?=/usr
+ CABAL?=cabal # set to "./Setup" if you lack a cabal program
+
+ # Am I typing :make in vim? Do a fast build.
+"""]]
+
+--[[anarcat]]
+
+> [[done]] --[[Joey]]
+
+> > [[thanks]]! ;) --[[anarcat]]
diff --git a/doc/todo/mdwn2man:_make_backticks_bold.mdwn b/doc/todo/mdwn2man:_make_backticks_bold.mdwn
new file mode 100644
index 000000000..21707a309
--- /dev/null
+++ b/doc/todo/mdwn2man:_make_backticks_bold.mdwn
@@ -0,0 +1,22 @@
+The traditionnal way of marking commandline flags in a manpage is with a `.B` (for Bold, I guess). It doesn't seem to be used by mdwn2man, which makes the manpage look a little more dull than it could.
+
+The following patch makes those options come out more obviously:
+
+[[!format diff """
+diff --git a/Build/mdwn2man b/Build/mdwn2man
+index ba5919b..7f819ad 100755
+--- a/Build/mdwn2man
++++ b/Build/mdwn2man
+@@ -8,6 +8,7 @@ print ".TH $prog $section\n";
+
+ while (<>) {
+ s{(\\?)\[\[([^\s\|\]]+)(\|[^\s\]]+)?\]\]}{$1 ? "[[$2]]" : $2}eg;
++ s/\`([^\`]*)\`/\\fB$1\\fP/g;
+ s/\`//g;
+ s/^\s*\./\\&./g;
+ if (/^#\s/) {
+"""]]
+
+I tested it against the git-annex manpage and it seems to work well. --[[anarcat]]
+
+> [[done]], thanks --[[Joey]]
diff --git a/doc/todo/nicer_whereis_output.mdwn b/doc/todo/nicer_whereis_output.mdwn
new file mode 100644
index 000000000..871eee01a
--- /dev/null
+++ b/doc/todo/nicer_whereis_output.mdwn
@@ -0,0 +1,100 @@
+We had some informal discussions on IRC about improving the output of the `whereis` command.
+
+[[!toc levels=2]]
+
+First version: columns
+======================
+
+[[mastensg]] started by implementing a [simple formatter](https://gist.github.com/mastensg/6500982) that would display things in columns [screenshot](http://www.ping.uio.no/~mastensg/whereis.png)
+
+Second version: Xs
+==================
+
+After some suggestions from [[joey]], [[mastensg]] changed the format slightly ([screenshot](http://www.ping.uio.no/~mastensg/whereis2.png)):
+
+[[!format txt """
+17:01:34 <joeyh> foo
+17:01:34 <joeyh> |bar
+17:01:34 <joeyh> ||baz (untrusted)
+17:01:34 <joeyh> |||
+17:01:34 <joeyh> XXx 3? img.png
+17:01:36 <joeyh> _X_ 1! bigfile
+17:01:37 <joeyh> XX_ 2 zort
+17:01:39 <joeyh> __x 1?! maybemissing
+17:02:09 * joeyh does a s/\?/+/ in the above
+17:02:24 <joeyh> and decrements the counters for untrusted
+17:03:37 <joeyh> __x 0+! maybemissing
+"""]]
+
+Third version: incremental
+==========================
+
+Finally, [[anarcat]] worked on making it run faster on large repositories, in a [fork](https://gist.github.com/anarcat/6502988) of that first gist. Then paging was added (so headers are repeated).
+
+Fourth version: tuning and blocked
+==================================
+
+[[TobiasTheViking]] provided some bugfixes, and the next step was to implement the trusted/untrusted detection, and have a counter.
+
+This required more advanced parsing of the remotes, and instead of starting to do some JSON parsing, [[anarcat]] figured it was time to learn some Haskell instead.
+
+Current status: needs merge
+===========================
+
+So right now, the most recent version of the python script is in [anarcat's gist](https://gist.github.com/anarcat/6502988) and works reasonably well. However, it doesn't distinguish between trusted and untrusted repos and so on.
+
+Furthermore, we'd like to see this factored into the `whereis` command directly. A [raw.hs](http://codepad.org/miVJb5oK) file has been programmed by `mastensg`, and is now available in the above gist. It fits the desired output and prototypes, and has been `haskellized` thanks to [[guilhem]].
+
+Now we just need to merge those marvelous functions in `Whereis.hs` - but I can't quite figure out where to throw that code, so I'll leave it to someone more familiar with the internals of git-annex. The most recent version is still in [anarcat's gist](https://gist.github.com/anarcat/6502988). --[[anarcat]]
+
+Desired output
+--------------
+
+The output we're aiming for is:
+
+ foo
+ |bar
+ ||baz (untrusted)
+ |||
+ XXx 2+ img.png
+ _X_ 1! bigfile
+ XX_ 2 zort
+ __x 0+! maybemissing
+
+Legend:
+
+ * `_` - file missing from repo
+ * `x` - file may be present in untrusted repo
+ * `X` - file is present in trusted repo
+ * `[0-9]` - number of copies present in trusted repos
+ * `+` - indicates there may be more copies present
+ * `!` - indicates only one copy is left
+
+Implementation notes
+--------------------
+
+[[!format txt """
+20:48:18 <joeyh> if someone writes me a headerWhereis :: [(RemoteName, TrustLevel)] -> String and a formatWhereis :: [(RemoteName, TrustLevel, UUID)] -> [UUD] -> FileName -> String , I can do the rest ;)
+20:49:22 <joeyh> make that second one formatWhereis :: [(RemoteName, TrueLevel, Bool)] -> FileName -> String
+20:49:37 <joeyh> gah, typos
+20:49:45 <joeyh> suppose you don't need the RemoteName either
+"""]]
+
+> So, I incorporated this, in a new remotes command.
+> Showing all known repositories seemed a bit much
+> (I have 30-some known repositories in some cases),
+> so just showing configured remotes seems a good simplification.
+> [[done]]
+> --[[Joey]]
+
+> > I would have prefered this to be optional since I don't explicitely configure all remotes in git, especially if I can't reach them all the time (e.g. my laptop). It seems to me this should at least be an option, but I am confused as to why `Remote.List.remoteList` doesn't list all remotes the same way `Remote.remote_list` does... Also, it's unfortunate that the +/!/count flags have been dropped, it would have been useful... Thanks for the merge anyways! --[[done]]
+> >
+> > The more I look at this, the more i think there are a few things wrong with the new `remotes` command.
+> >
+> > 1. the name is confusing: being a git addict, I would expect the `git annex remote` command to behave like the `git remote` command: list remotes, add remotes, remove remotes and so on. it would actually be useful to have such a command (which would replace `initremote`, I guess). i recommend replacing the current `whereis` command, even if enabled through a special flag
+> >
+> > 2. its behavior is inconsistent with other git annex commands: `git annex status`, for example, lists information about all remotes, regardless of whether they are configured in git. `remotes` (whatever it's called), should do the same, or at least provide an option to allow the user to list files on all remotes. The way things stand, there is no way to list files on non-git remotes, even if they are added explicitely as a remote, if the remote is not actually reachable: the files are just marked as absent (even thought `whereis` actually finds them). i recommend showing all remotes regardless, either opt-in or opt-out using a flag.
+> >
+> > 3. having the `!` flag, at least, would be useful because it would allow users to intuitively grep for problematic files without having to learn extra syntax. same with + and having an explicit count.
+> >
+> > thanks. --[[anarcat]]
diff --git a/doc/todo/redundancy_stats_in_status/comment_2_686ced0684d10511caf07953c64cd5b6._comment b/doc/todo/redundancy_stats_in_status/comment_2_686ced0684d10511caf07953c64cd5b6._comment
new file mode 100644
index 000000000..a4711b2a3
--- /dev/null
+++ b/doc/todo/redundancy_stats_in_status/comment_2_686ced0684d10511caf07953c64cd5b6._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 2"
+ date="2013-09-25T18:03:55Z"
+ content="""
+`git annex status .` or otherwise running it with a directory has recently started walking all the location logs for all files in the directory in order to display variance from configured numcopies. It would be easy to add a redundancy counter to that.
+
+It would slow down the global status when not passed a directory to add redundancy info there. Maybe local is enough?
+"""]]
diff --git a/doc/todo/smudge/comment_3_4e7c25fe24a1e71f58a8354fa64f41c2._comment b/doc/todo/smudge/comment_3_4e7c25fe24a1e71f58a8354fa64f41c2._comment
new file mode 100644
index 000000000..cd64b7001
--- /dev/null
+++ b/doc/todo/smudge/comment_3_4e7c25fe24a1e71f58a8354fa64f41c2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawn1QhtPvsRBV7pfaDW_ZTPFv_ZIxSzQ8Rg"
+ nickname="Paul Léo"
+ subject="comment 3"
+ date="2013-11-13T20:41:52Z"
+ content="""
+> SHA1 has a harder job. Would not want to re-sha1 the file every time, probably. So it'd need a local cache of file stat info, mapped to known objects.
+
+I think that is not true? If gits wants the file to be cleaned, it thinks that the file was changed. So you would have to SHA1 it anyway if you don't want rely on WORM (which git already does in the first step anyway).
+"""]]
diff --git a/doc/todo/support_for_lossy_remotes.mdwn b/doc/todo/support_for_lossy_remotes.mdwn
index e757343f4..23083b2d7 100644
--- a/doc/todo/support_for_lossy_remotes.mdwn
+++ b/doc/todo/support_for_lossy_remotes.mdwn
@@ -3,3 +3,9 @@ I'm curious if there's a possibility to support lossy remotes. It may be handy t
1. an online place that their videos are available from
2. a worst-case scenario "backup"
3. a remote that they could download smaller video files
+
+> [[done]]; lossy remotes are supported as seen with `git annex addurl
+> --fast` and also with the new addurl support for using quvi to get
+> videos fro youtube. Just make a key with a URL or something in it, and
+> no size or checksum, and any content will be assumed to be the right
+> content. --[[Joey]]
diff --git a/doc/todo/sync_my_local_git-annex_from_a_dump_remote.mdwn b/doc/todo/sync_my_local_git-annex_from_a_dump_remote.mdwn
new file mode 100644
index 000000000..524782bc7
--- /dev/null
+++ b/doc/todo/sync_my_local_git-annex_from_a_dump_remote.mdwn
@@ -0,0 +1,6 @@
+As discussed on debconf, I have the following use case:
+
+* I have a dump remote, a folder on my webserver where files are uploaded through the web app. I don't have git on the webserver, just a plain folder.
+* I have git-annex repo on a development server. The development server polls the webserver (ssh/ftp) once in an hour and synchronizes the state of the local git-annex repo with the state found on the webserver and commits that.
+* This is not meant to be backup facility. I just want to be able to have a state on my development machine that is very likely to the state on the webserver.
+
diff --git a/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_1_81d63854f89f00855cda5ace0fc8262a._comment b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_1_81d63854f89f00855cda5ace0fc8262a._comment
new file mode 100644
index 000000000..d9abb3a3c
--- /dev/null
+++ b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_1_81d63854f89f00855cda5ace0fc8262a._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-13T21:44:17Z"
+ content="""
+We had a conversation about this IRL. At the time, I thought I understood what you wanted. Reading the above, I am not so sure.
+
+What I thought you wanted was something like `git annex mirror --from remote`, which would, for each object known to git-annex that the location log said was present on the remote, make sure that the local repo had the object too, and for each object that the location log said was not present on the remote, drop it from the local repo (if numcopies etc allowed).
+
+`git annex mirror --to remote` could also be used as the complement of the above.
+
+If that's not the sort of thing you meant, let me know.
+"""]]
diff --git a/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_2_66822b72b1450e79e8edd0c6c21d5aa6._comment b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_2_66822b72b1450e79e8edd0c6c21d5aa6._comment
new file mode 100644
index 000000000..3d459371f
--- /dev/null
+++ b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_2_66822b72b1450e79e8edd0c6c21d5aa6._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://thkoch2001.myopenid.com/"
+ nickname="thkoch"
+ subject="pseudocode"
+ date="2013-08-14T04:58:22Z"
+ content="""
+lets say my local annex is in direct mode, then the following might already do what I want:
+
+cd $LOCAL_ANNEX
+rsync --recursive --delete $REMOTE .
+git annex add && git commit
+
+It would however be nice if I could do the same with an annex in indirect mode or even a bare annex.
+"""]]
diff --git a/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_3_b9f73375e2c732e798495f8ee6970c7c._comment b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_3_b9f73375e2c732e798495f8ee6970c7c._comment
new file mode 100644
index 000000000..df4be033b
--- /dev/null
+++ b/doc/todo/sync_my_local_git-annex_from_a_dump_remote/comment_3_b9f73375e2c732e798495f8ee6970c7c._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 3"
+ date="2013-08-24T16:35:33Z"
+ content="""
+Seems to me that this could easily be dealt with by installing git-annex on the webserver, making the directory there a git repository, and using either a cron job or `git annex watch` to commit files as they were changed there.
+
+Then you can make a direct mode, indirect mode, or even a bare clone on your local machine and use git-annex to get the files.
+
+Maybe you have good reasons for not wanting to go that route. And rsync on a direct mode repository should work, provided to tell it to not delete `.git`. :P I don't see any way to make rsync work in an indirect mode repository. As for trying to make git-annex handle this import over rsync itself in a way that would work in an indirect mode repository, let alone a bare repository -- I don't see a good way to do it and it seems quite special case and likely to get quite complicated to implement.
+
+In the meantime, I did implement `git annex mirror`, which I think is a much more interesting and generally useful tool to have. And could even be used in my recommended solution above.
+"""]]
diff --git a/doc/todo/untracked_remotes.mdwn b/doc/todo/untracked_remotes.mdwn
new file mode 100644
index 000000000..883b5acff
--- /dev/null
+++ b/doc/todo/untracked_remotes.mdwn
@@ -0,0 +1,9 @@
+Seems that a fairly common desire in some use cases is to be able to make a
+clone of a repository and be able to get files, without updating the
+location tracking information. (And without even recording a uuid in the
+remote.log.) Use cases include wanting to have temporary
+clones without cluttering history, and centralized development where the
+developers don't care to know about one-another's systems.
+
+It seems that such an untracked repository would need to automatically
+consider itself untrusted. Is that enough to avoid losing data?
diff --git a/doc/todo/whishlist:_git_annex_drop_--dry-run.mdwn b/doc/todo/whishlist:_git_annex_drop_--dry-run.mdwn
new file mode 100644
index 000000000..6bbfd7a4d
--- /dev/null
+++ b/doc/todo/whishlist:_git_annex_drop_--dry-run.mdwn
@@ -0,0 +1,5 @@
+It'd be useful to be able to see what `git annex drop` would do *before* asking it to drop any files.
+
+For example, I just set up my preferred contents expressions, and I don't know if I got them right. Before dropping anything from this repo, it'd be nice to check what would happen. I know git annex drop will only drop files that are above their minimum numcopies, but I'd still like to avoid heavyweight copying in case I got my preferred contents expressions wrong.
+
+> [[done]]; added --want-get and --want-drop. --[[Joey]]
diff --git a/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_1_20ecfa8ffa52c238d21b904076ac69a2._comment b/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_1_20ecfa8ffa52c238d21b904076ac69a2._comment
new file mode 100644
index 000000000..098d399e3
--- /dev/null
+++ b/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_1_20ecfa8ffa52c238d21b904076ac69a2._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-10-28T17:11:04Z"
+ content="""
+It would be nice, but it adds quite a lot of complexity to have a --dry-run, and if I add it to just drop, the next bug is going to ask for get to have it..
+
+I feel that the right approach is to add a --wanted, which could then be used with find to find files that are and are not wanted, according to the preferred content settings. To see what it would want to get: `git annex find --wanted --not --in .` To see what it would want to drop: `git annex find --not --wanted --in .`
+"""]]
diff --git a/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_2_d19bc268c9467d24baa8d8f77a6e5e09._comment b/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_2_d19bc268c9467d24baa8d8f77a6e5e09._comment
new file mode 100644
index 000000000..3f1102985
--- /dev/null
+++ b/doc/todo/whishlist:_git_annex_drop_--dry-run/comment_2_d19bc268c9467d24baa8d8f77a6e5e09._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnWwEEA3CurHkBjIYaJsJzFc4jtY2SCkrQ"
+ nickname="Diego"
+ subject="comment 2"
+ date="2013-10-29T00:28:51Z"
+ content="""
+That makes sense, and thanks for adding this feature so quickly!
+"""]]
diff --git a/doc/todo/windows_support.mdwn b/doc/todo/windows_support.mdwn
index 08327dba8..a8cbd6db8 100644
--- a/doc/todo/windows_support.mdwn
+++ b/doc/todo/windows_support.mdwn
@@ -9,7 +9,15 @@ now! --[[Joey]]
* rsync special remotes are known buggy.
* Bad file locking, it's probably not safe to run more than one git-annex
process at the same time on Windows.
-* No support for the assistant or webapp.
* Ssh connection caching does not work on Windows, so `git annex get`
has to connect twice to the remote system over ssh per file, which
is much slower than on systems supporting connection caching.
+* Webapp doesn't build yet.
+* `git annex watch` builds, but does not quite work.
+* `git annex assistant` builds, but has not been tested, and is known
+ to not download any files. (transferrer doesn't built yet)
+* watch and assistant cannot be built with cabal. Possibly due to too many
+ files overflowing command line length limit at link stage.
+ To build a binary with them:
+ `ghc --make git-annex.hs -threaded -XPackageImports -DWITH_ASSISTANT=1 -DWITH_WIN32NOTIFY=1`
+ (should add all the other flags cabal uses)
diff --git a/doc/todo/wishlist:_Freeing_X_space_on_remote_Y.mdwn b/doc/todo/wishlist:_Freeing_X_space_on_remote_Y.mdwn
new file mode 100644
index 000000000..5fec39d98
--- /dev/null
+++ b/doc/todo/wishlist:_Freeing_X_space_on_remote_Y.mdwn
@@ -0,0 +1 @@
+As suggested during the first Gitify BoF during DebConf13: Adding a way to have on-demand dropping of content in a given remote would allow a user to quickly free up disk space on demand while still heeding numcopies etc.
diff --git a/doc/todo/wishlist:___34__quiet__34___annex_get_for_centralized_use_case.mdwn b/doc/todo/wishlist:___34__quiet__34___annex_get_for_centralized_use_case.mdwn
index 27f4744c8..d53fa56ab 100644
--- a/doc/todo/wishlist:___34__quiet__34___annex_get_for_centralized_use_case.mdwn
+++ b/doc/todo/wishlist:___34__quiet__34___annex_get_for_centralized_use_case.mdwn
@@ -7,3 +7,8 @@ We would like to be able to get the files without updating the `git-annex` branc
I think the easiest way would be to just add an option to not update the `git-annex` branch when `annex get` is executed.
Thoughts?
+
+> See [[untracked_remotes]] for a todo item that will probably
+> be useful in this sitation. Since that describes better what
+> this bug report seems to be asking for, I am closing this one.
+> [[closed|done]] --[[Joey]]
diff --git a/doc/todo/wishlist:___39__get__39___queue_and_schedule..mdwn b/doc/todo/wishlist:___39__get__39___queue_and_schedule..mdwn
new file mode 100644
index 000000000..8919bae3f
--- /dev/null
+++ b/doc/todo/wishlist:___39__get__39___queue_and_schedule..mdwn
@@ -0,0 +1,30 @@
+During the campaign adding a chunking feature to obscure filesize for encrypted files was added to the roadmap. But there is still one potentially valuable set* of data that git-annex can help obscure: when you access your remotes.
+
+This data can be used to determine when a user is actively using a remote, but if a remote is always accessed at the same time that data becomes less useful. Somebody could still monitor total traffic over a long period and figure out that a remote was more active in a given week or month, but scheduling reduces the resolution of your access times and their data. Maybe this isn't the most important feature to add, but it would be nice to have, and could possibly be built on top of the existing git-annex scheduler. It could work by queuing inter-remote transactions ('get', 'copy', 'sync', etc.), so that jobs start at the same time every day, or even the same time and day every week.
+
+Possible syntax examples:
+###Setting up the schedule:
+git annex queue schedule Monday:1730 (starts every monday at 5:30PM)
+
+git annex queue schedule 1400 (starts every day at 2PM)
+
+###Queuing git-annex commands:
+git annex queue prepend sync (pretends 'sync' to the very front of the queue)
+
+git annex queue append get file.ISO (appends to queue file.ISO for retrieval from a repo)
+
+###Viewing/editing queue:
+git annex queue view (view the current queue, jobs displayed with corresponding numbers)
+
+git annex queue rm 20 (removes job 20 from queue)
+
+
+\*The four I can think of are:
+
+* File contents (solved by crypto)
+
+* File size (solved on the remote by chunking, but total traffic usage can't be helped)
+
+* User IP/Remote IP (solved by VPN - outside scope of git-annex, unless someone writes a plugin)
+
+* Access times (obscured by a queue and scheduling)
diff --git a/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__.mdwn b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__.mdwn
new file mode 100644
index 000000000..626f5a03f
--- /dev/null
+++ b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__.mdwn
@@ -0,0 +1,5 @@
+Also suggested during the first Gitify BoF during DebConf13:
+
+`git annex drop` deletes immediately. In some situations a mechanism to tell git-annex "I would like to hold onto this data if possible, but if you need the space, please delete it" could be nice.
+
+An obvious question would be how to do cleanups. With the assistant, that's easy. On CLI, at the very least `git annex fsck` should list, and optionally delete, that data.
diff --git a/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_1_c83a6cddd0ce222205a149cfa41ca395._comment b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_1_c83a6cddd0ce222205a149cfa41ca395._comment
new file mode 100644
index 000000000..32d0c0112
--- /dev/null
+++ b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_1_c83a6cddd0ce222205a149cfa41ca395._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://cstork.org/"
+ nickname="Chris Stork"
+ subject="How should this interact with the trust model and location tracking?"
+ date="2013-10-04T11:13:11Z"
+ content="""
+This could become complicated. AFAIU, right now git-annex keeps track of files as either present or absent. With this feature it's tempting to introduce a third state 'potentially dropped' (or 'dropped in a relaxed fashion') but do you then treat them as if they were dropped depending in wether they are on a trusted or untrusted repo? Or maybe a potentially dropped file in a trusted repo is treated as a file in a semitrusted repo? This becomes convoluted. You also need a command to undrop a file in case you decide that you really want to keep it and in order to do this you need a command to see which files are up for relaxed dropping....
+
+As an alternative approach maybe it makes sense to extend [[preferred content]] expressions to take file sizes and disk usage into account.
+"""]]
diff --git a/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_2_353fbc2bcc40cb8c9af42907a34c6e5a._comment b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_2_353fbc2bcc40cb8c9af42907a34c6e5a._comment
new file mode 100644
index 000000000..40f299fa0
--- /dev/null
+++ b/doc/todo/wishlist:___96__git_annex_drop_--relaxed__96__/comment_2_353fbc2bcc40cb8c9af42907a34c6e5a._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.243"
+ subject="comment 2"
+ date="2013-10-04T20:17:07Z"
+ content="""
+I don't think that a third state would be necessary. Actually dropping the file when it happens would need to do the same numcopies verification that `git annex drop` does now.
+
+I agree it might be simpler to first improve the power of preferred content expressions. Unfortunately one thing that cannot be put in them is anything that probes the current state of the system. This is because repo A on machine X needs to be able to calculate the preferred content of repo B on machine Y.
+But I could certainly add file size as a preferred content term, since that info is known throughout the network.
+"""]]
diff --git a/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp.mdwn b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp.mdwn
new file mode 100644
index 000000000..85c8874fc
--- /dev/null
+++ b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp.mdwn
@@ -0,0 +1,6 @@
+It could be useful for Linux users and package maintainers to have systemd .service file samples to launch the assistant and the webapp.
+
+For multi-user systems, we could have a git-annex-webapp@username.service .
+
+See [systemd documentation](http://www.freedesktop.org/software/systemd/man/systemd.service.html) for informations about those files.
+See [archlinux wiki](https://wiki.archlinux.org/index.php/Systemd/Services) for .service examples.
diff --git a/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_1_b89e90f9a70748c95aaf81740a40b76e._comment b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_1_b89e90f9a70748c95aaf81740a40b76e._comment
new file mode 100644
index 000000000..5e8c8a374
--- /dev/null
+++ b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_1_b89e90f9a70748c95aaf81740a40b76e._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="64.134.31.139"
+ subject="comment 1"
+ date="2013-10-19T15:33:18Z"
+ content="""
+Wouldn't this involve running it as root or a dedicated user? Neither is ideal. git-annex already uses .desktop files to auto-start when the user who is using it logs in.
+"""]]
diff --git a/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_2_d64361380cb18b98ddb43ada1c9f540a._comment b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_2_d64361380cb18b98ddb43ada1c9f540a._comment
new file mode 100644
index 000000000..5dfeedf37
--- /dev/null
+++ b/doc/todo/wishlist:_add_systemd_services_file_samples_for_assistant_and_webapp/comment_2_d64361380cb18b98ddb43ada1c9f540a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmVE2R20dyfPQIzdi6urVUUAXtD6eeBsr0"
+ nickname="Benoît"
+ subject="comment 2"
+ date="2013-10-19T15:43:36Z"
+ content="""
+ Not necessarily. I have a systemd instance handling my userland services. See [archlinux wiki systemd/User](https://wiki.archlinux.org/index.php/Systemd/User).
+"""]]
diff --git a/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods.mdwn b/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods.mdwn
new file mode 100644
index 000000000..849e73cc3
--- /dev/null
+++ b/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods.mdwn
@@ -0,0 +1,5 @@
+This is a wishlist item:
+
+Please allow the same remote to be available via different remotes. So in my LAN my remote is available using a ssh-connection, and when I travel with my laptop, the git-annex can also reach this remote using the Jabber transport.
+
+> [[done]]; this has always been fully supported. --[[Joey]]
diff --git a/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods/comment_1_abb6263f3807160222bba1122475c89c._comment b/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods/comment_1_abb6263f3807160222bba1122475c89c._comment
new file mode 100644
index 000000000..a95ba56f9
--- /dev/null
+++ b/doc/todo/wishlist:_allow_the_same_remote_to_be_accissable_via_different_methods/comment_1_abb6263f3807160222bba1122475c89c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="2001:4978:f:21a::2"
+ subject="comment 1"
+ date="2013-08-07T16:09:26Z"
+ content="""
+You can have as many git remotes as you like all pointing at the same repository via different paths. git-annex fully supports this AFAIK. Are you having some problem with it?
+"""]]
diff --git a/doc/bugs/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn b/doc/todo/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn
index 0dc9ec08a..0dc9ec08a 100644
--- a/doc/bugs/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn
+++ b/doc/todo/wishlist:_allow_users_to_provide_UUID_when_running___96__git_annex_init__96__.mdwn
diff --git a/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync.mdwn b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync.mdwn
new file mode 100644
index 000000000..873988eea
--- /dev/null
+++ b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync.mdwn
@@ -0,0 +1 @@
+The `annex.largefiles` feature is very nice to mix annexed files with normal git managed files. I'd like to be able to configure this setting on the webapp and that the configuration directive would be synchronized accross all remotes.
diff --git a/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_1_db632de391ce9fce42af51a770ed3aeb._comment b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_1_db632de391ce9fce42af51a770ed3aeb._comment
new file mode 100644
index 000000000..e402d26c3
--- /dev/null
+++ b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_1_db632de391ce9fce42af51a770ed3aeb._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="209.250.56.47"
+ subject="comment 1"
+ date="2013-11-05T16:46:28Z"
+ content="""
+It might make sense to sync this across remotes and have it edited with `git annex vicfg`
+
+Putting it in the webapp would need some nice interface for constructing the underlying expression. Might be doable for at least simple filtering (ie, files larger than XX or with extensions .A, .B, .C). I tend to think of this as a setting for people comfortable with the command line though.
+"""]]
diff --git a/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_2_4a0931d9884054d764fde315d4fe4851._comment b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_2_4a0931d9884054d764fde315d4fe4851._comment
new file mode 100644
index 000000000..0e24014d2
--- /dev/null
+++ b/doc/todo/wishlist:_annex.largefiles_configuration_in_webapp_and_sync/comment_2_4a0931d9884054d764fde315d4fe4851._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawne_amN4fko4p5cRY_9EYwaYuJKNn7LRio"
+ nickname="Tobias"
+ subject="feedback"
+ date="2013-11-05T21:23:11Z"
+ content="""
+> It might make sense to sync this across remotes and have it edited with git annex vicfg
+
+That would be great!
+
+> Putting it in the webapp would need some nice interface for constructing the underlying expression. Might be doable for at least simple filtering (ie, files larger than XX or with extensions .A, .B, .C). I tend to think of this as a setting for people comfortable with the command line though.
+
+I could live with a simple filtering interface without too many fancy stuff. The fancy stuff could be done on the command line if needed...
+"""]]
diff --git a/doc/todo/wishlist:_annex.largefiles_support_for_mimetypes/comment_1_304431bb62b5b8a64edc37a11bbaff59._comment b/doc/todo/wishlist:_annex.largefiles_support_for_mimetypes/comment_1_304431bb62b5b8a64edc37a11bbaff59._comment
new file mode 100644
index 000000000..b06008475
--- /dev/null
+++ b/doc/todo/wishlist:_annex.largefiles_support_for_mimetypes/comment_1_304431bb62b5b8a64edc37a11bbaff59._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawlhE8Xar6m4x3JSILXdm-Y5KhwHTH5qzKQ"
+ nickname="bruno"
+ subject="+1"
+ date="2013-10-14T14:43:11Z"
+ content="""
+Big +1 for this feature: this would really help configuring annex.largefiles
+"""]]
diff --git a/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space.mdwn b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space.mdwn
new file mode 100644
index 000000000..acc8b363e
--- /dev/null
+++ b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space.mdwn
@@ -0,0 +1 @@
+An interesting feature, when an archived file cannot be removed from all clients because of the minimum number of copies required, would be to remove it from the repositories with the smallest amount of free space available.
diff --git a/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_1_6813fdc7ecc98765a5d35d34163a1712._comment b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_1_6813fdc7ecc98765a5d35d34163a1712._comment
new file mode 100644
index 000000000..89fe4c069
--- /dev/null
+++ b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_1_6813fdc7ecc98765a5d35d34163a1712._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.153.14.105"
+ subject="comment 1"
+ date="2013-09-19T21:01:30Z"
+ content="""
+That might be useful in some cases. git-annex can only tell how much free space is available on remotes that are mounted to the local filesystem. Did you use case involve removable drives?
+"""]]
diff --git a/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_2_21a249cedca1ceb80d10784004735524._comment b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_2_21a249cedca1ceb80d10784004735524._comment
new file mode 100644
index 000000000..d2b29c239
--- /dev/null
+++ b/doc/todo/wishlist:_archive_from_remote_with_the_least_free_space/comment_2_21a249cedca1ceb80d10784004735524._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmOsy6nbvPyXLd--qqjPMLnVIzxgZwtKlQ"
+ nickname="Nicolas"
+ subject="comment 2"
+ date="2013-09-20T19:03:13Z"
+ content="""
+I was not thinking of removable drives, but only of \"client\" repositories. Ideally, git-annex would query the remaining space of all connected client repositories to choose on which repositories to drop a copy.
+"""]]
diff --git a/doc/todo/wishlist:_detection_of_merge_conflicts.mdwn b/doc/todo/wishlist:_detection_of_merge_conflicts.mdwn
new file mode 100644
index 000000000..1b4caeff0
--- /dev/null
+++ b/doc/todo/wishlist:_detection_of_merge_conflicts.mdwn
@@ -0,0 +1,13 @@
+A conflict during sync or merge is something that requires user intervention, or at least notification. For that reason it would be nice if git annex returned a nonzero exit status when such a conflict happened during a sync or a merge. This is what git does after a conflicting pull, and would make it easier to spot a conflict in automated syncs without having to parse annex output or the logs.
+
+> Good idea, [[done]]. --[[Joey]]
+
+Also, it would be nice if your new `git annex status` were able to inform about remaining conflicts in the repo, for instance by reporting files with variant-XXX suffix.
+
+> Hmm, that would need a separate pass through the whole tree, since
+> currently it can use `git ls-files` to find only modified/deleted/new
+> files. I would rather not make the new `git annex status` slower for
+> this.
+>
+> It would be possible to add it to `git annex info` (old `status`)
+> which already has to look through the entire work tree.
diff --git a/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied.mdwn b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied.mdwn
new file mode 100644
index 000000000..837f0a587
--- /dev/null
+++ b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied.mdwn
@@ -0,0 +1,6 @@
+When addWatcher gets a permission denied, it would be helpful to display the name of the object on which the permission was denied, in the error message which shows in the webapp.
+
+> I have made the inotify code more robust; now it doesn't crash if it
+> cannot read a directory or a file, and only logs a warning, which includes
+> the directory name.
+> [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_1_d2665e7347689b520d37561cfddf0aa8._comment b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_1_d2665e7347689b520d37561cfddf0aa8._comment
new file mode 100644
index 000000000..de0528855
--- /dev/null
+++ b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_1_d2665e7347689b520d37561cfddf0aa8._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T18:47:13Z"
+ content="""
+This is an exception from the inotify library, which is what contains the `addWatch` function. I catch and display the exception. Since `addWatch` is only passed a directory to watch, the most I could do is tack on the name of the directory when displaying the exception. That does not seem likely to be much help?
+"""]]
diff --git a/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_2_db153571a32fb072453ed583e3e9ccf4._comment b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_2_db153571a32fb072453ed583e3e9ccf4._comment
new file mode 100644
index 000000000..e0199a42d
--- /dev/null
+++ b/doc/todo/wishlist:_display_name_of_object_when_addWatcher_gets_a_permission_denied/comment_2_db153571a32fb072453ed583e3e9ccf4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl-g0hYpGY11pBP_42lHh5GWTyFuB4UwH8"
+ nickname="Nicolas"
+ subject="comment 2"
+ date="2013-09-25T23:08:56Z"
+ content="""
+Well, of course it would not be as helpful as if the inotify exception would contain the name of the exact object on which it got a permission denied (would this be a valid wishlist request for inotify?), but I think that displaying the name of the directory would already be better than nothing.
+"""]]
diff --git a/doc/todo/wishlist:_display_status_of_remotes_in_the_webapp.mdwn b/doc/todo/wishlist:_display_status_of_remotes_in_the_webapp.mdwn
new file mode 100644
index 000000000..741466994
--- /dev/null
+++ b/doc/todo/wishlist:_display_status_of_remotes_in_the_webapp.mdwn
@@ -0,0 +1 @@
+It would be nice to have an indication of the status of the remotes in the webapp, for example with a field showing "In Sync", "Syncing", or the date of the last successful synchronization for unreachable remotes.
diff --git a/doc/todo/wishlist:_dropping_git-annex_history.mdwn b/doc/todo/wishlist:_dropping_git-annex_history.mdwn
new file mode 100644
index 000000000..8286699c7
--- /dev/null
+++ b/doc/todo/wishlist:_dropping_git-annex_history.mdwn
@@ -0,0 +1,28 @@
+In real life discussions with git-annex users at DebConf, the idea was proposed to have a way to drop the history of the git-annex branch, and replace it with a new branch with just the current state of the repository.
+
+The only thing that breaks when this is done, in theory, is `git annex log`, which can't show the location history
+of files.
+
+The crucial thing is that this operation would only need to be done in one repository, and it would then record some information in its (new) git-annex branch, so when it was pushed to other repositories, git-annex there could notice that history had been dropped, and do the same. So, even if you have rarely used offline archive repositories, the history dropping would eventually reach them, without needing to remember to do it.
+
+There was speculation that it would be enough to record eg, the SHA of the top commit on the old branch. That may not be good enough, because another remote may have not gotten that SHA into its branch yet, or may have commits on top of that SHA.
+
+Maybe instead we want to record the SHA of the *first* commit to the old git-annex branch. This way, we can tell if the branch that got deleted is the one we're currently using. And if it is, we create a new branch with the current state of *our* branch, and then union merge the other branch into it.
+
+Hmm, another wrinkle is that, when this indication propigates from remote A to remote B, remote B may also have some git-annex branches available for remotes C and D, which have not transitioned, and E, which has transitioned already. It seems B should first union merge C and D into B, and then flatten B to B', and then union merge A and E into B'.
+
+I think that'd work!
+
+--[[Joey]]
+
+Will also allow dropping dead remotes from history. Just remove all
+references to them when rewriting the branch. May or may not be desirable;
+I sometimes care about dead remotes that I hope to one day recuscitate.
+(OTOH, I can always run git annex fsck in them to get their location
+tracking back, if I do manage to get them back.)
+
+--[[Joey]]
+
+See also : [[forum/safely_dropping_git-annex_history]]
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/wishlist:_dropping_git-annex_history/comment_1_a4bee2e26b22a9bdaadc05b7227769ef._comment b/doc/todo/wishlist:_dropping_git-annex_history/comment_1_a4bee2e26b22a9bdaadc05b7227769ef._comment
new file mode 100644
index 000000000..043e674ed
--- /dev/null
+++ b/doc/todo/wishlist:_dropping_git-annex_history/comment_1_a4bee2e26b22a9bdaadc05b7227769ef._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-24T19:39:45Z"
+ content="""
+BTW, a motivation for this is that some of us have old repositories that have been upgrades all the way from annex.version 1 and have a lot of cruft in them because of it. (I have repos that have been upgraded from annex.version 0, but this would not help with that cruft which is on the master branch!)
+
+Also, people worry that eg, a large copy back and forth bloats history, and having a way to unbloat it if it ever gets actually annoyingly bloated would stop them pestering me. ;)
+"""]]
diff --git a/doc/todo/wishlist:_dropping_git-annex_history/comment_2_f6d750bfe0c9d8a2aa6bc218ca5c49cc._comment b/doc/todo/wishlist:_dropping_git-annex_history/comment_2_f6d750bfe0c9d8a2aa6bc218ca5c49cc._comment
new file mode 100644
index 000000000..a60973b82
--- /dev/null
+++ b/doc/todo/wishlist:_dropping_git-annex_history/comment_2_f6d750bfe0c9d8a2aa6bc218ca5c49cc._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawl9sYlePmv1xK-VvjBdN-5doOa_Xw-jH4U"
+ nickname="Richard"
+ subject="comment 2"
+ date="2013-08-27T20:02:23Z"
+ content="""
+If starting commit id _and_ commit id from when history is being dropped are documented, you could potentially drop more data.
+
+* Don't have any commits in common? Full merge.
+* Only share the starting ids? Reduce local history as much as possible, and then merge.
+* Share both starting id and have the last id somewhere in history? Take history from last id up to current, reduce that, and merge.
+
+-- RichiH
+"""]]
diff --git a/doc/todo/wishlist:_encrypted_git_remote_on_hosting_site_from_webapp.mdwn b/doc/todo/wishlist:_encrypted_git_remote_on_hosting_site_from_webapp.mdwn
new file mode 100644
index 000000000..b7b1bad0c
--- /dev/null
+++ b/doc/todo/wishlist:_encrypted_git_remote_on_hosting_site_from_webapp.mdwn
@@ -0,0 +1 @@
+It would be great to be able to do **private encrypted git remote on hosting site** and **multiuser encrypted git remote on hosting site** as explained in [[tips/fully encrypted git repositories with gcrypt]] through the webapp. I think it's a pretty common usecase that can be very useful for people not owning a proper server.
diff --git a/doc/bugs/wishlist:_generic_annex.cost-command.mdwn b/doc/todo/wishlist:_generic_annex.cost-command.mdwn
index 6adf1460e..6adf1460e 100644
--- a/doc/bugs/wishlist:_generic_annex.cost-command.mdwn
+++ b/doc/todo/wishlist:_generic_annex.cost-command.mdwn
diff --git a/doc/bugs/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn b/doc/todo/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn
index 41c8e574b..41c8e574b 100644
--- a/doc/bugs/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn
+++ b/doc/todo/wishlist:_make_git_annex_reinject_work_in_direct_mode.mdwn
diff --git a/doc/bugs/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn b/doc/todo/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn
index 3a891fc9b..3a891fc9b 100644
--- a/doc/bugs/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn
+++ b/doc/todo/wishlist:_more_descriptive_commit_messages_in_git-annex_branch.mdwn
diff --git a/doc/bugs/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn b/doc/todo/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn
index 7a9b81f72..7a9b81f72 100644
--- a/doc/bugs/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn
+++ b/doc/todo/wishlist:_option_to_print_more_info_with___39__unused__39__.mdwn
diff --git a/doc/todo/wishlist:_perform_fsck_remotely.mdwn b/doc/todo/wishlist:_perform_fsck_remotely.mdwn
new file mode 100644
index 000000000..f2187d912
--- /dev/null
+++ b/doc/todo/wishlist:_perform_fsck_remotely.mdwn
@@ -0,0 +1,39 @@
+Currently, when `fsck`'ing a remote, files are first downloaded to a temporary
+file locally, decrypted if needed, and finally digested; the temporary file is
+then either thrown away, or quarantined, depending on the value of that digest.
+
+Whereas this approach works with any kind of remote, in the particular case
+where the user is granted execution rights on the digest command, one could
+avoid cluttering the network and digest the file remotely. I propose the
+addition of a per-remote git option `annex-remote-fsck` to switch between the
+two behaviors.
+
+
+There is an issue with encrypted specialremotes, though. As hinted at
+[[here|tips/beware_of_SSD_wear_when_doing_fsck_on_large_special_remotes/#comment-70055f166f7eeca976021d24a736b471]],
+since the digest of a ciphertext can't be deduced from that of a plaintext in
+general one would needs, before sending an encrypted file to such a remote, to
+digest it and store that digest somewhere (together with the cipher's size and
+perhaps other meta-information).
+
+The usual directory structure (`.../.../{backend}-s{size}--{digest}.log`) seems
+perfectly suitable to store these informations. Lines there would look like
+`{timestamp}s {numcopy} {UUID} {remote digest}`. Of course, it implies that
+remote digest commands are trustworthy (are doing the right thing), and that
+the digest output are not tampered by others who have access to the git repo.
+But that's outside the current threat model, I guess.
+
+Actually, since git-annex always includes a MDC in the ciphertexts, we could do
+something clever and even avoid running a digest algorithm. According to the
+[[OpenPGP standard|https://tools.ietf.org/html/rfc4880#section-5.14]] the MDC
+is essentially a SHA-1 hash of the plaintext. I'm still investigating if it's
+even possible, but in theory it would be enough (with non-chained ciphers at
+least) to download a few bytes from the encrypted remote, decrypt those bytes
+to retrieve the hash, and compare that hash with the known value. Of course
+there is a downside here, namely that files tampered anywhere but on the MDC
+packets would not be detected by `fsck` (but gpg will warn when decrypting the
+file).
+
+
+My 2 cents :-) Is there something I missed? I suppose there was a reason to
+perform `fsck` locally at the first place...
diff --git a/doc/todo/wishlist:_perform_fsck_remotely/comment_1_db92311dcdb1ef0ab0413f83e191c70c._comment b/doc/todo/wishlist:_perform_fsck_remotely/comment_1_db92311dcdb1ef0ab0413f83e191c70c._comment
new file mode 100644
index 000000000..6bf6af23a
--- /dev/null
+++ b/doc/todo/wishlist:_perform_fsck_remotely/comment_1_db92311dcdb1ef0ab0413f83e191c70c._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 1"
+ date="2013-08-22T15:18:35Z"
+ content="""
+The only reason fsck is done locally for remotes is ease of implementation and it being a generic operation that supports any kind of special remote.
+
+Seems that the the only types of remotes where a remote fsck is a possibility are some rsync remotes and git remotes.
+git remotes already have git-annex installed, so the fsck could be run locally on the remote system using it.
+
+I don't know if I see a benefit with the MDC check. Any non-malicious data corruption on the remote is likely to affect the body of the file and not the small portion that holds the MDC. So checking the MDC does not seem much better than the current existence check done by `git annex fsck --fast --from remote`.
+
+As for storing the remote digest on the git-annex branch, my initial reaction was just that it's potentially a lot of bloat. Thinking about it some more, when using non-shared encryption, there is currently no way, given just a clone of a git repository, to match up files in git with encrypted objects stored on a special remote. So storing the remote digest might be considered to weaken the security.
+"""]]
diff --git a/doc/todo/wishlist:_perform_fsck_remotely/comment_2_2f0dbaf143d94290bfbebb6869eb7241._comment b/doc/todo/wishlist:_perform_fsck_remotely/comment_2_2f0dbaf143d94290bfbebb6869eb7241._comment
new file mode 100644
index 000000000..5418ff991
--- /dev/null
+++ b/doc/todo/wishlist:_perform_fsck_remotely/comment_2_2f0dbaf143d94290bfbebb6869eb7241._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="guilhem"
+ ip="129.16.20.209"
+ subject="comment 2"
+ date="2013-08-22T16:56:55Z"
+ content="""
+Oh yeah, the MDC paragraph was pretty much pointless indeed. Oops :-P
+
+I agree that this would potentially add some noise to the index, and weaken the
+security, but depending on the threat model and people's preferences that's an
+option that's worth considering IMHO.
+"""]]
diff --git a/doc/bugs/wishlist:_query_things_like_description__44___trust_level.mdwn b/doc/todo/wishlist:_query_things_like_description__44___trust_level.mdwn
index d158850cd..d158850cd 100644
--- a/doc/bugs/wishlist:_query_things_like_description__44___trust_level.mdwn
+++ b/doc/todo/wishlist:_query_things_like_description__44___trust_level.mdwn
diff --git a/doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment b/doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment
index 3ac4ba267..3ac4ba267 100644
--- a/doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment
+++ b/doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_1_14311384788312b96e550749ab7de9ea._comment
diff --git a/doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment b/doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment
index 3bb92919f..3bb92919f 100644
--- a/doc/bugs/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment
+++ b/doc/todo/wishlist:_query_things_like_description__44___trust_level/comment_2_342d1ac07573c7ef4e27f003a692e261._comment
diff --git a/doc/bugs/wishlist:_simple_url_for_webapp.mdwn b/doc/todo/wishlist:_simple_url_for_webapp.mdwn
index 4549f2e74..4549f2e74 100644
--- a/doc/bugs/wishlist:_simple_url_for_webapp.mdwn
+++ b/doc/todo/wishlist:_simple_url_for_webapp.mdwn
diff --git a/doc/bugs/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment b/doc/todo/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment
index 1211be9b5..1211be9b5 100644
--- a/doc/bugs/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment
+++ b/doc/todo/wishlist:_simple_url_for_webapp/comment_1_552aad504fbb68d1f85abfde8c535e69._comment
diff --git a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote.mdwn b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote.mdwn
index 4227678ba..229dc258b 100644
--- a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote.mdwn
+++ b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote.mdwn
@@ -10,3 +10,13 @@ The [[Web special remote|special remotes/web]] could possibly be improved by det
> this.
>
> --[[Joey]]
+
+> > There's a library for this called [quvi](http://quvi.sourceforge.net/) which supports many
+> > different sites and also allows fetching the URL (as opposed to just
+> > downloading the file). It seems to me this would be the best tool
+> > for this task. One problem to consider here is that a single youtube
+> > URL may yield different file contents depending on the quality
+> > chosen. Also, it seems that the URLs guessed by quvi may be
+> > ephemeral. --[[anarcat]]
+
+> [[done]]!!! --[[Joey]]
diff --git a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_2_81f7f893ac36c145b31f02db6a682a17._comment b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_2_81f7f893ac36c145b31f02db6a682a17._comment
new file mode 100644
index 000000000..a25b3c89d
--- /dev/null
+++ b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_2_81f7f893ac36c145b31f02db6a682a17._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="quvi thoughts. excited!"
+ date="2013-08-22T18:22:51Z"
+ content="""
+Anarcat's quvi suggestion is interesting, because it seems to simplify the whole thing down to just `addurl`, which git-annex is already good at.
+
+If quvi manages to find the url that can be used to download the actual video file, without needing to run a special downloader, then all you really need, it seems, is `git annex addurl --relaxed $(quvi youtube-url)` The --relaxed will make git-annex not care if the content or size of the url's content varies in the future. Since --relaxed skips the actual download, you'd want to follow that with `git annex get`, since we don't know how long these urls will last..
+
+I suppose git-annex could, if quvi is available, make any attempt to download a web special remote url that
+matches the `quvi --support` output run the url through quvi to get the real url and download that instead. The difficulties with this approach:
+
+* would need to read and parse `quvi --support` every time it gets an url from the web special remote? (I don't think I'd want to link with libquvi, although that would be possible, just because this is an edge thing.)
+* what it an url that had been supported stopped being supported -- we'd not want to download the raw url in that case
+* putting the quvi support here doesn't allow relaxed mode to be set when `addurl` adds the url.
+
+Maybe it would be better to keep the support in `addurl`, and record the url generated by quvi. That url would probably be more likely to break in the future, but that kind of breakage is why `git annex untrust web` is wise..
+Keeping the support in `addurl` would also let it use the title that quvi also returns to determine the filename it creates.
+"""]]
diff --git a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_3_a7e3cd68c5e5f05139151a58f358df95._comment b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_3_a7e3cd68c5e5f05139151a58f358df95._comment
new file mode 100644
index 000000000..c4d8cf754
--- /dev/null
+++ b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_3_a7e3cd68c5e5f05139151a58f358df95._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.154.0.63"
+ subject="comment 3"
+ date="2013-08-22T18:44:15Z"
+ content="""
+Since the quvi urls are quite likely to break as the CDNs etc change things around, maybe it would be better to somehow have addurl tag an url as needing to be downloaded with quvi. Then `git annex get` could re-run quvi to get an url to download.
+
+We could expand url syntax for this. `quvi:http://youtube.com/foo`
+This also allows for future expansion for other similar things.
+
+I'd be inclined to still make `addurl` automatically try quvi to see if an url is supported, rather than requiring the user fix up the url themselves. But if trying quvi turns out to be too expensive, manually specifying it in the url would also work.
+"""]]
diff --git a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_4_a57947ed257b28bbe995a68bfeb5eeaa._comment b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_4_a57947ed257b28bbe995a68bfeb5eeaa._comment
new file mode 100644
index 000000000..ee0ab45e7
--- /dev/null
+++ b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_4_a57947ed257b28bbe995a68bfeb5eeaa._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://rmunn.myopenid.com/"
+ nickname="rmunn"
+ subject="comment 4"
+ date="2013-08-24T15:31:36Z"
+ content="""
+Either quvi or youtube-dl might be a good possibility: youtube-dl has the --get-url option (or -g for short) that outputs just the download URL (and nothing else) to stdout. So if for some reason quvi turned out not to be suitable, it wouldn't necessarily mean the idea would have to be abandoned.
+"""]]
diff --git a/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_5_a0612ae05dbda7f7935be648b42b30fc._comment b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_5_a0612ae05dbda7f7935be648b42b30fc._comment
new file mode 100644
index 000000000..38ac09511
--- /dev/null
+++ b/doc/todo/wishlist:_special-case_handling_of_Youtube_URLs_in_Web_special_remote/comment_5_a0612ae05dbda7f7935be648b42b30fc._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="aaaaawesome!"
+ date="2013-08-26T04:43:27Z"
+ content="""
+wow, thanks! i am happy my little suggestion led to an actual implentation, great!
+"""]]
diff --git a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn b/doc/todo/wishlist:_support_drop__44___find_on_special_remotes.mdwn
index 24cacbf71..24cacbf71 100644
--- a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes.mdwn
+++ b/doc/todo/wishlist:_support_drop__44___find_on_special_remotes.mdwn
diff --git a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment b/doc/todo/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment
index 6028933b4..6028933b4 100644
--- a/doc/bugs/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment
+++ b/doc/todo/wishlist:_support_drop__44___find_on_special_remotes/comment_1_f11ed642a83d965076778a162f701e84._comment
diff --git a/doc/todo/wishlist:_unify_directory_scheme_for_the_store.mdwn b/doc/todo/wishlist:_unify_directory_scheme_for_the_store.mdwn
new file mode 100644
index 000000000..83ce53127
--- /dev/null
+++ b/doc/todo/wishlist:_unify_directory_scheme_for_the_store.mdwn
@@ -0,0 +1,20 @@
+In regular repos, objects are stored in files of the form: .git/annex/objects/xY/z1/SHA1-.../SHA1-.... (scheme 1)
+
+On (some) special remotes, the corresponding file is stored at: .../abc/def/SHA1-... (scheme 2)
+
+I'm not sure why the same scheme as in .git/objects isn't used, but it would be useful that the two-directory prefix were the same for all objects stores.
+
+My use case is: I synchronize a git repo, say containing photos, to a server on which I can't install git-annex. I want the server to store all annexed files. For the photos to be viewed online, the annex store must use the scheme 1 (because the symlinks point to files with scheme 1). So I need to rsync .git/annex/objects manually from my desktop, because a git-annex rsync remote uses scheme 2. On the other hand, the repo on this server is not known by git-annex (like it would if I used a rsync remote).
+
+At least it would be valuable (to get around above problem) to have a plumbing command giving the 2-directory prefix from a given key, for example:
+
+$ git annex prefix-dir SHA1-s2--3f786850e387550fdab836ed7e6dc881
+
+7w/88
+
+f18/122
+
+
+Even if the 2 schemes were unified, this prefix-dir command would still be useful when hacking around git-annex (for now I need to maintain a dictionary structure).
+
+Thanks a lot.
diff --git a/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_1_44da58beaaab359ecaba7fb905ca4ae1._comment b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_1_44da58beaaab359ecaba7fb905ca4ae1._comment
new file mode 100644
index 000000000..86c33d434
--- /dev/null
+++ b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_1_44da58beaaab359ecaba7fb905ca4ae1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.243"
+ subject="comment 1"
+ date="2013-10-04T20:50:33Z"
+ content="""
+Using the mixed case hash directory names is not desirable because people want to use git-annex on a variety of filesystems and operating systems that treat them in a variety of broken ways. However, migrating to the all lower case hash directory names would require changing every git-annex symlink in every git repository, and I do not want to inflict that on my users.
+
+It seems to me that the best solution to your problem is to install git-annex on your server, which should not be very hard.
+"""]]
diff --git a/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_2_bc698c501ecdb56df57171f4f3bb831a._comment b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_2_bc698c501ecdb56df57171f4f3bb831a._comment
new file mode 100644
index 000000000..5c5269f8c
--- /dev/null
+++ b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_2_bc698c501ecdb56df57171f4f3bb831a._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnpdM9F8VbtQ_H5PaPMpGSxPe_d5L1eJ6w"
+ nickname="Rafaël"
+ subject="comment 2"
+ date="2013-10-05T10:45:16Z"
+ content="""
+Thank you for prompt answer. I didn't know there were tarballs,
+and indeed I managed to install them easily (although I had to
+manually install glibc version 2.9, only 2.7 was installed).
+
+I found that bare git repos also use lower case hash directory
+names... I still would be happy with an optional migration to all
+lower case, with a new key-value backend, to avoid this little
+complication which happens sometimes (say when converting a repo
+from non-bare to bare).
+"""]]
diff --git a/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_3_e555d0dbbaa05528806905c6a940724b._comment b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_3_e555d0dbbaa05528806905c6a940724b._comment
new file mode 100644
index 000000000..e6acad3b9
--- /dev/null
+++ b/doc/todo/wishlist:_unify_directory_scheme_for_the_store/comment_3_e555d0dbbaa05528806905c6a940724b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawnpdM9F8VbtQ_H5PaPMpGSxPe_d5L1eJ6w"
+ nickname="Rafaël"
+ subject="comment 3"
+ date="2013-10-07T13:33:40Z"
+ content="""
+By the way, I just had the case above, i.e. convert a bare repo to non-bare. In order to keep the annex files, I cloned the bare one, and git-annex move'ed all annex content to the new repo, and to my surprise it was slow, as if all files where copied (or maybe they were only checksummed?), instead of being only renamed (old and new repos were on the same partition). So I restate that at least a command line tool giving the prefix dirs would be useful, to allow scripting for this kind of situation.
+"""]]
diff --git a/doc/todo/wishlist:_use_hardlinks_for_local_clones.mdwn b/doc/todo/wishlist:_use_hardlinks_for_local_clones.mdwn
new file mode 100644
index 000000000..4b0694422
--- /dev/null
+++ b/doc/todo/wishlist:_use_hardlinks_for_local_clones.mdwn
@@ -0,0 +1,9 @@
+as far as I know, if you `git clone` locally a git-annex enabled repository, it will not have all the files available. you would need to use `git annex get` and all files would be copied over, wasting a significant amount of space.
+
+`git-clone` has this `--local` flags which hardlinks objects in `.git/objects`, but also, maybe more interestingly, has a `--shared` option to simply tell git to look in another repo for objects. it seems to me git-annex could leverage those functionalities to avoid file duplication when using local repositories.
+
+this would be especially useful for [ikiwiki](http://ikiwiki.info/forum/ikiwiki_and_big_files).
+
+This is a [[wishlist]], but I would also welcome implementation pointers to do this myself, thanks! --[[anarcat]]
+
+> [[dup|done]]
diff --git a/doc/todo/wishlist:_use_hardlinks_for_local_clones/comment_1_85064fafe472a5bd395d60ce8f7acb56._comment b/doc/todo/wishlist:_use_hardlinks_for_local_clones/comment_1_85064fafe472a5bd395d60ce8f7acb56._comment
new file mode 100644
index 000000000..4ef5f8414
--- /dev/null
+++ b/doc/todo/wishlist:_use_hardlinks_for_local_clones/comment_1_85064fafe472a5bd395d60ce8f7acb56._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ ip="4.152.108.220"
+ subject="comment 1"
+ date="2013-09-25T17:14:28Z"
+ content="""
+git-annex uses cp --reflink=auto. So on a filesystem supporting COW file copies, like btrfs, `git annex get` will not use any disk space when getting from the same filesystem.
+
+I do not like the idea of using hardlinks, because changing the file in one repository would change it in the other, which may not be desired.
+
+[[union_mounting]] seems to cover this item pretty well, so I will close this as a duplicate.
+"""]]
diff --git a/doc/todo/wishlist_degraded_files.mdwn b/doc/todo/wishlist_degraded_files.mdwn
new file mode 100644
index 000000000..0b265c5eb
--- /dev/null
+++ b/doc/todo/wishlist_degraded_files.mdwn
@@ -0,0 +1,5 @@
+This is an idea to have a small placeholder file that is put into
+place when the file's actual content is not available in the local
+annex.
+
+Details being discussed here: <http://bugs.debian.org/728552>
diff --git a/doc/upgrades.mdwn b/doc/upgrades.mdwn
index 6cf54477c..5cf4093dc 100644
--- a/doc/upgrades.mdwn
+++ b/doc/upgrades.mdwn
@@ -18,10 +18,18 @@ conflicts first before upgrading git-annex.
## Upgrade events, so far
+### v4 -> v5 (git-annex version 5.x)
+
+v5 is only used for [[direct_mode]]. The upgrade from v4 to v5 is handled
+automatically.
+
+This upgrade involves changing direct mode repositories to operate with
+core.bare=true.
+
### v3 -> v4 (git-annex version 4.x)
-v4 is only used for [[direct_mode]], and no upgrade needs to be done from
-existing v3 repositories, they will continue to work.
+v4 was only used for [[direct_mode]], to ensure that a version of git-annex
+that understands direct mode was used with a direct mode repository.
### v2 -> v3 (git-annex version 3.x)
diff --git a/doc/upgrades/gcrypt.mdwn b/doc/upgrades/gcrypt.mdwn
new file mode 100644
index 000000000..65f80f86e
--- /dev/null
+++ b/doc/upgrades/gcrypt.mdwn
@@ -0,0 +1,25 @@
+Unfortunately the initial gcrypt repository layout had to be changed
+after git-annex version 4.20130920. If you have an encrypted git repository
+created using version 4.20130920 or 4.20130909, you need to manually
+upgrade it.
+
+If you look at the contents of your gcrypt repository, you will
+see a bare git repository, with a few three-letter subdirectories,
+which are where git-annex stores its encrypted file contents:
+
+<pre>
+27f/ branches/ description hooks/ objects/
+HEAD config f37/ info/ refs/
+</pre>
+
+In the example above, the subdirectories are `27f` and `f37`.
+
+All you need to do to transition is move those subdirectories
+into an `annex/objects` directory.
+
+ mkdir annex ; mkdir annex/objects ; mv 27f f37 annex/objects
+
+Probably those are the only 3 letter things inside your git repository,
+so this will probably work:
+
+ mkdir annex ; mkdir annex/objects ; mv ??? annex/objects
diff --git a/doc/upgrades/gcrypt/comment_1_606c1527735996ae671f78948e4ad84b._comment b/doc/upgrades/gcrypt/comment_1_606c1527735996ae671f78948e4ad84b._comment
new file mode 100644
index 000000000..8805f4a8d
--- /dev/null
+++ b/doc/upgrades/gcrypt/comment_1_606c1527735996ae671f78948e4ad84b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmj3kEGlCiy_Y-wb6AIBBnJ0B_SiPHV5Bo"
+ nickname="Thomas"
+ subject="small omission"
+ date="2013-09-25T04:59:03Z"
+ content="""
+In your second example, `mv ??? annex` has to be `mv ??? annex/objects`, I think.
+"""]]
diff --git a/doc/use_case/Bob.mdwn b/doc/use_case/Bob.mdwn
index 42d10ea97..7a90cdd11 100644
--- a/doc/use_case/Bob.mdwn
+++ b/doc/use_case/Bob.mdwn
@@ -1,7 +1,7 @@
### use case: The Archivist
-Bob has many drives to archive his data, most of them kept offline, in a
-safe place.
+Bob has many drives to archive his data, most of them
+[[kept offline|tips/offline_archive_drives]], in a safe place.
With git-annex, Bob has a single directory tree that includes all
his files, even if their content is being stored offline. He can
diff --git a/doc/users/anarcat.mdwn b/doc/users/anarcat.mdwn
new file mode 100644
index 000000000..c7054ff19
--- /dev/null
+++ b/doc/users/anarcat.mdwn
@@ -0,0 +1,41 @@
+I use git-annex to manage huge files, mostly video and audio attached to other git repositories (such as presentations), but I also use git-annex to manage my music collection across multiple devices. I also use it to manage the `ISO` images I download, podcasts, and youtube videos.
+
+See <http://anarc.at/>.
+
+[[!toc]]
+
+My tips
+=======
+
+... or the ones I commented it, to be more precise.
+
+[[!inline pages="tips/* and and link(users/anarcat) and !bugs/*/*" sort=mtime feeds=no actions=yes archive=yes show=0]]
+
+
+My todos
+========
+
+... same.
+
+[[!inline pages="todo/* and !todo/done and !link(todo/done) and
+link(users/anarcat) and !todo/*/*" sort=mtime feeds=no actions=yes archive=yes show=0]]
+
+Done
+----
+
+[[!inline pages="todo/* and !todo/done and link(todo/done) and
+link(users/anarcat) and !todo/*/*" feeds=no actions=yes archive=yes show=0]]
+
+My bugs
+=======
+
+... same.
+
+[[!inline pages="bugs/* and !bugs/done and !link(bugs/done) and
+link(users/anarcat) and !bugs/*/*" sort=mtime feeds=no actions=yes archive=yes show=0]]
+
+Fixed
+-----
+
+[[!inline pages="bugs/* and !bugs/done and link(bugs/done) and
+link(users/anarcat) and !bugs/*/*" feeds=no actions=yes archive=yes show=0]]
diff --git a/doc/users/chrysn.mdwn b/doc/users/chrysn.mdwn
index f5c07b88b..ba4261567 100644
--- a/doc/users/chrysn.mdwn
+++ b/doc/users/chrysn.mdwn
@@ -1,5 +1,11 @@
* **name**: chrysn
* **website**: <http://christian.amsuess.com/>
-* **uses git-annex for**: managing the family's photos (and possibly videos and music in the future)
-* **likes git-annex because**: it adds a layer of commit semantics over a regular file system without keeping everything in duplicate locally
-* **would like git-annex to**: not be required any more as git itself learns to use cow filesystems to avoid abundant disk usage and gets better with sparser checkouts (git-annex might then still be a simpler tool that watches over what can be safely dropped for a sparser checkout)
+* **uses git-annex for** managing the family's photos (and possibly videos and music in the future).
+* **likes git-annex because** it adds a layer of commit semantics over a regular file system without keeping everything in duplicate locally.
+* **would like git-annex not to** be required any more at all when
+ * git itself learns to use cow filesystems to avoid abundant disk usage, and
+ * git gets better with shallow clones.
+
+ git-annex might then still be a simpler tool that watches over what can be safely dropped from a particular shallow clone
+
+ (the issues with shallow clones seem to relate primarily to shallow history; i haven't read anything about what would happen if all commits were checked out, but not all trees and blobs)
diff --git a/doc/users/clacke.mdwn b/doc/users/clacke.mdwn
new file mode 100644
index 000000000..c48cd311f
--- /dev/null
+++ b/doc/users/clacke.mdwn
@@ -0,0 +1,3 @@
+Claes Wallin (韋嘉誠)
+
+[[https://microca.st/clacke]]
diff --git a/doc/users/tobiastheviking.mdwn b/doc/users/tobiastheviking.mdwn
new file mode 100644
index 000000000..0629e34a9
--- /dev/null
+++ b/doc/users/tobiastheviking.mdwn
@@ -0,0 +1,20 @@
+Tobias Ussing
+
+See:
+
+[[https://github.com/TobiasTheViking/flickrannex/]]
+
+[[https://github.com/TobiasTheViking/imapannex]]
+
+[[https://github.com/TobiasTheViking/dropboxannex]]
+
+[[https://github.com/TobiasTheViking/skydriveannex]]
+
+[[https://github.com/TobiasTheViking/googledriveannex]]
+
+[[https://github.com/TobiasTheViking/owncloudannex]]
+
+[[https://github.com/TobiasTheViking/megaannex]]
+
+[[http://git-annex.branchable.com/forum/nntp__47__usenet_special_remote/]]
+
diff --git a/doc/walkthrough/getting_file_content.mdwn b/doc/walkthrough/getting_file_content.mdwn
index f41e17770..f92704ff3 100644
--- a/doc/walkthrough/getting_file_content.mdwn
+++ b/doc/walkthrough/getting_file_content.mdwn
@@ -6,7 +6,7 @@ We can use this to copy everything in the laptop's annex to the
USB drive.
# cd /media/usb/annex
- # git fetch laptop; git merge laptop/master
+ # git annex sync laptop
# git annex get .
get my_cool_big_file (from laptop...) ok
get iso/debian.iso (from laptop...) ok
diff --git a/doc/walkthrough/syncing.mdwn b/doc/walkthrough/syncing.mdwn
index 3c43e502c..0c8d52559 100644
--- a/doc/walkthrough/syncing.mdwn
+++ b/doc/walkthrough/syncing.mdwn
@@ -1,11 +1,9 @@
-Notice that in the [[previous example|getting_file_content]], you had to
-git fetch and merge from laptop first. This lets git-annex know what has
-changed in laptop, and so it knows about the files present there and can
+Notice that in the [[previous example|getting_file_content]], `git annex
+sync` was used. This lets git-annex know what has changed in the other
+repositories like the laptop, and so it knows about the files present there and can
get them.
-If you have a lot of repositories to keep in sync, manually fetching and
-merging from them can become tedious. To automate it there is a handy
-sync command, which also even commits your changes for you.
+Let's look at what the sync command does in more detail:
# cd /media/usb/annex
# git annex sync
diff --git a/git-annex.cabal b/git-annex.cabal
index 367cdab71..9b3a66e1c 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
Name: git-annex
-Version: 4.20130802
+Version: 4.20131106
Cabal-Version: >= 1.8
License: GPL-3
Maintainer: Joey Hess <joey@kitenet.net>
@@ -68,15 +68,25 @@ Flag TDFA
Flag Feed
Description: Enable podcast feed support
+Flag Quvi
+ Description: Enable use of quvi to download videos
+
+Flag CryptoHash
+ Description: Enable use of cryptohash for checksumming
+
+Flag EKG
+ Description: Enable use of EKG to monitor git-annex as it runs (at http://localhost:4242/)
+ Default: False
+
Executable git-annex
Main-Is: git-annex.hs
Build-Depends: MissingH, hslogger, directory, filepath,
containers, utf8-string, network (>= 2.0), mtl (>= 2),
bytestring, old-locale, time, HTTP,
extensible-exceptions, dataenc, SHA, process, json,
- base (>= 4.5 && < 4.8), monad-control, MonadCatchIO-transformers,
+ base (>= 4.5 && < 4.9), monad-control, MonadCatchIO-transformers,
IfElse, text, QuickCheck >= 2.1, bloomfilter, edit-distance, process,
- SafeSemaphore, uuid, random, dlist, unix-compat
+ SafeSemaphore, uuid, random, dlist, unix-compat, async
-- Need to list these because they're generated from .hsc files.
Other-Modules: Utility.Touch Utility.Mounts
Include-Dirs: Utility
@@ -91,9 +101,7 @@ Executable git-annex
if flag(Production)
GHC-Options: -O2
- if os(windows)
- CPP-Options: -D__WINDOWS__
- else
+ if (! os(windows))
Build-Depends: unix
if flag(TestSuite)
@@ -103,6 +111,10 @@ Executable git-annex
if flag(TDFA)
Build-Depends: regex-tdfa
CPP-Options: -DWITH_TDFA
+
+ if flag(CryptoHash)
+ Build-Depends: cryptohash (>= 0.10.0)
+ CPP-Options: -DWITH_CRYPTOHASH
if flag(S3)
Build-Depends: hS3
@@ -112,14 +124,10 @@ Executable git-annex
Build-Depends: DAV (>= 0.3), http-conduit, xml-conduit, http-types
CPP-Options: -DWITH_WEBDAV
- if flag(Assistant) && ! os(windows) && ! os(solaris)
- Build-Depends: async, stm (>= 2.3)
+ if flag(Assistant) && ! os(solaris)
+ Build-Depends: stm (>= 2.3)
CPP-Options: -DWITH_ASSISTANT
- if flag(Android)
- Build-Depends: data-endian
- CPP-Options: -D__ANDROID__
-
if flag(Assistant)
if os(linux) && flag(Inotify)
Build-Depends: hinotify
@@ -129,27 +137,39 @@ Executable git-annex
Build-Depends: hfsevents
CPP-Options: -DWITH_FSEVENTS
else
- if (! os(windows) && ! os(solaris) && ! os(linux))
- CPP-Options: -DWITH_KQUEUE
- C-Sources: Utility/libkqueue.c
+ if os(windows)
+ Build-Depends: Win32-notify
+ CPP-Options: -DWITH_WIN32NOTIFY
+ else
+ if (! os(solaris) && ! os(linux))
+ if flag(Android)
+ Build-Depends: hinotify
+ CPP-Options: -DWITH_INOTIFY
+ else
+ 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 flag(Android)
+ Build-Depends: data-endian
+ CPP-Options: -D__ANDROID__
- if flag(Webapp)
+ if flag(Webapp) && (! os(windows))
Build-Depends:
yesod, yesod-default, yesod-static, yesod-form, yesod-core,
case-insensitive, http-types, transformers, wai, wai-logger, warp,
- blaze-builder, crypto-api, hamlet, clientsession, aeson,
- template-haskell, data-default
+ blaze-builder, crypto-api, hamlet, clientsession,
+ template-haskell, data-default, aeson
CPP-Options: -DWITH_WEBAPP
if flag(Pairing)
Build-Depends: network-multicast, network-info
CPP-Options: -DWITH_PAIRING
- if flag(XMPP)
+ if flag(XMPP) && (! os(windows))
Build-Depends: network-protocol-xmpp, gnutls (>= 0.1.4), xml-types
CPP-Options: -DWITH_XMPP
@@ -160,6 +180,15 @@ Executable git-annex
if flag(Feed)
Build-Depends: feed
CPP-Options: -DWITH_FEED
+
+ if flag(Quvi)
+ Build-Depends: aeson
+ CPP-Options: -DWITH_QUVI
+
+ if flag(EKG)
+ Build-Depends: ekg
+ GHC-Options: -with-rtsopts=-T
+ CPP-Options: -DWITH_EKG
source-repository head
type: git
diff --git a/git-recover-repository.hs b/git-recover-repository.hs
new file mode 100644
index 000000000..3e348f5bb
--- /dev/null
+++ b/git-recover-repository.hs
@@ -0,0 +1,42 @@
+{- git-recover-repository program
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+import System.Environment
+import qualified Data.Set as S
+import Data.Tuple.Utils
+
+import Common
+import qualified Git
+import qualified Git.CurrentRepo
+import qualified Git.Fsck
+import qualified Git.Repair
+import qualified Git.Config
+import qualified Git.Branch
+
+header :: String
+header = "Usage: git-recover-repository"
+
+usage :: a
+usage = error $ "bad parameters\n\n" ++ header
+
+parseArgs :: IO Bool
+parseArgs = do
+ args <- getArgs
+ return $ or $ map parse args
+ where
+ parse "--force" = True
+ parse _ = usage
+
+main :: IO ()
+main = do
+ forced <- parseArgs
+
+ g <- Git.Config.read =<< Git.CurrentRepo.get
+ ifM (fst3 <$> Git.Repair.runRepair forced g)
+ ( exitSuccess
+ , exitFailure
+ )
diff --git a/standalone/android/Makefile b/standalone/android/Makefile
index 39b8df054..d80d568db 100644
--- a/standalone/android/Makefile
+++ b/standalone/android/Makefile
@@ -2,22 +2,21 @@
# and builds the Android app.
# Add Android cross-compiler to PATH (as installed by ghc-android)
-# (This directory also needs to have a cc that is a symlink to the prefixed
-# gcc cross-compiler executable.)
-ANDROID_CROSS_COMPILER?=$(HOME)/.ghc/android-14/arm-linux-androideabi-4.7/bin
+ANDROID_CROSS_COMPILER?=$(HOME)/.ghc/$(shell cat abiversion)/bin
PATH:=$(ANDROID_CROSS_COMPILER):$(PATH)
# Paths to the Android SDK and NDK.
-export ANDROID_SDK_ROOT?=$(HOME)/tmp/adt-bundle-linux-x86/sdk
-export ANDROID_NDK_ROOT?=$(HOME)/tmp/android-ndk-r8d
+export ANDROID_SDK_ROOT?=$(HOME)/.android/adt-bundle-linux-x86/sdk
+export ANDROID_NDK_ROOT?=$(HOME)/.android/android-ndk
# Where to store the source tree used to build utilities. This
# directory will be created by `make source`.
-GIT_ANNEX_ANDROID_SOURCETREE?=$(HOME)/tmp/android-sourcetree
+GIT_ANNEX_ANDROID_SOURCETREE?=$(HOME)/.android/git-annex-sourcetree
GITTREE=$(GIT_ANNEX_ANDROID_SOURCETREE)/git/installed-tree
build: start
+ if [ ! -e "$(GIT_ANNEX_ANDROID_SOURCETREE)" ]; then $(MAKE) source; fi
$(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl/build-stamp
$(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh/build-stamp
$(MAKE) $(GIT_ANNEX_ANDROID_SOURCETREE)/busybox/build-stamp
@@ -32,7 +31,6 @@ build: start
# Install executables as pseudo-libraries so they will be
# unpacked from the .apk.
mkdir -p $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi
- cp ../../tmp/androidtree/dist/build/git-annex/git-annex $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so
cp $(GIT_ANNEX_ANDROID_SOURCETREE)/busybox/busybox $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.busybox.so
cp $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh/ssh $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.ssh.so
cp $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh/ssh-keygen $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.ssh-keygen.so
@@ -75,9 +73,15 @@ build: start
git rev-parse HEAD > $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.version.so
+ mkdir -p ../../tmp/4.0 ../../tmp/4.3
+
+ cp ../../tmp/androidtree/dist/build/git-annex/4.3/git-annex $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so
+ cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && ant debug
+ cp $(GIT_ANNEX_ANDROID_SOURCETREE)/term/bin/Term-debug.apk ../../tmp/4.3/git-annex.apk
+
+ cp ../../tmp/androidtree/dist/build/git-annex/4.0/git-annex $(GIT_ANNEX_ANDROID_SOURCETREE)/term/libs/armeabi/lib.git-annex.so
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && ant debug
- mkdir -p ../../tmp
- cp $(GIT_ANNEX_ANDROID_SOURCETREE)/term/bin/Term-debug.apk ../../tmp/git-annex.apk
+ cp $(GIT_ANNEX_ANDROID_SOURCETREE)/term/bin/Term-debug.apk ../../tmp/4.0/git-annex.apk
$(GIT_ANNEX_ANDROID_SOURCETREE)/openssl/build-stamp:
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl && CC=$$(which cc) ./Configure android
@@ -85,7 +89,9 @@ $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl/build-stamp:
touch $@
$(GIT_ANNEX_ANDROID_SOURCETREE)/openssh/build-stamp: openssh.patch openssh.config.h
- cd $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh && git reset --hard
+ # This is a known-good version that the patch works with.
+ # TODO: Upgrade
+ cd $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh && git reset --hard 0a8617ed5af2f0248d0e9648e26b224e16ada742
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh && ./configure --host=arm-linux-androideabi --with-ssl-dir=../openssl --without-openssl-header-check
cat openssh.patch | (cd $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh && patch -p1)
cp openssh.config.h $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh/config.h
@@ -105,21 +111,23 @@ $(GIT_ANNEX_ANDROID_SOURCETREE)/git/build-stamp:
touch $@
$(GIT_ANNEX_ANDROID_SOURCETREE)/rsync/build-stamp: rsync.patch
- cat rsync.patch | (cd $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync && git reset --hard origin/master && git am)
+ # This is a known-good version that the patch works with.
+ cat rsync.patch | (cd $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync && git reset --hard eec26089b1c7bdbb260674480ffe6ece257bca63 && git am)
cp $(GIT_ANNEX_ANDROID_SOURCETREE)/automake/lib/config.sub $(GIT_ANNEX_ANDROID_SOURCETREE)/automake/lib/config.guess $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync/
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync && ./configure --host=arm-linux-androideabi --disable-locale --disable-iconv-open --disable-iconv --disable-acl-support --disable-xattr-support
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync && $(MAKE)
touch $@
$(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg/build-stamp:
- cd $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg && git checkout gnupg-1.4.13
+ cd $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg && git checkout gnupg-1.4.15
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg && ./autogen.sh
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg && ./configure --host=arm-linux-androideabi --disable-gnupg-iconv --disable-card-support --disable-agent-support --disable-photo-viewers --disable-keyserver-helpers --disable-nls
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg; $(MAKE) || true # expected failure in doc build
touch $@
$(GIT_ANNEX_ANDROID_SOURCETREE)/term/build-stamp: term.patch icons
- cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && git reset --hard
+ # This is a known-good version that the patch works with.
+ cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && git reset --hard 3d34b3c42295c215b62e70f3ee696dd664ba08ce
cat term.patch | (cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && patch -p1)
(cd icons && tar c .) | (cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term/res && tar x)
# This renaming has a purpose. It makes the path to the app's
@@ -129,21 +137,21 @@ $(GIT_ANNEX_ANDROID_SOURCETREE)/term/build-stamp: term.patch icons
# app, if it's also installed.
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && find -name .git -prune -o -type f -print0 | xargs -0 perl -pi -e 's/jackpal/ga/g'
cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && perl -pi -e 's/Terminal Emulator/Git Annex/g' res/*/strings.xml
- cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && tools/update.sh >/dev/null 2>&1
+ cd $(GIT_ANNEX_ANDROID_SOURCETREE)/term && echo y | tools/update.sh
touch $@
source: $(GIT_ANNEX_ANDROID_SOURCETREE)
$(GIT_ANNEX_ANDROID_SOURCETREE):
mkdir -p $(GIT_ANNEX_ANDROID_SOURCETREE)
- git clone --bare git://git.savannah.gnu.org/automake.git $(GIT_ANNEX_ANDROID_SOURCETREE)/automake
- git clone --bare git://git.debian.org/git/d-i/busybox $(GIT_ANNEX_ANDROID_SOURCETREE)/busybox
- git clone --bare git://git.kernel.org/pub/scm/git/git.git $(GIT_ANNEX_ANDROID_SOURCETREE)/git
- git clone --bare git://git.samba.org/rsync.git $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync
- git clone --bare git://git.gnupg.org/gnupg.git $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg
- git clone --bare git://git.openssl.org/openssl $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl
- git clone --bare git://github.com/CyanogenMod/android_external_openssh.git $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh
- git clone --bare git://github.com/jackpal/Android-Terminal-Emulator.git $(GIT_ANNEX_ANDROID_SOURCETREE)/term
+ git clone git://git.savannah.gnu.org/automake.git $(GIT_ANNEX_ANDROID_SOURCETREE)/automake
+ git clone git://git.debian.org/git/d-i/busybox $(GIT_ANNEX_ANDROID_SOURCETREE)/busybox
+ git clone git://git.kernel.org/pub/scm/git/git.git $(GIT_ANNEX_ANDROID_SOURCETREE)/git
+ git clone git://git.samba.org/rsync.git $(GIT_ANNEX_ANDROID_SOURCETREE)/rsync
+ git clone git://git.gnupg.org/gnupg.git $(GIT_ANNEX_ANDROID_SOURCETREE)/gnupg
+ git clone git://git.openssl.org/openssl $(GIT_ANNEX_ANDROID_SOURCETREE)/openssl
+ git clone git://github.com/CyanogenMod/android_external_openssh.git $(GIT_ANNEX_ANDROID_SOURCETREE)/openssh
+ git clone git://github.com/jackpal/Android-Terminal-Emulator.git $(GIT_ANNEX_ANDROID_SOURCETREE)/term
clean:
rm -rf $(GITTREE)
diff --git a/standalone/android/abiversion b/standalone/android/abiversion
new file mode 100644
index 000000000..4cc4c14cd
--- /dev/null
+++ b/standalone/android/abiversion
@@ -0,0 +1 @@
+android-14/arm-linux-androideabi-4.8
diff --git a/standalone/android/buildchroot b/standalone/android/buildchroot
new file mode 100755
index 000000000..44337eb0c
--- /dev/null
+++ b/standalone/android/buildchroot
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -e
+if [ "$(whoami)" != root ]; then
+ echo "Must run this as root!" >&2
+ exit 1
+fi
+
+debootstrap --arch=i386 stable debian-stable-android
+cp $0-inchroot debian-stable-android/tmp
+cp $0-inchroot-asuser debian-stable-android/tmp
+cp $(dirname $0)/abiversion debian-stable-android/tmp
+
+# Don't use these vars in the chroot.
+unset TMP
+unset TEMP
+unset TMPDIR
+unset TEMPDIR
+
+chroot debian-stable-android "tmp/$(basename $0)-inchroot"
+
+echo
+echo
+echo "debian-stable-android is set up, with a user androidbuilder"
+echo "your next step is probably to check out git-annex in this chroot"
+echo "and run standalone/android/install-haskell-packages"
+echo
+echo
diff --git a/standalone/android/buildchroot-inchroot b/standalone/android/buildchroot-inchroot
new file mode 100755
index 000000000..70deea0ab
--- /dev/null
+++ b/standalone/android/buildchroot-inchroot
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Runs inside the chroot set up by buildchroot
+set -e
+if [ "$(whoami)" != root ]; then
+ echo "Must run this as root!" >&2
+ exit 1
+fi
+
+# java needs this mounted to work
+mount -t proc proc /proc
+
+echo "deb-src http://ftp.us.debian.org/debian stable main" >> /etc/apt/sources.list
+apt-get update
+apt-get -y install build-essential ghc git libncurses5-dev cabal-install
+apt-get -y install llvm-3.0 # not 3.1; buggy on arm. 3.2 is ok too
+apt-get -y install ca-certificates curl file m4 autoconf zlib1g-dev
+apt-get -y install libgnutls-dev libxml2-dev libgsasl7-dev pkg-config c2hs
+apt-get -y install ant default-jdk rsync wget gnupg lsof
+apt-get -y install gettext unzip python
+apt-get clean
+wget http://snapshot.debian.org/archive/debian/20130903T155330Z/pool/main/a/automake-1.14/automake_1.14-1_all.deb
+dpkg -i automake*.deb
+rm *.deb
+useradd androidbuilder --create-home
+su androidbuilder -c $0-asuser
diff --git a/standalone/android/buildchroot-inchroot-asuser b/standalone/android/buildchroot-inchroot-asuser
new file mode 100755
index 000000000..710e76e46
--- /dev/null
+++ b/standalone/android/buildchroot-inchroot-asuser
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Runs inside the chroot set up by buildchroot, as the user it creates
+set -e
+
+cd
+rm -rf .ghc .cabal
+cabal update
+cabal install happy alex --bindir=$HOME/bin
+PATH=$HOME/bin:$PATH
+export PATH
+mkdir -p .android
+cd .android
+git clone https://github.com/joeyh/ghc-android
+cd ghc-android
+git checkout stable-ghc-snapshot
+./build
+
+# This saves 2 gb, and the same sources are in build-*/ghc
+rm -rf stage0
+
+# Set up android SDK where the git-annex android Makefile
+# expects to find it.
+cd ..
+ln -s ghc-android/android-ndk-* android-ndk
+wget http://dl.google.com/android/adt/adt-bundle-linux-x86-20130917.zip
+unzip adt*.zip
+rm adt*.zip
+mv adt-bundle-linux-x86-* adt-bundle-linux-x86
+rm -rf adt-bundle-linux-x86/eclipse
+
+# The git-annex android Makefile needs this cc symlink.
+ln -s arm-linux-androideabi-gcc $HOME/.ghc/$(cat /tmp/abiversion)/bin/cc
+
+cd
+git clone git://git-annex.branchable.com/ git-annex
+
+git config --global user.email androidbuilder@example.com
+git config --global user.name androidbuilder
diff --git a/standalone/android/clean-haskell-packages b/standalone/android/clean-haskell-packages
new file mode 100755
index 000000000..b8c6132d6
--- /dev/null
+++ b/standalone/android/clean-haskell-packages
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Removes all currently installed cross-compiled haskell packages
+# except those part of ghc.
+# Useful if the build failed.
+rm -f $(grep -l $HOME/.ghc/$(cat abiversion)/.cabal/lib/ $HOME/.ghc/android-14/arm-linux-androideabi-4.8/lib/*-ghc-*/package.conf.d/*.conf)
+$HOME/.ghc/$(cat abiversion)/arm-linux-androideabi/bin/ghc-pkg recache
diff --git a/standalone/android/evilsplicer-headers.hs b/standalone/android/evilsplicer-headers.hs
index 35a20a001..ee4d6f1a3 100644
--- a/standalone/android/evilsplicer-headers.hs
+++ b/standalone/android/evilsplicer-headers.hs
@@ -6,6 +6,7 @@
- ** DO NOT COMMIT **
-}
import qualified Data.Monoid
+import qualified Data.Set
import qualified Data.Map
import qualified Data.Map as Data.Map.Base
import qualified Data.Foldable
@@ -16,12 +17,16 @@ import qualified Text.Hamlet
import qualified Text.Julius
import qualified Text.Css
import qualified "blaze-markup" Text.Blaze.Internal
-import qualified Yesod.Widget
+import qualified Yesod.Core.Widget
import qualified Yesod.Routes.TH.Types
import qualified Yesod.Routes.Dispatch
import qualified WaiAppStatic.Storage.Embedded
+import qualified WaiAppStatic.Storage.Embedded.Runtime
import qualified Data.FileEmbed
import qualified Data.ByteString.Internal
+import qualified Data.Text.Encoding
+import qualified Network.Wai
+import qualified Yesod.Core.Types
{- End EvilSplicer headers. -}
diff --git a/standalone/android/haskell-patches/DAV_0.3-0001-build-without-TH.patch b/standalone/android/haskell-patches/DAV_0.3-0001-build-without-TH.patch
deleted file mode 100644
index 3fbf764c2..000000000
--- a/standalone/android/haskell-patches/DAV_0.3-0001-build-without-TH.patch
+++ /dev/null
@@ -1,306 +0,0 @@
-From d195f807dac2351d29aeff00d2aee3e151eb82e3 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 18 Apr 2013 19:37:28 -0400
-Subject: [PATCH] build without TH
-
-Used the EvilSplicer to expand the TH
-
-Left off CmdArgs to save time.
----
- DAV.cabal | 20 +----
- Network/Protocol/HTTP/DAV.hs | 53 ++++++++++---
- Network/Protocol/HTTP/DAV/TH.hs | 167 ++++++++++++++++++++++++++++++++++++++-
- 3 files changed, 207 insertions(+), 33 deletions(-)
-
-diff --git a/DAV.cabal b/DAV.cabal
-index 774d4e5..8b85133 100644
---- a/DAV.cabal
-+++ b/DAV.cabal
-@@ -38,25 +38,7 @@ library
- , transformers >= 0.3
- , xml-conduit >= 1.0 && <= 1.1
- , xml-hamlet >= 0.4 && <= 0.5
--executable hdav
-- main-is: hdav.hs
-- ghc-options: -Wall
-- build-depends: base >= 4.5 && <= 5
-- , bytestring
-- , bytestring
-- , case-insensitive >= 0.4
-- , cmdargs >= 0.9
-- , containers
-- , http-conduit >= 1.4
-- , http-types >= 0.7
-- , lens >= 3.0
-- , lifted-base >= 0.1
-- , mtl >= 2.1
-- , network >= 2.3
-- , resourcet >= 0.3
-- , transformers >= 0.3
-- , xml-conduit >= 1.0 && <= 1.1
-- , xml-hamlet >= 0.4 && <= 0.5
-+ , text
-
- source-repository head
- type: git
-diff --git a/Network/Protocol/HTTP/DAV.hs b/Network/Protocol/HTTP/DAV.hs
-index 02e5d15..c0be362 100644
---- a/Network/Protocol/HTTP/DAV.hs
-+++ b/Network/Protocol/HTTP/DAV.hs
-@@ -52,7 +52,8 @@ import Network.HTTP.Types (hContentType, Method, Status, RequestHeaders, unautho
-
- import qualified Text.XML as XML
- import Text.XML.Cursor (($/), (&/), element, node, fromDocument, checkName)
--import Text.Hamlet.XML (xml)
-+import Text.Hamlet.XML
-+import qualified Data.Text
-
- import Data.CaseInsensitive (mk)
-
-@@ -246,18 +247,48 @@ makeCollection url username password = withDS url username password $
- propname :: XML.Document
- propname = XML.Document (XML.Prologue [] Nothing []) root []
- where
-- root = XML.Element "D:propfind" (Map.fromList [("xmlns:D", "DAV:")]) [xml|
--<D:allprop>
--|]
-+ root = XML.Element "D:propfind" (Map.fromList [("xmlns:D", "DAV:")]) $ concat
-+ [[XML.NodeElement
-+ (XML.Element
-+ (XML.Name
-+ (Data.Text.pack "D:allprop") Nothing Nothing)
-+ Map.empty
-+ (concat []))]]
-+
-
- locky :: XML.Document
- locky = XML.Document (XML.Prologue [] Nothing []) root []
- where
-- root = XML.Element "D:lockinfo" (Map.fromList [("xmlns:D", "DAV:")]) [xml|
--<D:lockscope>
-- <D:exclusive>
--<D:locktype>
-- <D:write>
--<D:owner>Haskell DAV user
--|]
-+ root = XML.Element "D:lockinfo" (Map.fromList [("xmlns:D", "DAV:")]) $ concat
-+ [[XML.NodeElement
-+ (XML.Element
-+ (XML.Name
-+ (Data.Text.pack "D:lockscope") Nothing Nothing)
-+ Map.empty
-+ (concat
-+ [[XML.NodeElement
-+ (XML.Element
-+ (XML.Name
-+ (Data.Text.pack "D:exclusive") Nothing Nothing)
-+ Map.empty
-+ (concat []))]]))],
-+ [XML.NodeElement
-+ (XML.Element
-+ (XML.Name
-+ (Data.Text.pack "D:locktype") Nothing Nothing)
-+ Map.empty
-+ (concat
-+ [[XML.NodeElement
-+ (XML.Element
-+ (XML.Name (Data.Text.pack "D:write") Nothing Nothing)
-+ Map.empty
-+ (concat []))]]))],
-+ [XML.NodeElement
-+ (XML.Element
-+ (XML.Name (Data.Text.pack "D:owner") Nothing Nothing)
-+ Map.empty
-+ (concat
-+ [[XML.NodeContent
-+ (Data.Text.pack "Haskell DAV user")]]))]]
-+
-
-diff --git a/Network/Protocol/HTTP/DAV/TH.hs b/Network/Protocol/HTTP/DAV/TH.hs
-index 036a2bc..4d3c0f4 100644
---- a/Network/Protocol/HTTP/DAV/TH.hs
-+++ b/Network/Protocol/HTTP/DAV/TH.hs
-@@ -16,11 +16,13 @@
- -- You should have received a copy of the GNU General Public License
- -- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
--{-# LANGUAGE TemplateHaskell #-}
-+{-# LANGUAGE RankNTypes #-}
-
- module Network.Protocol.HTTP.DAV.TH where
-
--import Control.Lens (makeLenses)
-+import Control.Lens
-+import qualified Control.Lens.Type
-+import qualified Data.Functor
- import qualified Data.ByteString as B
- import Network.HTTP.Conduit (Manager, Request)
-
-@@ -33,4 +35,163 @@ data DAVContext a = DAVContext {
- , _basicusername :: B.ByteString
- , _basicpassword :: B.ByteString
- }
--makeLenses ''DAVContext
-+allowedMethods ::
-+ forall a_a4Oo.
-+ Control.Lens.Type.Lens' (DAVContext a_a4Oo) [B.ByteString]
-+allowedMethods
-+ _f_a5tt
-+ (DAVContext __allowedMethods'_a5tu
-+ __baseRequest_a5tw
-+ __complianceClasses_a5tx
-+ __httpManager_a5ty
-+ __lockToken_a5tz
-+ __basicusername_a5tA
-+ __basicpassword_a5tB)
-+ = ((\ __allowedMethods_a5tv
-+ -> DAVContext
-+ __allowedMethods_a5tv
-+ __baseRequest_a5tw
-+ __complianceClasses_a5tx
-+ __httpManager_a5ty
-+ __lockToken_a5tz
-+ __basicusername_a5tA
-+ __basicpassword_a5tB)
-+ Data.Functor.<$> (_f_a5tt __allowedMethods'_a5tu))
-+{-# INLINE allowedMethods #-}
-+baseRequest ::
-+ forall a_a4Oo a_a5tC.
-+ Control.Lens.Type.Lens (DAVContext a_a4Oo) (DAVContext a_a5tC) (Request a_a4Oo) (Request a_a5tC)
-+baseRequest
-+ _f_a5tD
-+ (DAVContext __allowedMethods_a5tE
-+ __baseRequest'_a5tF
-+ __complianceClasses_a5tH
-+ __httpManager_a5tI
-+ __lockToken_a5tJ
-+ __basicusername_a5tK
-+ __basicpassword_a5tL)
-+ = ((\ __baseRequest_a5tG
-+ -> DAVContext
-+ __allowedMethods_a5tE
-+ __baseRequest_a5tG
-+ __complianceClasses_a5tH
-+ __httpManager_a5tI
-+ __lockToken_a5tJ
-+ __basicusername_a5tK
-+ __basicpassword_a5tL)
-+ Data.Functor.<$> (_f_a5tD __baseRequest'_a5tF))
-+{-# INLINE baseRequest #-}
-+basicpassword ::
-+ forall a_a4Oo.
-+ Control.Lens.Type.Lens' (DAVContext a_a4Oo) B.ByteString
-+basicpassword
-+ _f_a5tM
-+ (DAVContext __allowedMethods_a5tN
-+ __baseRequest_a5tO
-+ __complianceClasses_a5tP
-+ __httpManager_a5tQ
-+ __lockToken_a5tR
-+ __basicusername_a5tS
-+ __basicpassword'_a5tT)
-+ = ((\ __basicpassword_a5tU
-+ -> DAVContext
-+ __allowedMethods_a5tN
-+ __baseRequest_a5tO
-+ __complianceClasses_a5tP
-+ __httpManager_a5tQ
-+ __lockToken_a5tR
-+ __basicusername_a5tS
-+ __basicpassword_a5tU)
-+ Data.Functor.<$> (_f_a5tM __basicpassword'_a5tT))
-+{-# INLINE basicpassword #-}
-+basicusername ::
-+ forall a_a4Oo.
-+ Control.Lens.Type.Lens' (DAVContext a_a4Oo) B.ByteString
-+basicusername
-+ _f_a5tV
-+ (DAVContext __allowedMethods_a5tW
-+ __baseRequest_a5tX
-+ __complianceClasses_a5tY
-+ __httpManager_a5tZ
-+ __lockToken_a5u0
-+ __basicusername'_a5u1
-+ __basicpassword_a5u3)
-+ = ((\ __basicusername_a5u2
-+ -> DAVContext
-+ __allowedMethods_a5tW
-+ __baseRequest_a5tX
-+ __complianceClasses_a5tY
-+ __httpManager_a5tZ
-+ __lockToken_a5u0
-+ __basicusername_a5u2
-+ __basicpassword_a5u3)
-+ Data.Functor.<$> (_f_a5tV __basicusername'_a5u1))
-+{-# INLINE basicusername #-}
-+complianceClasses ::
-+ forall a_a4Oo.
-+ Control.Lens.Type.Lens' (DAVContext a_a4Oo) [B.ByteString]
-+complianceClasses
-+ _f_a5u4
-+ (DAVContext __allowedMethods_a5u5
-+ __baseRequest_a5u6
-+ __complianceClasses'_a5u7
-+ __httpManager_a5u9
-+ __lockToken_a5ua
-+ __basicusername_a5ub
-+ __basicpassword_a5uc)
-+ = ((\ __complianceClasses_a5u8
-+ -> DAVContext
-+ __allowedMethods_a5u5
-+ __baseRequest_a5u6
-+ __complianceClasses_a5u8
-+ __httpManager_a5u9
-+ __lockToken_a5ua
-+ __basicusername_a5ub
-+ __basicpassword_a5uc)
-+ Data.Functor.<$> (_f_a5u4 __complianceClasses'_a5u7))
-+{-# INLINE complianceClasses #-}
-+httpManager ::
-+ forall a_a4Oo. Control.Lens.Type.Lens' (DAVContext a_a4Oo) Manager
-+httpManager
-+ _f_a5ud
-+ (DAVContext __allowedMethods_a5ue
-+ __baseRequest_a5uf
-+ __complianceClasses_a5ug
-+ __httpManager'_a5uh
-+ __lockToken_a5uj
-+ __basicusername_a5uk
-+ __basicpassword_a5ul)
-+ = ((\ __httpManager_a5ui
-+ -> DAVContext
-+ __allowedMethods_a5ue
-+ __baseRequest_a5uf
-+ __complianceClasses_a5ug
-+ __httpManager_a5ui
-+ __lockToken_a5uj
-+ __basicusername_a5uk
-+ __basicpassword_a5ul)
-+ Data.Functor.<$> (_f_a5ud __httpManager'_a5uh))
-+{-# INLINE httpManager #-}
-+lockToken ::
-+ forall a_a4Oo.
-+ Control.Lens.Type.Lens' (DAVContext a_a4Oo) (Maybe B.ByteString)
-+lockToken
-+ _f_a5um
-+ (DAVContext __allowedMethods_a5un
-+ __baseRequest_a5uo
-+ __complianceClasses_a5up
-+ __httpManager_a5uq
-+ __lockToken'_a5ur
-+ __basicusername_a5ut
-+ __basicpassword_a5uu)
-+ = ((\ __lockToken_a5us
-+ -> DAVContext
-+ __allowedMethods_a5un
-+ __baseRequest_a5uo
-+ __complianceClasses_a5up
-+ __httpManager_a5uq
-+ __lockToken_a5us
-+ __basicusername_a5ut
-+ __basicpassword_a5uu)
-+ Data.Functor.<$> (_f_a5um __lockToken'_a5ur))
-+{-# INLINE lockToken #-}
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/DAV_build-without-TH.patch b/standalone/android/haskell-patches/DAV_build-without-TH.patch
new file mode 100644
index 000000000..b871fa9ef
--- /dev/null
+++ b/standalone/android/haskell-patches/DAV_build-without-TH.patch
@@ -0,0 +1,377 @@
+From 2b5fc33607720d0cccd7d8f9cb7232042ead73e6 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 00:36:56 +0000
+Subject: [PATCH] expand TH
+
+used the EvilSplicer
++ manual fix ups
+---
+ DAV.cabal | 20 +--
+ Network/Protocol/HTTP/DAV.hs | 73 ++++++-----
+ Network/Protocol/HTTP/DAV/TH.hs | 196 +++++++++++++++++++++++++++-
+ dist/build/HSDAV-0.4.1.o | Bin 140080 -> 0 bytes
+ dist/build/Network/Protocol/HTTP/DAV.hi | Bin 34549 -> 57657 bytes
+ dist/build/Network/Protocol/HTTP/DAV.o | Bin 160248 -> 201932 bytes
+ dist/build/Network/Protocol/HTTP/DAV/TH.hi | Bin 17056 -> 18733 bytes
+ dist/build/Network/Protocol/HTTP/DAV/TH.o | Bin 19672 -> 28120 bytes
+ dist/build/autogen/Paths_DAV.hs | 18 ++-
+ dist/build/autogen/cabal_macros.h | 45 +++----
+ dist/build/libHSDAV-0.4.1.a | Bin 200082 -> 260188 bytes
+ dist/package.conf.inplace | 2 -
+ dist/setup-config | 2 -
+ 13 files changed, 266 insertions(+), 90 deletions(-)
+ delete mode 100644 dist/build/HSDAV-0.4.1.o
+ delete mode 100644 dist/package.conf.inplace
+ delete mode 100644 dist/setup-config
+
+diff --git a/DAV.cabal b/DAV.cabal
+index 06b3a8b..90368c6 100644
+--- a/DAV.cabal
++++ b/DAV.cabal
+@@ -38,25 +38,7 @@ library
+ , transformers >= 0.3
+ , xml-conduit >= 1.0 && <= 1.2
+ , xml-hamlet >= 0.4 && <= 0.5
+-executable hdav
+- main-is: hdav.hs
+- ghc-options: -Wall
+- build-depends: base >= 4.5 && <= 5
+- , bytestring
+- , bytestring
+- , case-insensitive >= 0.4
+- , containers
+- , http-conduit >= 1.9.0
+- , http-types >= 0.7
+- , lens >= 3.0
+- , lifted-base >= 0.1
+- , mtl >= 2.1
+- , network >= 2.3
+- , optparse-applicative
+- , resourcet >= 0.3
+- , transformers >= 0.3
+- , xml-conduit >= 1.0 && <= 1.2
+- , xml-hamlet >= 0.4 && <= 0.5
++ , text
+
+ source-repository head
+ type: git
+diff --git a/Network/Protocol/HTTP/DAV.hs b/Network/Protocol/HTTP/DAV.hs
+index 8ffc270..d064a8f 100644
+--- a/Network/Protocol/HTTP/DAV.hs
++++ b/Network/Protocol/HTTP/DAV.hs
+@@ -28,12 +28,12 @@ module Network.Protocol.HTTP.DAV (
+ , deleteContent
+ , moveContent
+ , makeCollection
+- , caldavReport
+ , module Network.Protocol.HTTP.DAV.TH
+ ) where
+
+ import Network.Protocol.HTTP.DAV.TH
+
++import qualified Data.Text
+ import Control.Applicative (liftA2)
+ import Control.Exception.Lifted (catchJust, finally, bracketOnError)
+ import Control.Lens ((.~), (^.))
+@@ -200,11 +200,6 @@ props2patch = XML.renderLBS XML.def . patch . props . fromDocument
+ , "{DAV:}supportedlock"
+ ]
+
+-caldavReportM :: MonadResourceBase m => DAVState m XML.Document
+-caldavReportM = do
+- let ahs = [(hContentType, "application/xml; charset=\"utf-8\"")]
+- calrresp <- davRequest "REPORT" ahs (xmlBody calendarquery)
+- return $ (XML.parseLBS_ def . responseBody) calrresp
+
+ getProps :: String -> B.ByteString -> B.ByteString -> Maybe Depth -> IO XML.Document
+ getProps url username password md = withDS url username password md getPropsM
+@@ -246,9 +241,6 @@ moveContent :: String -> B.ByteString -> B.ByteString -> B.ByteString -> IO ()
+ moveContent url newurl username password = withDS url username password Nothing $
+ moveContentM newurl
+
+-caldavReport :: String -> B.ByteString -> B.ByteString -> IO XML.Document
+-caldavReport url username password = withDS url username password (Just Depth1) $ caldavReportM
+-
+ -- | Creates a WebDAV collection, which is similar to a directory.
+ --
+ -- Returns False if the collection could not be made due to an intermediate
+@@ -264,28 +256,45 @@ makeCollection url username password = withDS url username password Nothing $
+ propname :: XML.Document
+ propname = XML.Document (XML.Prologue [] Nothing []) root []
+ where
+- root = XML.Element "D:propfind" (Map.fromList [("xmlns:D", "DAV:")]) [xml|
+-<D:allprop>
+-|]
+-
++ root = XML.Element "D:propfind" (Map.fromList [("xmlns:D", "DAV:")]) $ concat
++ [[XML.NodeElement
++ (XML.Element
++ (XML.Name
++ (Data.Text.pack "D:allprop") Nothing Nothing)
++ Map.empty
++ (concat []))]]
+ locky :: XML.Document
+ locky = XML.Document (XML.Prologue [] Nothing []) root []
+- where
+- root = XML.Element "D:lockinfo" (Map.fromList [("xmlns:D", "DAV:")]) [xml|
+-<D:lockscope>
+- <D:exclusive>
+-<D:locktype>
+- <D:write>
+-<D:owner>Haskell DAV user
+-|]
+-
+-calendarquery :: XML.Document
+-calendarquery = XML.Document (XML.Prologue [] Nothing []) root []
+- where
+- root = XML.Element "C:calendar-query" (Map.fromList [("xmlns:D", "DAV:"),("xmlns:C", "urn:ietf:params:xml:ns:caldav")]) [xml|
+-<D:prop>
+- <D:getetag>
+- <C:calendar-data>
+-<C:filter>
+- <C:comp-filter name="VCALENDAR">
+-|]
++ where
++ root = XML.Element "D:lockinfo" (Map.fromList [("xmlns:D", "DAV:")]) $ concat
++ [[XML.NodeElement
++ (XML.Element
++ (XML.Name
++ (Data.Text.pack "D:lockscope") Nothing Nothing)
++ Map.empty
++ (concat
++ [[XML.NodeElement
++ (XML.Element
++ (XML.Name
++ (Data.Text.pack "D:exclusive") Nothing Nothing)
++ Map.empty
++ (concat []))]]))],
++ [XML.NodeElement
++ (XML.Element
++ (XML.Name
++ (Data.Text.pack "D:locktype") Nothing Nothing)
++ Map.empty
++ (concat
++ [[XML.NodeElement
++ (XML.Element
++ (XML.Name (Data.Text.pack "D:write") Nothing Nothing)
++ Map.empty
++ (concat []))]]))],
++ [XML.NodeElement
++ (XML.Element
++ (XML.Name (Data.Text.pack "D:owner") Nothing Nothing)
++ Map.empty
++ (concat
++ [[XML.NodeContent
++ (Data.Text.pack "Haskell DAV user")]]))]]
++
+diff --git a/Network/Protocol/HTTP/DAV/TH.hs b/Network/Protocol/HTTP/DAV/TH.hs
+index 9fb3495..18b8df7 100644
+--- a/Network/Protocol/HTTP/DAV/TH.hs
++++ b/Network/Protocol/HTTP/DAV/TH.hs
+@@ -20,7 +20,8 @@
+
+ module Network.Protocol.HTTP.DAV.TH where
+
+-import Control.Lens (makeLenses)
++import qualified Control.Lens.Type
++import qualified Data.Functor
+ import qualified Data.ByteString as B
+ import Network.HTTP.Conduit (Manager, Request)
+
+@@ -46,4 +47,195 @@ data DAVContext a = DAVContext {
+ , _basicpassword :: B.ByteString
+ , _depth :: Maybe Depth
+ }
+-makeLenses ''DAVContext
++allowedMethods ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) [B.ByteString]
++allowedMethods
++ _f_a5GM
++ (DAVContext __allowedMethods'_a5GN
++ __baseRequest_a5GP
++ __complianceClasses_a5GQ
++ __httpManager_a5GR
++ __lockToken_a5GS
++ __basicusername_a5GT
++ __basicpassword_a5GU
++ __depth_a5GV)
++ = ((\ __allowedMethods_a5GO
++ -> DAVContext
++ __allowedMethods_a5GO
++ __baseRequest_a5GP
++ __complianceClasses_a5GQ
++ __httpManager_a5GR
++ __lockToken_a5GS
++ __basicusername_a5GT
++ __basicpassword_a5GU
++ __depth_a5GV)
++ Data.Functor.<$> (_f_a5GM __allowedMethods'_a5GN))
++{-# INLINE allowedMethods #-}
++baseRequest ::
++ Control.Lens.Type.Lens (DAVContext a_a4I4) (DAVContext a_a5GW) (Request a_a4I4) (Request a_a5GW)
++baseRequest
++ _f_a5GX
++ (DAVContext __allowedMethods_a5GY
++ __baseRequest'_a5GZ
++ __complianceClasses_a5H1
++ __httpManager_a5H2
++ __lockToken_a5H3
++ __basicusername_a5H4
++ __basicpassword_a5H5
++ __depth_a5H6)
++ = ((\ __baseRequest_a5H0
++ -> DAVContext
++ __allowedMethods_a5GY
++ __baseRequest_a5H0
++ __complianceClasses_a5H1
++ __httpManager_a5H2
++ __lockToken_a5H3
++ __basicusername_a5H4
++ __basicpassword_a5H5
++ __depth_a5H6)
++ Data.Functor.<$> (_f_a5GX __baseRequest'_a5GZ))
++{-# INLINE baseRequest #-}
++basicpassword ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) B.ByteString
++basicpassword
++ _f_a5H7
++ (DAVContext __allowedMethods_a5H8
++ __baseRequest_a5H9
++ __complianceClasses_a5Ha
++ __httpManager_a5Hb
++ __lockToken_a5Hc
++ __basicusername_a5Hd
++ __basicpassword'_a5He
++ __depth_a5Hg)
++ = ((\ __basicpassword_a5Hf
++ -> DAVContext
++ __allowedMethods_a5H8
++ __baseRequest_a5H9
++ __complianceClasses_a5Ha
++ __httpManager_a5Hb
++ __lockToken_a5Hc
++ __basicusername_a5Hd
++ __basicpassword_a5Hf
++ __depth_a5Hg)
++ Data.Functor.<$> (_f_a5H7 __basicpassword'_a5He))
++{-# INLINE basicpassword #-}
++basicusername ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) B.ByteString
++basicusername
++ _f_a5Hh
++ (DAVContext __allowedMethods_a5Hi
++ __baseRequest_a5Hj
++ __complianceClasses_a5Hk
++ __httpManager_a5Hl
++ __lockToken_a5Hm
++ __basicusername'_a5Hn
++ __basicpassword_a5Hp
++ __depth_a5Hq)
++ = ((\ __basicusername_a5Ho
++ -> DAVContext
++ __allowedMethods_a5Hi
++ __baseRequest_a5Hj
++ __complianceClasses_a5Hk
++ __httpManager_a5Hl
++ __lockToken_a5Hm
++ __basicusername_a5Ho
++ __basicpassword_a5Hp
++ __depth_a5Hq)
++ Data.Functor.<$> (_f_a5Hh __basicusername'_a5Hn))
++{-# INLINE basicusername #-}
++complianceClasses ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) [B.ByteString]
++complianceClasses
++ _f_a5Hr
++ (DAVContext __allowedMethods_a5Hs
++ __baseRequest_a5Ht
++ __complianceClasses'_a5Hu
++ __httpManager_a5Hw
++ __lockToken_a5Hx
++ __basicusername_a5Hy
++ __basicpassword_a5Hz
++ __depth_a5HA)
++ = ((\ __complianceClasses_a5Hv
++ -> DAVContext
++ __allowedMethods_a5Hs
++ __baseRequest_a5Ht
++ __complianceClasses_a5Hv
++ __httpManager_a5Hw
++ __lockToken_a5Hx
++ __basicusername_a5Hy
++ __basicpassword_a5Hz
++ __depth_a5HA)
++ Data.Functor.<$> (_f_a5Hr __complianceClasses'_a5Hu))
++{-# INLINE complianceClasses #-}
++depth ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) (Maybe Depth)
++depth
++ _f_a5HB
++ (DAVContext __allowedMethods_a5HC
++ __baseRequest_a5HD
++ __complianceClasses_a5HE
++ __httpManager_a5HF
++ __lockToken_a5HG
++ __basicusername_a5HH
++ __basicpassword_a5HI
++ __depth'_a5HJ)
++ = ((\ __depth_a5HK
++ -> DAVContext
++ __allowedMethods_a5HC
++ __baseRequest_a5HD
++ __complianceClasses_a5HE
++ __httpManager_a5HF
++ __lockToken_a5HG
++ __basicusername_a5HH
++ __basicpassword_a5HI
++ __depth_a5HK)
++ Data.Functor.<$> (_f_a5HB __depth'_a5HJ))
++{-# INLINE depth #-}
++httpManager ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) Manager
++httpManager
++ _f_a5HL
++ (DAVContext __allowedMethods_a5HM
++ __baseRequest_a5HN
++ __complianceClasses_a5HO
++ __httpManager'_a5HP
++ __lockToken_a5HR
++ __basicusername_a5HS
++ __basicpassword_a5HT
++ __depth_a5HU)
++ = ((\ __httpManager_a5HQ
++ -> DAVContext
++ __allowedMethods_a5HM
++ __baseRequest_a5HN
++ __complianceClasses_a5HO
++ __httpManager_a5HQ
++ __lockToken_a5HR
++ __basicusername_a5HS
++ __basicpassword_a5HT
++ __depth_a5HU)
++ Data.Functor.<$> (_f_a5HL __httpManager'_a5HP))
++{-# INLINE httpManager #-}
++lockToken ::
++ Control.Lens.Type.Lens' (DAVContext a_a4I4) (Maybe B.ByteString)
++lockToken
++ _f_a5HV
++ (DAVContext __allowedMethods_a5HW
++ __baseRequest_a5HX
++ __complianceClasses_a5HY
++ __httpManager_a5HZ
++ __lockToken'_a5I0
++ __basicusername_a5I2
++ __basicpassword_a5I3
++ __depth_a5I4)
++ = ((\ __lockToken_a5I1
++ -> DAVContext
++ __allowedMethods_a5HW
++ __baseRequest_a5HX
++ __complianceClasses_a5HY
++ __httpManager_a5HZ
++ __lockToken_a5I1
++ __basicusername_a5I2
++ __basicpassword_a5I3
++ __depth_a5I4)
++ Data.Functor.<$> (_f_a5HV __lockToken'_a5I0))
++{-# INLINE lockToken #-}
diff --git a/standalone/android/haskell-patches/HTTP_4000.2.8-0001-build-with-base-4.8.patch b/standalone/android/haskell-patches/HTTP_4000.2.8-0001-build-with-base-4.8.patch
index 3114653f2..dfcdc387f 100644
--- a/standalone/android/haskell-patches/HTTP_4000.2.8-0001-build-with-base-4.8.patch
+++ b/standalone/android/haskell-patches/HTTP_4000.2.8-0001-build-with-base-4.8.patch
@@ -1,31 +1,25 @@
-From 32d0741c64e6bd280e46f7c452db9462fbac05f9 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Tue, 7 May 2013 18:21:04 -0400
-Subject: [PATCH] fix build
+From 5c57c4ae7dac0c1aa940005f5ea55fdcd4fcd1f5 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 22:46:42 +0000
+Subject: [PATCH] fix build with new base
---
- HTTP.cabal | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
+ HTTP.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HTTP.cabal b/HTTP.cabal
-index 76cb5d6..edddf26 100644
+index 76cb5d6..bb38f24 100644
--- a/HTTP.cabal
+++ b/HTTP.cabal
-@@ -85,12 +85,12 @@ Library
+@@ -85,7 +85,7 @@ Library
Network.HTTP.Utils
Paths_HTTP
GHC-options: -fwarn-missing-signatures -Wall
- Build-depends: base >= 2 && < 4.7, network < 2.5, parsec
-+ Build-depends: base >= 2 && < 4.8, network < 2.5, parsec
++ Build-depends: base >= 2 && < 4.9, network < 2.5, parsec
Extensions: FlexibleInstances
if flag(old-base)
Build-depends: base < 3
- else
-- Build-depends: base >= 3, array, old-time, bytestring
-+ Build-depends: base >= 3, array, old-time, bytestring (>= 0.10.3.0)
-
- if flag(mtl1)
- Build-depends: mtl >= 1.1 && < 1.2
--
1.7.10.4
diff --git a/standalone/android/haskell-patches/MonadCatchIO-transformers_hack-to-get-to-build-with-new-ghc.patch b/standalone/android/haskell-patches/MonadCatchIO-transformers_hack-to-get-to-build-with-new-ghc.patch
new file mode 100644
index 000000000..9881d35d6
--- /dev/null
+++ b/standalone/android/haskell-patches/MonadCatchIO-transformers_hack-to-get-to-build-with-new-ghc.patch
@@ -0,0 +1,56 @@
+From 083c9d135ec68316db173235994c63603ad76444 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 23:01:35 +0000
+Subject: [PATCH] hack to get to build with new ghc
+
+Copied the old implemenations of block and unblock from old Control.Exception
+since these deprecated functions have now been removed.
+---
+ MonadCatchIO-transformers.cabal | 2 +-
+ src/Control/Monad/CatchIO.hs | 13 +++++++++++--
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/MonadCatchIO-transformers.cabal b/MonadCatchIO-transformers.cabal
+index fe6674d..b9f559f 100644
+--- a/MonadCatchIO-transformers.cabal
++++ b/MonadCatchIO-transformers.cabal
+@@ -26,4 +26,4 @@ Library
+ Exposed-Modules:
+ Control.Monad.CatchIO
+ Hs-Source-Dirs: src
+- Ghc-options: -Wall
++ Ghc-options: -Wall -fglasgow-exts
+diff --git a/src/Control/Monad/CatchIO.hs b/src/Control/Monad/CatchIO.hs
+index 62afb83..853996b 100644
+--- a/src/Control/Monad/CatchIO.hs
++++ b/src/Control/Monad/CatchIO.hs
+@@ -19,6 +19,9 @@ where
+ import Prelude hiding ( catch )
+ import Control.Applicative ((<$>))
+ import qualified Control.Exception.Extensible as E
++import qualified Control.Exception.Base as E
++import GHC.Base (maskAsyncExceptions#)
++import GHC.IO (unsafeUnmask, IO(..))
+
+ import Control.Monad.IO.Class (MonadIO,liftIO)
+
+@@ -51,8 +54,14 @@ class MonadIO m => MonadCatchIO m where
+
+ instance MonadCatchIO IO where
+ catch = E.catch
+- block = E.block
+- unblock = E.unblock
++ block = oldblock
++ unblock = oldunblock
++
++oldblock :: IO a -> IO a
++oldblock (IO io) = IO $ maskAsyncExceptions# io
++
++oldunblock :: IO a -> IO a
++oldunblock = unsafeUnmask
+
+ -- | Warning: this instance is somewhat contentious.
+ --
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/SafeSemaphore_fix-build-with-new-base.patch b/standalone/android/haskell-patches/SafeSemaphore_fix-build-with-new-base.patch
new file mode 100644
index 000000000..a79ca519a
--- /dev/null
+++ b/standalone/android/haskell-patches/SafeSemaphore_fix-build-with-new-base.patch
@@ -0,0 +1,36 @@
+From 010db89634eb0f64e7961581e65da3acbb2b9f3d Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 22:05:41 +0000
+Subject: [PATCH] fix build with new base
+
+---
+ src/Control/Concurrent/MSampleVar.hs | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/src/Control/Concurrent/MSampleVar.hs b/src/Control/Concurrent/MSampleVar.hs
+index d029c64..16ad6c5 100644
+--- a/src/Control/Concurrent/MSampleVar.hs
++++ b/src/Control/Concurrent/MSampleVar.hs
+@@ -30,7 +30,7 @@ module Control.Concurrent.MSampleVar
+ import Control.Monad(void,join)
+ import Control.Concurrent.MVar(MVar,newMVar,newEmptyMVar,tryTakeMVar,takeMVar,putMVar,withMVar,isEmptyMVar)
+ import Control.Exception(mask_)
+-import Data.Typeable(Typeable1(typeOf1),mkTyCon,mkTyConApp)
++import Data.Typeable(mkTyConApp)
+
+ -- |
+ -- Sample variables are slightly different from a normal 'MVar':
+@@ -62,10 +62,6 @@ data MSampleVar a = MSampleVar { readQueue :: MVar ()
+ , lockedStore :: MVar (MVar a) }
+ deriving (Eq)
+
+-instance Typeable1 MSampleVar where
+- typeOf1 _ = mkTyConApp tc []
+- where tc = mkTyCon "MSampleVar"
+-
+
+ -- | 'newEmptySV' allocates a new MSampleVar in an empty state. No futher
+ -- allocation is done when using the 'MSampleVar'.
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/aeson_0.6.1.0_0001-disable-TH.patch b/standalone/android/haskell-patches/aeson_0.6.1.0_0001-disable-TH.patch
deleted file mode 100644
index 787caf45c..000000000
--- a/standalone/android/haskell-patches/aeson_0.6.1.0_0001-disable-TH.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From b220c377941d0b1271cf525a8d06bb8e48196d2b Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:29:04 -0400
-Subject: [PATCH] disable TH
-
----
- aeson.cabal | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/aeson.cabal b/aeson.cabal
-index 242aa67..275aa49 100644
---- a/aeson.cabal
-+++ b/aeson.cabal
-@@ -99,7 +99,6 @@ library
- Data.Aeson.Generic
- Data.Aeson.Parser
- Data.Aeson.Types
-- Data.Aeson.TH
-
- other-modules:
- Data.Aeson.Functions
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/async_2.0.1.4_0001-allow-building-with-unreleased-ghc.patch b/standalone/android/haskell-patches/async_fix-build-with-new-ghc.patch
index e959941b8..727720ad4 100644
--- a/standalone/android/haskell-patches/async_2.0.1.4_0001-allow-building-with-unreleased-ghc.patch
+++ b/standalone/android/haskell-patches/async_fix-build-with-new-ghc.patch
@@ -1,14 +1,14 @@
-From 55f424de9946c4d1d89837bb18698437aecfcfa4 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:29:16 -0400
-Subject: [PATCH] allow building with unreleased ghc
+From 0035f0366e426af213244b2eb25ffb63cb9e74d0 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 06:14:50 +0000
+Subject: [PATCH] fix build with new ghc
---
async.cabal | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/async.cabal b/async.cabal
-index 8e47d9d..ff317c7 100644
+index 8e47d9d..98e6312 100644
--- a/async.cabal
+++ b/async.cabal
@@ -70,7 +70,7 @@ source-repository head
@@ -16,7 +16,7 @@ index 8e47d9d..ff317c7 100644
library
exposed-modules: Control.Concurrent.Async
- build-depends: base >= 4.3 && < 4.7, stm >= 2.2 && < 2.5
-+ build-depends: base >= 4.3 && < 4.8, stm >= 2.2 && < 2.5
++ build-depends: base >= 4.3 && < 4.9, stm >= 2.2 && < 2.5
test-suite test-async
type: exitcode-stdio-1.0
diff --git a/standalone/android/haskell-patches/bloomfilter_fix-build-with-newer-base.patch b/standalone/android/haskell-patches/bloomfilter_fix-build-with-newer-base.patch
new file mode 100644
index 000000000..d2f783a7f
--- /dev/null
+++ b/standalone/android/haskell-patches/bloomfilter_fix-build-with-newer-base.patch
@@ -0,0 +1,26 @@
+From 09bcaf4f203c39c967a6951d56fd015347bb5dae Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 21:57:21 +0000
+Subject: [PATCH] fix build with newer base
+
+---
+ Data/BloomFilter/Array.hs | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Data/BloomFilter/Array.hs b/Data/BloomFilter/Array.hs
+index e085bbe..d94757a 100644
+--- a/Data/BloomFilter/Array.hs
++++ b/Data/BloomFilter/Array.hs
+@@ -3,7 +3,8 @@
+
+ module Data.BloomFilter.Array (newArray) where
+
+-import Control.Monad.ST (ST, unsafeIOToST)
++import Control.Monad.ST (ST)
++import Control.Monad.ST.Unsafe (unsafeIOToST)
+ import Data.Array.Base (MArray, STUArray(..), unsafeNewArray_)
+ #if __GLASGOW_HASKELL__ >= 704
+ import Foreign.C.Types (CInt(..), CSize(..))
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/case-insensitive_0.4.0.1_0001-allow-building-with-unreleased-ghc.patch b/standalone/android/haskell-patches/case-insensitive_0.4.0.1_0001-allow-building-with-unreleased-ghc.patch
deleted file mode 100644
index 2d7c45089..000000000
--- a/standalone/android/haskell-patches/case-insensitive_0.4.0.1_0001-allow-building-with-unreleased-ghc.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From efd0e93de82c0b5554a4f3a4517e6127f405f6da Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:29:36 -0400
-Subject: [PATCH] allow building with unreleased ghc
-
----
- case-insensitive.cabal | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/case-insensitive.cabal b/case-insensitive.cabal
-index a73479d..18a1a51 100644
---- a/case-insensitive.cabal
-+++ b/case-insensitive.cabal
-@@ -25,8 +25,8 @@ source-repository head
-
- Library
- GHC-Options: -Wall
-- build-depends: base >= 3 && < 4.6
-- , bytestring >= 0.9 && < 0.10
-+ build-depends: base >= 3 && < 4.8
-+ , bytestring >= 0.9 && < 0.15
- , text >= 0.3 && < 0.12
- , hashable >= 1.0 && < 1.2
- exposed-modules: Data.CaseInsensitive
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/certificate_1.3.7-0001-support-Android-cert-store.patch b/standalone/android/haskell-patches/certificate_1.3.7-0001-support-Android-cert-store.patch
deleted file mode 100644
index 5f772bfdf..000000000
--- a/standalone/android/haskell-patches/certificate_1.3.7-0001-support-Android-cert-store.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 3779c75175e895f94b21341ebd6361e9d6af54fd Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 9 May 2013 12:36:23 -0400
-Subject: [PATCH] support Android cert store
-
-Android puts it in a different place and has only hashed files.
-See https://github.com/vincenthz/hs-certificate/issues/19
----
- System/Certificate/X509/Unix.hs | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/System/Certificate/X509/Unix.hs b/System/Certificate/X509/Unix.hs
-index 8463465..74e9503 100644
---- a/System/Certificate/X509/Unix.hs
-+++ b/System/Certificate/X509/Unix.hs
-@@ -35,7 +35,8 @@ import qualified Control.Exception as E
- import Data.Char
-
- defaultSystemPath :: FilePath
--defaultSystemPath = "/etc/ssl/certs/"
-+defaultSystemPath = "/system/etc/security/cacerts/"
-+--defaultSystemPath = "/etc/ssl/certs/"
-
- envPathOverride :: String
- envPathOverride = "SYSTEM_CERTIFICATE_PATH"
-@@ -47,7 +48,7 @@ listDirectoryCerts path = (map (path </>) . filter isCert <$> getDirectoryConten
- && isDigit (s !! 9)
- && (s !! 8) == '.'
- && all isHexDigit (take 8 s)
-- isCert x = (not $ isPrefixOf "." x) && (not $ isHashedFile x)
-+ isCert x = (not $ isPrefixOf "." x)
-
- getSystemCertificateStore :: IO CertificateStore
- getSystemCertificateStore = makeCertificateStore . concat <$> (getSystemPath >>= listDirectoryCerts >>= mapM readCertificates)
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/cipher-aes_0.1.7-0001-fix-cross-build.patch b/standalone/android/haskell-patches/cipher-aes_0.1.7-0001-fix-cross-build.patch
deleted file mode 100644
index fab0ae6ef..000000000
--- a/standalone/android/haskell-patches/cipher-aes_0.1.7-0001-fix-cross-build.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From d456247000ab839a1d32749717f4f8f92e37dbba Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Tue, 7 May 2013 17:45:45 -0400
-Subject: [PATCH] fix cross build
-
----
- cipher-aes.cabal | 5 +----
- 1 file changed, 1 insertion(+), 4 deletions(-)
-
-diff --git a/cipher-aes.cabal b/cipher-aes.cabal
-index 02ddfd0..eb916e3 100644
---- a/cipher-aes.cabal
-+++ b/cipher-aes.cabal
-@@ -31,16 +31,13 @@ Extra-Source-Files: Tests/*.hs
-
- Library
- Build-Depends: base >= 4 && < 5
-- , bytestring
-+ , bytestring >= 0.10.3.0
- Exposed-modules: Crypto.Cipher.AES
- ghc-options: -Wall
- C-sources: cbits/aes_generic.c
- cbits/aes.c
- cbits/gf.c
- cbits/cpu.c
-- if os(linux) && (arch(i386) || arch(x86_64))
-- CC-options: -mssse3 -maes -mpclmul -DWITH_AESNI
-- C-sources: cbits/aes_x86ni.c
-
- Test-Suite test-cipher-aes
- type: exitcode-stdio-1.0
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/comonad_cross-build.patch b/standalone/android/haskell-patches/comonad_cross-build.patch
new file mode 100644
index 000000000..ee8ae4268
--- /dev/null
+++ b/standalone/android/haskell-patches/comonad_cross-build.patch
@@ -0,0 +1,25 @@
+From 589c6a87ec62e35942c9a86ea8d91b443c80da99 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Fri, 18 Oct 2013 23:07:02 +0000
+Subject: [PATCH] cross build
+
+---
+ comonad.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/comonad.cabal b/comonad.cabal
+index 5d34b13..756ed92 100644
+--- a/comonad.cabal
++++ b/comonad.cabal
+@@ -13,7 +13,7 @@ copyright: Copyright (C) 2008-2013 Edward A. Kmett,
+ Copyright (C) 2004-2008 Dave Menendez
+ synopsis: Comonads
+ description: Comonads
+-build-type: Custom
++build-type: Simple
+ extra-source-files:
+ .ghci
+ .gitignore
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/crypto-numbers_build-fix.patch b/standalone/android/haskell-patches/crypto-numbers_build-fix.patch
new file mode 100644
index 000000000..f8bdd1c39
--- /dev/null
+++ b/standalone/android/haskell-patches/crypto-numbers_build-fix.patch
@@ -0,0 +1,235 @@
+From f6ed5c3093111ffe0276f5b5bb6241783611ab1c Mon Sep 17 00:00:00 2001
+From: androidbuilder <androidbuilder@example.com>
+Date: Mon, 11 Nov 2013 01:54:25 +0000
+Subject: [PATCH] hack to build
+
+---
+ Crypto/Number/Basic.hs | 17 -----------------
+ Crypto/Number/ModArithmetic.hs | 29 -----------------------------
+ Crypto/Number/Prime.hs | 18 ------------------
+ crypto-numbers.cabal | 2 +-
+ 4 files changed, 1 insertion(+), 65 deletions(-)
+
+diff --git a/Crypto/Number/Basic.hs b/Crypto/Number/Basic.hs
+index af03052..5de8518 100644
+--- a/Crypto/Number/Basic.hs
++++ b/Crypto/Number/Basic.hs
+@@ -1,8 +1,5 @@
+ {-# LANGUAGE BangPatterns #-}
+ {-# LANGUAGE CPP #-}
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-{-# LANGUAGE UnboxedTuples #-}
+-#endif
+ -- |
+ -- Module : Crypto.Number.Basic
+ -- License : BSD-style
+@@ -17,11 +14,7 @@ module Crypto.Number.Basic
+ , areEven
+ ) where
+
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-import GHC.Integer.GMP.Internals
+-#else
+ import Data.Bits
+-#endif
+
+ -- | sqrti returns two integer (l,b) so that l <= sqrt i <= b
+ -- the implementation is quite naive, use an approximation for the first number
+@@ -60,25 +53,16 @@ sqrti i
+ -- gcde 'a' 'b' find (x,y,gcd(a,b)) where ax + by = d
+ --
+ gcde :: Integer -> Integer -> (Integer, Integer, Integer)
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-gcde a b = (s, t, g)
+- where (# g, s #) = gcdExtInteger a b
+- t = (g - s * a) `div` b
+-#else
+ gcde a b = if d < 0 then (-x,-y,-d) else (x,y,d) where
+ (d, x, y) = f (a,1,0) (b,0,1)
+ f t (0, _, _) = t
+ f (a', sa, ta) t@(b', sb, tb) =
+ let (q, r) = a' `divMod` b' in
+ f t (r, sa - (q * sb), ta - (q * tb))
+-#endif
+
+ -- | get the extended GCD of two integer using the extended binary algorithm (HAC 14.61)
+ -- get (x,y,d) where d = gcd(a,b) and x,y satisfying ax + by = d
+ gcde_binary :: Integer -> Integer -> (Integer, Integer, Integer)
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-gcde_binary = gcde
+-#else
+ gcde_binary a' b'
+ | b' == 0 = (1,0,a')
+ | a' >= b' = compute a' b'
+@@ -102,7 +86,6 @@ gcde_binary a' b'
+ in if u2 >= v2
+ then loop g x y (u2 - v2) v2 (a2 - c2) (b2 - d2) c2 d2
+ else loop g x y u2 (v2 - u2) a2 b2 (c2 - a2) (d2 - b2)
+-#endif
+
+ -- | check if a list of integer are all even
+ areEven :: [Integer] -> Bool
+diff --git a/Crypto/Number/ModArithmetic.hs b/Crypto/Number/ModArithmetic.hs
+index 031f477..38b22b7 100644
+--- a/Crypto/Number/ModArithmetic.hs
++++ b/Crypto/Number/ModArithmetic.hs
+@@ -26,12 +26,8 @@ module Crypto.Number.ModArithmetic
+ import Control.Exception (throw, Exception)
+ import Data.Typeable
+
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-import GHC.Integer.GMP.Internals
+-#else
+ import Crypto.Number.Basic (gcde_binary)
+ import Data.Bits
+-#endif
+
+ -- | Raised when two numbers are supposed to be coprimes but are not.
+ data CoprimesAssertionError = CoprimesAssertionError
+@@ -52,13 +48,7 @@ expSafe :: Integer -- ^ base
+ -> Integer -- ^ exponant
+ -> Integer -- ^ modulo
+ -> Integer -- ^ result
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-expSafe b e m
+- | odd m = powModSecInteger b e m
+- | otherwise = powModInteger b e m
+-#else
+ expSafe = exponentiation
+-#endif
+
+ -- | Compute the modular exponentiation of base^exponant using
+ -- the fastest algorithm without any consideration for
+@@ -71,11 +61,7 @@ expFast :: Integer -- ^ base
+ -> Integer -- ^ modulo
+ -> Integer -- ^ result
+ expFast =
+-#if MIN_VERSION_integer_gmp(0,5,1)
+- powModInteger
+-#else
+ exponentiation
+-#endif
+
+ -- note on exponentiation: 0^0 is treated as 1 for mimicking the standard library;
+ -- the mathematic debate is still open on whether or not this is true, but pratically
+@@ -84,22 +70,15 @@ expFast =
+ -- | exponentiation_rtl_binary computes modular exponentiation as b^e mod m
+ -- using the right-to-left binary exponentiation algorithm (HAC 14.79)
+ exponentiation_rtl_binary :: Integer -> Integer -> Integer -> Integer
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-exponentiation_rtl_binary = expSafe
+-#else
+ exponentiation_rtl_binary 0 0 m = 1 `mod` m
+ exponentiation_rtl_binary b e m = loop e b 1
+ where sq x = (x * x) `mod` m
+ loop !0 _ !a = a `mod` m
+ loop !i !s !a = loop (i `shiftR` 1) (sq s) (if odd i then a * s else a)
+-#endif
+
+ -- | exponentiation computes modular exponentiation as b^e mod m
+ -- using repetitive squaring.
+ exponentiation :: Integer -> Integer -> Integer -> Integer
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-exponentiation = expSafe
+-#else
+ exponentiation b e m
+ | b == 1 = b
+ | e == 0 = 1
+@@ -107,7 +86,6 @@ exponentiation b e m
+ | even e = let p = (exponentiation b (e `div` 2) m) `mod` m
+ in (p^(2::Integer)) `mod` m
+ | otherwise = (b * exponentiation b (e-1) m) `mod` m
+-#endif
+
+ --{-# DEPRECATED exponantiation_rtl_binary "typo in API name it's called exponentiation_rtl_binary #-}
+ exponantiation_rtl_binary :: Integer -> Integer -> Integer -> Integer
+@@ -119,17 +97,10 @@ exponantiation = exponentiation
+
+ -- | inverse computes the modular inverse as in g^(-1) mod m
+ inverse :: Integer -> Integer -> Maybe Integer
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-inverse g m
+- | r == 0 = Nothing
+- | otherwise = Just r
+- where r = recipModInteger g m
+-#else
+ inverse g m
+ | d > 1 = Nothing
+ | otherwise = Just (x `mod` m)
+ where (x,_,d) = gcde_binary g m
+-#endif
+
+ -- | Compute the modular inverse of 2 coprime numbers.
+ -- This is equivalent to inverse except that the result
+diff --git a/Crypto/Number/Prime.hs b/Crypto/Number/Prime.hs
+index 2060f4d..61d37c0 100644
+--- a/Crypto/Number/Prime.hs
++++ b/Crypto/Number/Prime.hs
+@@ -1,8 +1,6 @@
+ {-# LANGUAGE CPP #-}
+ {-# LANGUAGE BangPatterns #-}
+-#if MIN_VERSION_integer_gmp(0,5,1)
+ {-# LANGUAGE MagicHash #-}
+-#endif
+ -- |
+ -- Module : Crypto.Number.Prime
+ -- License : BSD-style
+@@ -27,12 +25,7 @@ import Crypto.Number.Generate
+ import Crypto.Number.Basic (sqrti, gcde_binary)
+ import Crypto.Number.ModArithmetic (exponantiation)
+
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-import GHC.Integer.GMP.Internals
+-import GHC.Base
+-#else
+ import Data.Bits
+-#endif
+
+ -- | returns if the number is probably prime.
+ -- first a list of small primes are implicitely tested for divisibility,
+@@ -75,21 +68,11 @@ findPrimeFromWith rng prop !n
+ -- | find a prime from a starting point with no specific property.
+ findPrimeFrom :: CPRG g => g -> Integer -> (Integer, g)
+ findPrimeFrom rng n =
+-#if MIN_VERSION_integer_gmp(0,5,1)
+- (nextPrimeInteger n, rng)
+-#else
+ findPrimeFromWith rng (\g _ -> (True, g)) n
+-#endif
+
+ -- | Miller Rabin algorithm return if the number is probably prime or composite.
+ -- the tries parameter is the number of recursion, that determines the accuracy of the test.
+ primalityTestMillerRabin :: CPRG g => g -> Int -> Integer -> (Bool, g)
+-#if MIN_VERSION_integer_gmp(0,5,1)
+-primalityTestMillerRabin rng (I# tries) !n =
+- case testPrimeInteger n tries of
+- 0# -> (False, rng)
+- _ -> (True, rng)
+-#else
+ primalityTestMillerRabin rng tries !n
+ | n <= 3 = error "Miller-Rabin requires tested value to be > 3"
+ | even n = (False, rng)
+@@ -126,7 +109,6 @@ primalityTestMillerRabin rng tries !n
+ | x2 == 1 = False
+ | x2 /= nm1 = loop' ws ((x2*x2) `mod` n) (r+1)
+ | otherwise = loop ws
+-#endif
+
+ {-
+ n < z -> witness to test
+diff --git a/crypto-numbers.cabal b/crypto-numbers.cabal
+index 05c00c1..8da5e2a 100644
+--- a/crypto-numbers.cabal
++++ b/crypto-numbers.cabal
+@@ -15,7 +15,7 @@ Extra-Source-Files: Tests/*.hs
+
+ Flag integer-gmp
+ Description: Are we using integer-gmp?
+- Default: True
++ Default: False
+
+ Library
+ Build-Depends: base >= 4 && < 5
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/distributive_0.3-0001-fixes-for-cross-build.patch b/standalone/android/haskell-patches/distributive_0.3-0001-fixes-for-cross-build.patch
index 87cdef308..4859be9a4 100644
--- a/standalone/android/haskell-patches/distributive_0.3-0001-fixes-for-cross-build.patch
+++ b/standalone/android/haskell-patches/distributive_0.3-0001-fixes-for-cross-build.patch
@@ -1,19 +1,18 @@
-From ddf49377d37c82575c1b0b712a476fa93fc00d6b Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 18 Apr 2013 17:39:28 -0400
-Subject: [PATCH] fixes for cross build
+From 6cd7b7d3a8e38ada9b1e3989770525c63f9f1d7d Mon Sep 17 00:00:00 2001
+From: androidbuilder <androidbuilder@example.com>
+Date: Fri, 18 Oct 2013 23:10:16 +0000
+Subject: [PATCH] cross build
---
- distributive.cabal | 2 +-
- src/Data/Distributive.hs | 2 --
- 2 files changed, 1 insertion(+), 3 deletions(-)
+ distributive.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/distributive.cabal b/distributive.cabal
-index 66ac73c..5204755 100644
+index 5d4ac69..82d7593 100644
--- a/distributive.cabal
+++ b/distributive.cabal
@@ -12,7 +12,7 @@ bug-reports: http://github.com/ekmett/distributive/issues
- copyright: Copyright (C) 2011 Edward A. Kmett
+ copyright: Copyright (C) 2011-2013 Edward A. Kmett
synopsis: Haskell 98 Distributive functors -- Dual to Traversable
description: Haskell 98 Distributive functors -- Dual to Traversable
-build-type: Custom
@@ -21,19 +20,6 @@ index 66ac73c..5204755 100644
extra-source-files:
.ghci
.travis.yml
-diff --git a/src/Data/Distributive.hs b/src/Data/Distributive.hs
-index 6f5613d..66eaed2 100644
---- a/src/Data/Distributive.hs
-+++ b/src/Data/Distributive.hs
-@@ -26,8 +26,6 @@ import Data.Functor.Identity
- import Data.Functor.Product
- import Data.Functor.Reverse
-
--{-# ANN module "ignore Use section" #-}
--
- -- | This is the categorical dual of 'Traversable'. However, there appears
- -- to be little benefit to allow the distribution via an arbitrary comonad
- -- so we restrict ourselves to 'Functor'.
--
-1.8.2.rc3
+1.7.10.4
diff --git a/standalone/android/haskell-patches/dns_0.3.6-0001-use-getprop-to-get-dns-server.patch b/standalone/android/haskell-patches/dns_0.3.6-0001-use-getprop-to-get-dns-server.patch
deleted file mode 100644
index 069bdd20a..000000000
--- a/standalone/android/haskell-patches/dns_0.3.6-0001-use-getprop-to-get-dns-server.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From 8459f93270c7a6e8a2ebd415db2110a66bf1ec41 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Wed, 15 May 2013 20:31:14 -0400
-Subject: [PATCH] use getprop to get dns server
-
----
- Network/DNS/Resolver.hs | 13 +++++++++++--
- dns.cabal | 4 ++++
- 2 files changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/Network/DNS/Resolver.hs b/Network/DNS/Resolver.hs
-index 70ab9ed..9b27336 100644
---- a/Network/DNS/Resolver.hs
-+++ b/Network/DNS/Resolver.hs
-@@ -41,6 +41,8 @@ import Network.Socket.ByteString.Lazy
- import Prelude hiding (lookup)
- import System.Random
- import System.Timeout
-+import System.Process (readProcess)
-+import System.Directory
-
- #if mingw32_HOST_OS == 1
- import Network.Socket (send)
-@@ -73,7 +75,7 @@ data ResolvConf = ResolvConf {
- -}
- defaultResolvConf :: ResolvConf
- defaultResolvConf = ResolvConf {
-- resolvInfo = RCFilePath "/etc/resolv.conf"
-+ resolvInfo = RCFilePath "/system/etc/resolv.conf"
- , resolvTimeout = 3 * 1000 * 1000
- , resolvBufsize = 512
- }
-@@ -111,7 +113,14 @@ makeResolvSeed conf = ResolvSeed <$> addr
- where
- addr = case resolvInfo conf of
- RCHostName numhost -> makeAddrInfo numhost
-- RCFilePath file -> toAddr <$> readFile file >>= makeAddrInfo
-+ RCFilePath file -> do
-+ exists <- doesFileExist file
-+ if exists
-+ then toAddr <$> readFile file >>= makeAddrInfo
-+ else do
-+ s <- readProcess "getprop" ["net.dns1"] ""
-+ makeAddrInfo $ takeWhile (/= '\n') s
-+
- toAddr cs = let l:_ = filter ("nameserver" `isPrefixOf`) $ lines cs
- in extract l
- extract = reverse . dropWhile isSpace . reverse . dropWhile isSpace . drop 11
-diff --git a/dns.cabal b/dns.cabal
-index 40671f6..2c19734 100644
---- a/dns.cabal
-+++ b/dns.cabal
-@@ -34,6 +34,8 @@ library
- , network >= 2.3
- , network-conduit
- , random
-+ , process
-+ , directory
- else
- Build-Depends: base >= 4 && < 5
- , attoparsec
-@@ -49,6 +51,8 @@ library
- , network-bytestring
- , network-conduit
- , random
-+ , process
-+ , directory
- Source-Repository head
- Type: git
- Location: git://github.com/kazu-yamamoto/dns.git
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/entropy_cross-build.patch b/standalone/android/haskell-patches/entropy_cross-build.patch
new file mode 100644
index 000000000..5e09fdc8f
--- /dev/null
+++ b/standalone/android/haskell-patches/entropy_cross-build.patch
@@ -0,0 +1,25 @@
+From 10da50b5eea1e615af1d3b242f422ad278c9f268 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Fri, 18 Oct 2013 23:16:41 +0000
+Subject: [PATCH] cross build
+
+---
+ entropy.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/entropy.cabal b/entropy.cabal
+index e69dec4..4fa3774 100644
+--- a/entropy.cabal
++++ b/entropy.cabal
+@@ -14,7 +14,7 @@ category: Data, Cryptography
+ homepage: https://github.com/TomMD/entropy
+ bug-reports: https://github.com/TomMD/entropy/issues
+ stability: stable
+-build-type: Custom
++build-type: Simple
+ cabal-version: >=1.10
+ tested-with: GHC == 7.6.3
+ -- data-files:
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/file-embed_0.0.4.7-0001-remove-TH-and-export-one-symbol-used-by-TH.patch b/standalone/android/haskell-patches/file-embed_0.0.4.7-0001-remove-TH-and-export-one-symbol-used-by-TH.patch
deleted file mode 100644
index ff50d3947..000000000
--- a/standalone/android/haskell-patches/file-embed_0.0.4.7-0001-remove-TH-and-export-one-symbol-used-by-TH.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-From 256ff157005f44c97fa5affe2ed9655815b3788e Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 12:38:22 -0400
-Subject: [PATCH] remove TH and export one symbol used by TH
-
----
- Data/.FileEmbed.hs.swp | Bin 16384 -> 0 bytes
- Data/FileEmbed.hs | 80 +++----------------------------------------------
- 2 files changed, 4 insertions(+), 76 deletions(-)
- delete mode 100644 Data/.FileEmbed.hs.swp
-
-diff --git a/Data/.FileEmbed.hs.swp b/Data/.FileEmbed.hs.swp
-deleted file mode 100644
-index 1b2ddbfaa71697e9df3869555aee8c97ca7ea0cb..0000000000000000000000000000000000000000
-GIT binary patch
-literal 0
-HcmV?d00001
-
-literal 16384
-zcmeHNZEPGz8J?z;l0w=5RfRyn>$8>HBX?)xk`I~qq+D`I3}?sToJzq>+`YRw-^O>l
-z*WKCLCgwvzNFb1);!i<T;wykkiv)sSh>r*%6;!D~AU?_ukSIa|0TNP$5Jm93GrM~q
-zjuRvP0NRxw-|fsh@60^&&O0;jTz%?+xp_KLykFqiFT`)B+;d-j<zDfRmkV*(lbf7;
-zt7p{>ZzZDh-@^(gRkt_UayqggyLH(tOcke!Zz&#`JZUR?@)Xi5oLp=NyHc47r3|DD
-z?1q6*wF*b~iTkJDJT;yfqgTJ`{BBC6GARQo11SS311SS311SS311SS31OG=1sNNp&
-zPxNOGa0R$6!tMCX1MiLA@sU0$11SS311SS311SS311SS311SS311SS311SUlqYT(h
-zA*RvxX$}D3{-0w2zq&_=9|B(oJ`TJeP{1ls23`y71@-_h+%3fOz|Vo70p9>V3^ahF
-zz%+0#un)Kc_}e}qegu3C_%d)6aDW-$b-)X+5aMazbHMw6w*zCq9^f|M$M{{sb>Io$
-zDsTmu2a3QOfxq4*#4mxL0AB%~0z$wCs=#SrKk&!BLOct68+a6001g9(fV+S@fnUE&
-zh$n$h0-pdb0VUu*;P-b5@f+Y7;Bnwnz!hK(r~;F~i!T-8@4!!iYruDb&jKF=LO=l}
-z;0?g*f#>cJ;yXYO7zh6R5+S|?d;oYSa0ECE>;;}ffaVv#4}hnDCxOR-j{zSATEGS1
-zUf>TH+wTKwz-8bZPyu+%$AEi)y8$7HpN>=%&@2UQZ=IZNDccep(X*R1=Uo!Qv&r|F
-z8Jcqy6-rc7zT>V&%DFV2<%^snec$sb!$18fCO`ckYgMW_*Oh*5hAw!aPtCB~-K3yr
-zHzc*~fa+4Z)bM;i>?!<IBqOxS=%3}}X(cza!urcaWv_9wd>JSs<)EY;NTk@!fF`JX
-zv>3Y3yhZ_fP_B{J(t=EaWs>r`cn*w|i$SmBsN>)V!d0{a3W`nN>yg!w?y722*IsoR
-zIjW1e6I2H&$qQI17t5PU8d6Ln`|m=;if3thDtR$n3Za#w9SzTI*ou}jEt$zvX1<oW
-z80A4Srn}>`)S~V9(`4Css&o76R4UEVgY_)e>q`~-uF1^iL|+^_<~`SLQkP~+I={=s
-zQKTEGGGiGjn24J*LHx6xfM%%a_<^B28kDZxn<tC2t4^S@%zkGHtQDyhsGJt%GIXrK
-zI+XMw-SlK|((z?OdH!Z)1LYtdxXm2dolcf}GE@ba=Q{e`fUpEnO%Tq5&Guz#GOZk~
-zit~4_h0Q@%JInQuWhu1&*kmb32M!z{>%k4fsOc5bDaxmfoNn(4&sEY@h7~A^-}^l#
-z*HdSlW)ntrY@$T4n56TGuod$b)sPe1mtjh|;#q2X16deQ?%kpd`@|>?exEx_%T}C_
-zAF|EdMR<`&z3$E|k4;n?*OJNf^GB+<h1z~sSJ2iaKa`@MWMzxlnH4tIQ+6j9%o(Yq
-z?0Fqb80}q_yfV8i%x0d;gNZ1#(_CZYjE#7Vj`w;MYRgVf`ZO^{RYz6$(-f{!qish<
-z&9<Q5OofsAsGG5k6u`Qcw`ibkTNgz=Sn?_xJ*sm{F+lM<S~%(x&JhHMXW1Ang=pZi
-zX;;#$9tJf}a-)~MsHX#eW21_dqgmt9Z92xQJ$$^`JSlrffHCs0!-1{%o~P*GLCQ{M
-zF?U&^7<XDUKew>*K;<2^xw8u^N_Kl4Tger;-!<9kSkw6<`KcV7z2los87-D+PCek^
-zLl^t`BV)Id&9Qw(oi{T8dSa_%FN!%qBdTt0YlQ+WwVi<Qr`nR%J%6q3`B(tF7G?D>
-z5TP<F3I+Vp7M<pK&i>1|9a6r;`r+!bsHn?+u{b<1RC87<BuQ=d%m^_3JSQu9B3qUp
-zx+rSABd1fVm(z~ec&t80NH-n|s#wXg+PcZ?B$!m(0jM;DCkZ1Y8BWnfIPpy;ah4{m
-zL^y*EFW6m~$uSGD2viLE2E9u6m#TqP44#6EnX*o|=lO~r4sEz%M>c7s9Hdxqiz@s(
-z&mpowdKmc5BeJu}oNw~lAK)LB{f5_+n)igwzE@B9jBNhq1`no6rCl4irbtf|X4vqp
-zUvI{*7Dx!zZ!yFAm#@QA$LdCS8sPUoVK>0m3)8&CbN$AgMgvyc3^2>}HcT%Rmc`3k
-zP7G(yoh_bs1G^>33iaor^jn_aojaRIj`m|j9_|@V2ph5h`=_K3FLA!tDZ&YN9PDji
-z1XyIT5cXS;h+xyWj!Z1PxqP(7Cwg`?yW$D>@1um>WBF*@ryYg0SS%ISYxYFEiQ)Z;
-znW(&iY<q6BbSDjrXvP$bJj@ODIeEBF8L(aG4M|>b6}dsP&eOTj4jgNnKZn#VT{r8*
-z&X#?XFyGG&*MNnFtZ4Pi^Il%AO25j@;8oca8J01^i@wvX4i&g{iw^N(!YVCZ_{ie5
-zIB%RNe<-~0>X+BPHsP{ryQ`tSDvM{#s#IJ$Q><;e%HA*@I!Ehm>Bnt#+{>VxS=BY=
-zF&#KzxYPQmQR9=wZiq~pO$3+rCXmD$p;&ojyI7Us(3D+IYBZJ+RUdm_{YsR08vSk=
-zg^`cMe#7hbcnT}0D@E69hWM^0nzj=5q~c0poT|qcPM<%1x<V%w7iqlk?%~9xXcdp>
-z(gJ+`e*))O7w26*|L5^>9q0OIfiD6d0UiM^0B;5E1O9|_{L{cS;4xqcI0Wnm{(>|7
-zmw?Xzp9a=}67W3E?$?2D0$%_Kcn$C(&g|EKEnpEi415pg^Q*w;fe!&Iz!6{^xE=T%
-z+WHLe7{KlB0_l@7kTQ@mkTQ@mkTQ@m@ZZS*MbFzpgaMiW!X4$}y6-5-8#zuowaEXY
-zO(D^Or`kBev0xM}pL2t-)p8mRLO6q=aT5mD!ELj%<qa+cej^TP^H)R_1`f_hIkhN^
-zw5~rYVcLNII*1cD8lPwdLK)W3;Rk74Rv#L%3%*2NsCpry9Pv&&D!)xG4k{VRfmYyb
-zJs1!(n|Zs1V;33}#oIYfuH*9AgetCQ@LpkJ`^|!>WS92}IBf8pMleGe4v*>U5U#dd
-z8>({f!okrwx^0Nk@8+Ii=#C-#?_Dw^w;EPm;t(zeFDmK?6|dF8x(Pv&6-7o7z1H^=
-zp6{&cwkmJVy<FA2MmHEb1$q6m6XD@QA8E7YE00EW0TI_bq#a>o6NW|1E4~>r)#MRJ
-zMs<S%zBC7Z9QQSC1tU_;QFbbuCq3#WvdOJL2+xhDgx~}mEu$Wk^qov(%qEezmx$W1
-zARZXtyuDeML&nADtV`s|bt>2LC=hGcn)&p|kwa&PDJQgEt$EO3jZUuIaqSKi^9_lz
-z9hWDvK4Heq9I<p$5b<H0AC0Nv(9@6J#<6O?9MBhJS$c?1$`2tJ({qyV`Zg=dz?jDA
-zI%FLM82bu1%(xZ5BBIDW(h77&6yq6+*+fEI<Dg6&2a2*eNY0hd>f<{sAr2sLAk_D|
-z`qc+J6D-CzXMwU2H^e;Cr|*ba{SoCH#C(s9#asr$L<aeZ%jg>#<yG9U%QsA@jlbq-
-zVmD{{!*M8LFw8#`bk_k6DC6o_$TW{HhA_3Xr+|~_=du%-O(ufrT|dkaU2AGbJCF*)
-k07GoDCUU!rsE!Us=xSj*161jGRmD&g5~lU!(k&JL0(zanmH+?%
-
-diff --git a/Data/FileEmbed.hs b/Data/FileEmbed.hs
-index 66f7004..f8c98c9 100644
---- a/Data/FileEmbed.hs
-+++ b/Data/FileEmbed.hs
-@@ -1,31 +1,15 @@
--{-# LANGUAGE TemplateHaskell #-}
- {-# LANGUAGE CPP #-}
- module Data.FileEmbed
- ( -- * Embed at compile time
-- embedFile
-- , embedDir
-- , getDir
-+ getDir
- -- * Inject into an executable
--#if MIN_VERSION_template_haskell(2,5,0)
-- , dummySpace
--#endif
- , inject
- , injectFile
-+
-+ -- used by TH (pointlessly)
-+ , stringToBs
- ) where
-
--import Language.Haskell.TH.Syntax
-- ( Exp (AppE, ListE, LitE, TupE, SigE)
--#if MIN_VERSION_template_haskell(2,5,0)
-- , Lit (StringL, StringPrimL, IntegerL)
--#else
-- , Lit (StringL, IntegerL)
--#endif
-- , Q
-- , runIO
--#if MIN_VERSION_template_haskell(2,7,0)
-- , Quasi(qAddDependentFile)
--#endif
-- )
- import System.Directory (doesDirectoryExist, doesFileExist,
- getDirectoryContents)
- import Control.Monad (filterM)
-@@ -37,51 +21,12 @@ import Data.ByteString.Unsafe (unsafePackAddressLen)
- import System.IO.Unsafe (unsafePerformIO)
- import System.FilePath ((</>))
-
---- | Embed a single file in your source code.
----
---- > import qualified Data.ByteString
---- >
---- > myFile :: Data.ByteString.ByteString
---- > myFile = $(embedFile "dirName/fileName")
--embedFile :: FilePath -> Q Exp
--embedFile fp =
--#if MIN_VERSION_template_haskell(2,7,0)
-- qAddDependentFile fp >>
--#endif
-- (runIO $ B.readFile fp) >>= bsToExp
--
---- | Embed a directory recusrively in your source code.
----
---- > import qualified Data.ByteString
---- >
---- > myDir :: [(FilePath, Data.ByteString.ByteString)]
---- > myDir = $(embedDir "dirName")
--embedDir :: FilePath -> Q Exp
--embedDir fp = do
-- typ <- [t| [(FilePath, B.ByteString)] |]
-- e <- ListE <$> ((runIO $ fileList fp) >>= mapM (pairToExp fp))
-- return $ SigE e typ
--
- -- | Get a directory tree in the IO monad.
- --
- -- This is the workhorse of 'embedDir'
- getDir :: FilePath -> IO [(FilePath, B.ByteString)]
- getDir = fileList
-
--pairToExp :: FilePath -> (FilePath, B.ByteString) -> Q Exp
--pairToExp _root (path, bs) = do
--#if MIN_VERSION_template_haskell(2,7,0)
-- qAddDependentFile $ _root ++ '/' : path
--#endif
-- exp' <- bsToExp bs
-- return $! TupE [LitE $ StringL path, exp']
--
--bsToExp :: B.ByteString -> Q Exp
--bsToExp bs = do
-- helper <- [| stringToBs |]
-- let chars = B8.unpack bs
-- return $! AppE helper $! LitE $! StringL chars
--
- stringToBs :: String -> B.ByteString
- stringToBs = B8.pack
-
-@@ -123,23 +68,6 @@ padSize i =
- let s = show i
- in replicate (sizeLen - length s) '0' ++ s
-
--#if MIN_VERSION_template_haskell(2,5,0)
--dummySpace :: Int -> Q Exp
--dummySpace space = do
-- let size = padSize space
-- let start = magic ++ size
-- let chars = LitE $ StringPrimL $
--#if MIN_VERSION_template_haskell(2,6,0)
-- map (toEnum . fromEnum) $
--#endif
-- start ++ replicate space '0'
-- let len = LitE $ IntegerL $ fromIntegral $ length start + space
-- upi <- [|unsafePerformIO|]
-- pack <- [|unsafePackAddressLen|]
-- getInner' <- [|getInner|]
-- return $ getInner' `AppE` (upi `AppE` (pack `AppE` len `AppE` chars))
--#endif
--
- inject :: B.ByteString -- ^ bs to inject
- -> B.ByteString -- ^ original BS containing dummy
- -> Maybe B.ByteString -- ^ new BS, or Nothing if there is insufficient dummy space
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/gnuidn_fix-build-with-new-base.patch b/standalone/android/haskell-patches/gnuidn_fix-build-with-new-base.patch
new file mode 100644
index 000000000..ff9d8f245
--- /dev/null
+++ b/standalone/android/haskell-patches/gnuidn_fix-build-with-new-base.patch
@@ -0,0 +1,50 @@
+From afdec6c9e66211a0ac8419fffe191b059d1fd00c Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 17:24:33 +0000
+Subject: [PATCH] fix build with new base
+
+---
+ Data/Text/IDN/IDNA.chs | 1 +
+ Data/Text/IDN/Punycode.chs | 1 +
+ Data/Text/IDN/StringPrep.chs | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/Data/Text/IDN/IDNA.chs b/Data/Text/IDN/IDNA.chs
+index ed29ee4..dbb4ba5 100644
+--- a/Data/Text/IDN/IDNA.chs
++++ b/Data/Text/IDN/IDNA.chs
+@@ -31,6 +31,7 @@ import Foreign
+ import Foreign.C
+
+ import Data.Text.IDN.Internal
++import System.IO.Unsafe
+
+ #include <idna.h>
+ #include <idn-free.h>
+diff --git a/Data/Text/IDN/Punycode.chs b/Data/Text/IDN/Punycode.chs
+index 24b5fa6..4e62555 100644
+--- a/Data/Text/IDN/Punycode.chs
++++ b/Data/Text/IDN/Punycode.chs
+@@ -32,6 +32,7 @@ import Data.List (unfoldr)
+ import qualified Data.ByteString as B
+ import qualified Data.Text as T
+
++import System.IO.Unsafe
+ import Foreign
+ import Foreign.C
+
+diff --git a/Data/Text/IDN/StringPrep.chs b/Data/Text/IDN/StringPrep.chs
+index 752dc9e..5e9fd84 100644
+--- a/Data/Text/IDN/StringPrep.chs
++++ b/Data/Text/IDN/StringPrep.chs
+@@ -39,6 +39,7 @@ import qualified Data.ByteString as B
+ import qualified Data.Text as T
+ import qualified Data.Text.Encoding as TE
+
++import System.IO.Unsafe
+ import Foreign
+ import Foreign.C
+
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/hS3_0.5.7_0001-fix-build.patch b/standalone/android/haskell-patches/hS3_0.5.7_0001-fix-build.patch
deleted file mode 100644
index c0158c0f4..000000000
--- a/standalone/android/haskell-patches/hS3_0.5.7_0001-fix-build.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 643b3c9fd95967c5911107f46498cd851e68f97d Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Tue, 7 May 2013 18:26:33 -0400
-Subject: [PATCH] fix build
-
----
- hS3.cabal | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/hS3.cabal b/hS3.cabal
-index 35f7496..e04bf65 100644
---- a/hS3.cabal
-+++ b/hS3.cabal
-@@ -44,6 +44,3 @@ Library
- Network.AWS.AWSConnection,
- Network.AWS.Authentication,
- Network.AWS.ArrowUtils
--
--Executable hs3
-- main-is: hS3.hs
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/hamlet_1.1.6.1_0001-remove-TH.patch b/standalone/android/haskell-patches/hamlet_1.1.6.1_0001-remove-TH.patch
deleted file mode 100644
index 1c511a132..000000000
--- a/standalone/android/haskell-patches/hamlet_1.1.6.1_0001-remove-TH.patch
+++ /dev/null
@@ -1,294 +0,0 @@
-From b2c677ed39f1aca3a1111691ba51b26f7fd414a4 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Wed, 8 May 2013 01:50:58 -0400
-Subject: [PATCH] remove TH
-
----
- Text/Hamlet.hs | 219 ++------------------------------------------------------
- hamlet.cabal | 2 +-
- 2 files changed, 7 insertions(+), 214 deletions(-)
-
-diff --git a/Text/Hamlet.hs b/Text/Hamlet.hs
-index 4ac870a..63b8555 100644
---- a/Text/Hamlet.hs
-+++ b/Text/Hamlet.hs
-@@ -11,35 +11,26 @@
- module Text.Hamlet
- ( -- * Plain HTML
- Html
-- , shamlet
-- , shamletFile
-- , xshamlet
-- , xshamletFile
- -- * Hamlet
- , HtmlUrl
-- , hamlet
-- , hamletFile
-- , xhamlet
-- , xhamletFile
- -- * I18N Hamlet
- , HtmlUrlI18n
-- , ihamlet
-- , ihamletFile
- -- * Type classes
- , ToAttributes (..)
- -- * Internal, for making more
- , HamletSettings (..)
- , NewlineStyle (..)
-- , hamletWithSettings
-- , hamletFileWithSettings
- , defaultHamletSettings
- , xhtmlHamletSettings
- , Env (..)
- , HamletRules (..)
-- , hamletRules
-- , ihamletRules
-- , htmlRules
- , CloseStyle (..)
-+ , condH
-+ , maybeH
-+
-+ -- referred to in TH splices
-+ , attrsToHtml
-+ , asHtmlUrl
- ) where
-
- import Text.Shakespeare.Base
-@@ -90,14 +81,6 @@ type HtmlUrl url = Render url -> Html
- -- | A function generating an 'Html' given a message translator and a URL rendering function.
- type HtmlUrlI18n msg url = Translate msg -> Render url -> Html
-
--docsToExp :: Env -> HamletRules -> Scope -> [Doc] -> Q Exp
--docsToExp env hr scope docs = do
-- exps <- mapM (docToExp env hr scope) docs
-- case exps of
-- [] -> [|return ()|]
-- [x] -> return x
-- _ -> return $ DoE $ map NoBindS exps
--
- unIdent :: Ident -> String
- unIdent (Ident s) = s
-
-@@ -159,169 +142,9 @@ recordToFieldNames conStr = do
- [fields] <- return [fields | RecC name fields <- cons, name == conName]
- return [fieldName | (fieldName, _, _) <- fields]
-
--docToExp :: Env -> HamletRules -> Scope -> Doc -> Q Exp
--docToExp env hr scope (DocForall list idents inside) = do
-- let list' = derefToExp scope list
-- (pat, extraScope) <- bindingPattern idents
-- let scope' = extraScope ++ scope
-- mh <- [|F.mapM_|]
-- inside' <- docsToExp env hr scope' inside
-- let lam = LamE [pat] inside'
-- return $ mh `AppE` lam `AppE` list'
--docToExp env hr scope (DocWith [] inside) = do
-- inside' <- docsToExp env hr scope inside
-- return $ inside'
--docToExp env hr scope (DocWith ((deref, idents):dis) inside) = do
-- let deref' = derefToExp scope deref
-- (pat, extraScope) <- bindingPattern idents
-- let scope' = extraScope ++ scope
-- inside' <- docToExp env hr scope' (DocWith dis inside)
-- let lam = LamE [pat] inside'
-- return $ lam `AppE` deref'
--docToExp env hr scope (DocMaybe val idents inside mno) = do
-- let val' = derefToExp scope val
-- (pat, extraScope) <- bindingPattern idents
-- let scope' = extraScope ++ scope
-- inside' <- docsToExp env hr scope' inside
-- let inside'' = LamE [pat] inside'
-- ninside' <- case mno of
-- Nothing -> [|Nothing|]
-- Just no -> do
-- no' <- docsToExp env hr scope no
-- j <- [|Just|]
-- return $ j `AppE` no'
-- mh <- [|maybeH|]
-- return $ mh `AppE` val' `AppE` inside'' `AppE` ninside'
--docToExp env hr scope (DocCond conds final) = do
-- conds' <- mapM go conds
-- final' <- case final of
-- Nothing -> [|Nothing|]
-- Just f -> do
-- f' <- docsToExp env hr scope f
-- j <- [|Just|]
-- return $ j `AppE` f'
-- ch <- [|condH|]
-- return $ ch `AppE` ListE conds' `AppE` final'
-- where
-- go :: (Deref, [Doc]) -> Q Exp
-- go (d, docs) = do
-- let d' = derefToExp scope d
-- docs' <- docsToExp env hr scope docs
-- return $ TupE [d', docs']
--docToExp env hr scope (DocCase deref cases) = do
-- let exp_ = derefToExp scope deref
-- matches <- mapM toMatch cases
-- return $ CaseE exp_ matches
-- where
-- readMay s =
-- case reads s of
-- (x, ""):_ -> Just x
-- _ -> Nothing
-- toMatch (idents, inside) = do
-- let pat = case map unIdent idents of
-- ["_"] -> WildP
-- [str]
-- | Just i <- readMay str -> LitP $ IntegerL i
-- strs -> let (constr:fields) = map mkName strs
-- in ConP constr (map VarP fields)
-- insideExp <- docsToExp env hr scope inside
-- return $ Match pat (NormalB insideExp) []
--docToExp env hr v (DocContent c) = contentToExp env hr v c
--
--contentToExp :: Env -> HamletRules -> Scope -> Content -> Q Exp
--contentToExp _ hr _ (ContentRaw s) = do
-- os <- [|preEscapedText . pack|]
-- let s' = LitE $ StringL s
-- return $ hrFromHtml hr `AppE` (os `AppE` s')
--contentToExp _ hr scope (ContentVar d) = do
-- str <- [|toHtml|]
-- return $ hrFromHtml hr `AppE` (str `AppE` derefToExp scope d)
--contentToExp env hr scope (ContentUrl hasParams d) =
-- case urlRender env of
-- Nothing -> error "URL interpolation used, but no URL renderer provided"
-- Just wrender -> wrender $ \render -> do
-- let render' = return render
-- ou <- if hasParams
-- then [|\(u, p) -> $(render') u p|]
-- else [|\u -> $(render') u []|]
-- let d' = derefToExp scope d
-- pet <- [|toHtml|]
-- return $ hrFromHtml hr `AppE` (pet `AppE` (ou `AppE` d'))
--contentToExp env hr scope (ContentEmbed d) = hrEmbed hr env $ derefToExp scope d
--contentToExp env hr scope (ContentMsg d) =
-- case msgRender env of
-- Nothing -> error "Message interpolation used, but no message renderer provided"
-- Just wrender -> wrender $ \render ->
-- return $ hrFromHtml hr `AppE` (render `AppE` derefToExp scope d)
--contentToExp _ hr scope (ContentAttrs d) = do
-- html <- [|attrsToHtml . toAttributes|]
-- return $ hrFromHtml hr `AppE` (html `AppE` derefToExp scope d)
--
--shamlet :: QuasiQuoter
--shamlet = hamletWithSettings htmlRules defaultHamletSettings
--
--xshamlet :: QuasiQuoter
--xshamlet = hamletWithSettings htmlRules xhtmlHamletSettings
--
--htmlRules :: Q HamletRules
--htmlRules = do
-- i <- [|id|]
-- return $ HamletRules i ($ (Env Nothing Nothing)) (\_ b -> return b)
--
--hamlet :: QuasiQuoter
--hamlet = hamletWithSettings hamletRules defaultHamletSettings
--
--xhamlet :: QuasiQuoter
--xhamlet = hamletWithSettings hamletRules xhtmlHamletSettings
--
- asHtmlUrl :: HtmlUrl url -> HtmlUrl url
- asHtmlUrl = id
-
--hamletRules :: Q HamletRules
--hamletRules = do
-- i <- [|id|]
-- let ur f = do
-- r <- newName "_render"
-- let env = Env
-- { urlRender = Just ($ (VarE r))
-- , msgRender = Nothing
-- }
-- h <- f env
-- return $ LamE [VarP r] h
-- return $ HamletRules i ur em
-- where
-- em (Env (Just urender) Nothing) e = do
-- asHtmlUrl' <- [|asHtmlUrl|]
-- urender $ \ur' -> return ((asHtmlUrl' `AppE` e) `AppE` ur')
-- em _ _ = error "bad Env"
--
--ihamlet :: QuasiQuoter
--ihamlet = hamletWithSettings ihamletRules defaultHamletSettings
--
--ihamletRules :: Q HamletRules
--ihamletRules = do
-- i <- [|id|]
-- let ur f = do
-- u <- newName "_urender"
-- m <- newName "_mrender"
-- let env = Env
-- { urlRender = Just ($ (VarE u))
-- , msgRender = Just ($ (VarE m))
-- }
-- h <- f env
-- return $ LamE [VarP m, VarP u] h
-- return $ HamletRules i ur em
-- where
-- em (Env (Just urender) (Just mrender)) e =
-- urender $ \ur' -> mrender $ \mr -> return (e `AppE` mr `AppE` ur')
-- em _ _ = error "bad Env"
--
--hamletWithSettings :: Q HamletRules -> HamletSettings -> QuasiQuoter
--hamletWithSettings hr set =
-- QuasiQuoter
-- { quoteExp = hamletFromString hr set
-- }
--
- data HamletRules = HamletRules
- { hrFromHtml :: Exp
- , hrWithEnv :: (Env -> Q Exp) -> Q Exp
-@@ -333,36 +156,6 @@ data Env = Env
- , msgRender :: Maybe ((Exp -> Q Exp) -> Q Exp)
- }
-
--hamletFromString :: Q HamletRules -> HamletSettings -> String -> Q Exp
--hamletFromString qhr set s = do
-- hr <- qhr
-- case parseDoc set s of
-- Error s' -> error s'
-- Ok (_mnl, d) -> hrWithEnv hr $ \env -> docsToExp env hr [] d
--
--hamletFileWithSettings :: Q HamletRules -> HamletSettings -> FilePath -> Q Exp
--hamletFileWithSettings qhr set fp = do
--#ifdef GHC_7_4
-- qAddDependentFile fp
--#endif
-- contents <- fmap TL.unpack $ qRunIO $ readUtf8File fp
-- hamletFromString qhr set contents
--
--hamletFile :: FilePath -> Q Exp
--hamletFile = hamletFileWithSettings hamletRules defaultHamletSettings
--
--xhamletFile :: FilePath -> Q Exp
--xhamletFile = hamletFileWithSettings hamletRules xhtmlHamletSettings
--
--shamletFile :: FilePath -> Q Exp
--shamletFile = hamletFileWithSettings htmlRules defaultHamletSettings
--
--xshamletFile :: FilePath -> Q Exp
--xshamletFile = hamletFileWithSettings htmlRules xhtmlHamletSettings
--
--ihamletFile :: FilePath -> Q Exp
--ihamletFile = hamletFileWithSettings ihamletRules defaultHamletSettings
--
- varName :: Scope -> String -> Exp
- varName _ "" = error "Illegal empty varName"
- varName scope v@(_:_) = fromMaybe (strToExp v) $ lookup (Ident v) scope
-diff --git a/hamlet.cabal b/hamlet.cabal
-index 73fa6a8..4348508 100644
---- a/hamlet.cabal
-+++ b/hamlet.cabal
-@@ -50,7 +50,7 @@ library
- , text >= 0.7 && < 0.12
- , containers >= 0.2
- , blaze-builder >= 0.2 && < 0.4
-- , process >= 1.0 && < 1.2
-+ , process >= 1.0 && < 1.3
- , blaze-html >= 0.5 && < 0.6
- , blaze-markup >= 0.5.1 && < 0.6
-
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/language-javascript_fix-build-with-new-ghc.patch b/standalone/android/haskell-patches/language-javascript_fix-build-with-new-ghc.patch
new file mode 100644
index 000000000..6182cba44
--- /dev/null
+++ b/standalone/android/haskell-patches/language-javascript_fix-build-with-new-ghc.patch
@@ -0,0 +1,25 @@
+From cb5252db1a0d515da69d9167a8b2facd839940b2 Mon Sep 17 00:00:00 2001
+From: androidbuilder <androidbuilder@example.com>
+Date: Mon, 11 Nov 2013 02:29:06 +0000
+Subject: [PATCH] fix build with new ghc
+
+---
+ src/Language/JavaScript/Parser/Lexer.hs | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/Language/JavaScript/Parser/Lexer.hs b/src/Language/JavaScript/Parser/Lexer.hs
+index 79fa9c5..fa96e29 100644
+--- a/src/Language/JavaScript/Parser/Lexer.hs
++++ b/src/Language/JavaScript/Parser/Lexer.hs
+@@ -712,7 +712,7 @@ alex_scan_tkn user orig_input len input s last_acc =
+ (offset) = (base +# ord_c)
+ (check) = alexIndexInt16OffAddr alex_check offset
+
+- (new_s) = if (offset >=# 0#) && (check ==# ord_c)
++ (new_s) = if (tagToEnum# (offset >=# 0#)) && (tagToEnum# (check ==# ord_c))
+ then alexIndexInt16OffAddr alex_table offset
+ else alexIndexInt16OffAddr alex_deflt s
+ in
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/lens_3.8.5-0001-build-without-TH.patch b/standalone/android/haskell-patches/lens_various-hacking-to-cross-build.patch
index 62efccc32..274efc71e 100644
--- a/standalone/android/haskell-patches/lens_3.8.5-0001-build-without-TH.patch
+++ b/standalone/android/haskell-patches/lens_various-hacking-to-cross-build.patch
@@ -1,27 +1,30 @@
-From bbb49942123f06a36b170966e445692297f71d26 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 18 Apr 2013 19:14:30 -0400
-Subject: [PATCH] build without TH
+From 41706061810410cc38f602ccc9a4c9560502251f Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Sat, 19 Oct 2013 01:44:52 +0000
+Subject: [PATCH] hackity
---
- lens.cabal | 13 +------------
- src/Control/Exception/Lens.hs | 2 +-
- src/Control/Lens.hs | 6 +++---
- src/Control/Lens/Equality.hs | 4 ++--
- src/Control/Lens/Fold.hs | 6 +++---
- src/Control/Lens/Internal.hs | 2 +-
- src/Control/Lens/Internal/Zipper.hs | 2 +-
- src/Control/Lens/Iso.hs | 2 --
- src/Control/Lens/Lens.hs | 2 +-
- src/Control/Lens/Operators.hs | 2 +-
- src/Control/Lens/Plated.hs | 2 +-
- src/Control/Lens/Setter.hs | 2 --
- src/Control/Lens/TH.hs | 2 +-
- src/Data/Data/Lens.hs | 6 +++---
- 14 files changed, 19 insertions(+), 34 deletions(-)
+ lens.cabal | 12 +-----------
+ src/Control/Exception/Lens.hs | 2 +-
+ src/Control/Lens.hs | 6 +++---
+ src/Control/Lens/Equality.hs | 4 ++--
+ src/Control/Lens/Fold.hs | 6 +++---
+ src/Control/Lens/Internal.hs | 2 +-
+ src/Control/Lens/Internal/Exception.hs | 26 +-------------------------
+ src/Control/Lens/Internal/Instances.hs | 14 --------------
+ src/Control/Lens/Internal/Zipper.hs | 2 +-
+ src/Control/Lens/Iso.hs | 2 --
+ src/Control/Lens/Lens.hs | 2 +-
+ src/Control/Lens/Operators.hs | 2 +-
+ src/Control/Lens/Plated.hs | 2 +-
+ src/Control/Lens/Prism.hs | 2 --
+ src/Control/Lens/Setter.hs | 2 --
+ src/Control/Lens/TH.hs | 2 +-
+ src/Data/Data/Lens.hs | 6 +++---
+ 17 files changed, 20 insertions(+), 74 deletions(-)
diff --git a/lens.cabal b/lens.cabal
-index a06b3ce..a654b3d 100644
+index b25adf4..3e5c30c 100644
--- a/lens.cabal
+++ b/lens.cabal
@@ -10,7 +10,7 @@ stability: provisional
@@ -30,18 +33,10 @@ index a06b3ce..a654b3d 100644
copyright: Copyright (C) 2012-2013 Edward A. Kmett
-build-type: Custom
+build-type: Simple
- tested-with: GHC == 7.0.4, GHC == 7.4.1, GHC == 7.4.2, GHC == 7.6.1, GHC == 7.7.20121213, GHC == 7.7.20130117
+ tested-with: GHC == 7.6.3
synopsis: Lenses, Folds and Traversals
description:
-@@ -171,7 +171,6 @@ library
- containers >= 0.4.0 && < 0.6,
- distributive >= 0.3 && < 1,
- filepath >= 1.2.0.0 && < 1.4,
-- generic-deriving == 1.4.*,
- ghc-prim,
- hashable >= 1.1.2.3 && < 1.3,
- MonadCatchIO-transformers >= 0.3 && < 0.4,
-@@ -233,14 +232,12 @@ library
+@@ -235,14 +235,12 @@ library
Control.Lens.Review
Control.Lens.Setter
Control.Lens.Simple
@@ -56,7 +51,7 @@ index a06b3ce..a654b3d 100644
Control.Parallel.Strategies.Lens
Control.Seq.Lens
Data.Array.Lens
-@@ -264,12 +261,8 @@ library
+@@ -266,12 +264,8 @@ library
Data.Typeable.Lens
Data.Vector.Lens
Data.Vector.Generic.Lens
@@ -69,7 +64,7 @@ index a06b3ce..a654b3d 100644
Numeric.Lens
if flag(safe)
-@@ -368,7 +361,6 @@ test-suite doctests
+@@ -370,7 +364,6 @@ test-suite doctests
deepseq,
doctest >= 0.9.1,
filepath,
@@ -77,7 +72,7 @@ index a06b3ce..a654b3d 100644
mtl,
nats,
parallel,
-@@ -394,7 +386,6 @@ benchmark plated
+@@ -396,7 +389,6 @@ benchmark plated
comonad,
criterion,
deepseq,
@@ -85,7 +80,7 @@ index a06b3ce..a654b3d 100644
lens,
transformers
-@@ -429,7 +420,6 @@ benchmark unsafe
+@@ -431,7 +423,6 @@ benchmark unsafe
comonads-fd,
criterion,
deepseq,
@@ -93,7 +88,7 @@ index a06b3ce..a654b3d 100644
lens,
transformers
-@@ -446,6 +436,5 @@ benchmark zipper
+@@ -448,6 +439,5 @@ benchmark zipper
comonads-fd,
criterion,
deepseq,
@@ -101,7 +96,7 @@ index a06b3ce..a654b3d 100644
lens,
transformers
diff --git a/src/Control/Exception/Lens.hs b/src/Control/Exception/Lens.hs
-index 5c26d4e..9909132 100644
+index 0619335..c97ad9b 100644
--- a/src/Control/Exception/Lens.hs
+++ b/src/Control/Exception/Lens.hs
@@ -112,7 +112,7 @@ import Prelude
@@ -114,7 +109,7 @@ index 5c26d4e..9909132 100644
-- $setup
-- >>> :set -XNoOverloadedStrings
diff --git a/src/Control/Lens.hs b/src/Control/Lens.hs
-index 8481e44..74700ae 100644
+index 242c3c1..2ab9cdb 100644
--- a/src/Control/Lens.hs
+++ b/src/Control/Lens.hs
@@ -59,7 +59,7 @@ module Control.Lens
@@ -157,10 +152,10 @@ index 982c2d7..3a3fe1a 100644
-- $setup
-- >>> import Control.Lens
diff --git a/src/Control/Lens/Fold.hs b/src/Control/Lens/Fold.hs
-index ae5100d..467eb37 100644
+index 32a4073..cc7da1e 100644
--- a/src/Control/Lens/Fold.hs
+++ b/src/Control/Lens/Fold.hs
-@@ -161,9 +161,9 @@ import Data.Traversable
+@@ -163,9 +163,9 @@ import Data.Traversable
-- >>> let g :: Expr -> Expr; g = Debug.SimpleReflect.Vars.g
-- >>> let timingOut :: NFData a => a -> IO a; timingOut = fmap (fromMaybe (error "timeout")) . timeout (5*10^6) . evaluate . force
@@ -183,6 +178,90 @@ index 295662e..539642d 100644
-{-# ANN module "HLint: ignore Use import/export shortcut" #-}
+
+diff --git a/src/Control/Lens/Internal/Exception.hs b/src/Control/Lens/Internal/Exception.hs
+index 387203e..8bea89b 100644
+--- a/src/Control/Lens/Internal/Exception.hs
++++ b/src/Control/Lens/Internal/Exception.hs
+@@ -36,6 +36,7 @@ import Data.Monoid
+ import Data.Proxy
+ import Data.Reflection
+ import Data.Typeable
++import Data.Typeable
+ import System.IO.Unsafe
+
+ ------------------------------------------------------------------------------
+@@ -128,18 +129,6 @@ class Handleable e (m :: * -> *) (h :: * -> *) | h -> e m where
+ handler_ l = handler l . const
+ {-# INLINE handler_ #-}
+
+-instance Handleable SomeException IO Exception.Handler where
+- handler = handlerIO
+-
+-instance Handleable SomeException m (CatchIO.Handler m) where
+- handler = handlerCatchIO
+-
+-handlerIO :: forall a r. Getting (First a) SomeException a -> (a -> IO r) -> Exception.Handler r
+-handlerIO l f = reify (preview l) $ \ (_ :: Proxy s) -> Exception.Handler (\(Handling a :: Handling a s IO) -> f a)
+-
+-handlerCatchIO :: forall m a r. Getting (First a) SomeException a -> (a -> m r) -> CatchIO.Handler m r
+-handlerCatchIO l f = reify (preview l) $ \ (_ :: Proxy s) -> CatchIO.Handler (\(Handling a :: Handling a s m) -> f a)
+-
+ ------------------------------------------------------------------------------
+ -- Helpers
+ ------------------------------------------------------------------------------
+@@ -159,21 +148,8 @@ supply = unsafePerformIO $ newIORef 0
+ -- | This permits the construction of an \"impossible\" 'Control.Exception.Handler' that matches only if some function does.
+ newtype Handling a s (m :: * -> *) = Handling a
+
+--- the m parameter exists simply to break the Typeable1 pattern, so we can provide this without overlap.
+--- here we simply generate a fresh TypeRep so we'll fail to compare as equal to any other TypeRep.
+-instance Typeable (Handling a s m) where
+- typeOf _ = unsafePerformIO $ do
+- i <- atomicModifyIORef supply $ \a -> let a' = a + 1 in a' `seq` (a', a)
+- return $ mkTyConApp (mkTyCon3 "lens" "Control.Lens.Internal.Exception" ("Handling" ++ show i)) []
+- {-# INLINE typeOf #-}
+-
+ -- The @Handling@ wrapper is uninteresting, and should never be thrown, so you won't get much benefit here.
+ instance Show (Handling a s m) where
+ showsPrec d _ = showParen (d > 10) $ showString "Handling ..."
+ {-# INLINE showsPrec #-}
+
+-instance Reifies s (SomeException -> Maybe a) => Exception (Handling a s m) where
+- toException _ = SomeException HandlingException
+- {-# INLINE toException #-}
+- fromException = fmap Handling . reflect (Proxy :: Proxy s)
+- {-# INLINE fromException #-}
+diff --git a/src/Control/Lens/Internal/Instances.hs b/src/Control/Lens/Internal/Instances.hs
+index 6783f33..17715ce 100644
+--- a/src/Control/Lens/Internal/Instances.hs
++++ b/src/Control/Lens/Internal/Instances.hs
+@@ -24,26 +24,12 @@ import Data.Traversable
+ -- Orphan Instances
+ -------------------------------------------------------------------------------
+
+-instance Foldable ((,) b) where
+- foldMap f (_, a) = f a
+-
+ instance Foldable1 ((,) b) where
+ foldMap1 f (_, a) = f a
+
+-instance Traversable ((,) b) where
+- traverse f (b, a) = (,) b <$> f a
+-
+ instance Traversable1 ((,) b) where
+ traverse1 f (b, a) = (,) b <$> f a
+
+-instance Foldable (Either a) where
+- foldMap _ (Left _) = mempty
+- foldMap f (Right a) = f a
+-
+-instance Traversable (Either a) where
+- traverse _ (Left b) = pure (Left b)
+- traverse f (Right a) = Right <$> f a
+-
+ instance Foldable (Const m) where
+ foldMap _ _ = mempty
+
diff --git a/src/Control/Lens/Internal/Zipper.hs b/src/Control/Lens/Internal/Zipper.hs
index 95875b7..76060be 100644
--- a/src/Control/Lens/Internal/Zipper.hs
@@ -197,12 +276,12 @@ index 95875b7..76060be 100644
------------------------------------------------------------------------------
-- * Jacket
diff --git a/src/Control/Lens/Iso.hs b/src/Control/Lens/Iso.hs
-index 62d40ef..235511a 100644
+index 1152af4..80c3175 100644
--- a/src/Control/Lens/Iso.hs
+++ b/src/Control/Lens/Iso.hs
-@@ -70,8 +70,6 @@ import Data.Profunctor.Unsafe
- import Unsafe.Coerce
- #endif
+@@ -82,8 +82,6 @@ import Data.Maybe
+ import Data.Profunctor
+ import Data.Profunctor.Unsafe
-{-# ANN module "HLint: ignore Use on" #-}
-
@@ -210,12 +289,12 @@ index 62d40ef..235511a 100644
-- >>> :set -XNoOverloadedStrings
-- >>> import Control.Lens
diff --git a/src/Control/Lens/Lens.hs b/src/Control/Lens/Lens.hs
-index ff2a45f..5401ec4 100644
+index b26cc06..6f84943 100644
--- a/src/Control/Lens/Lens.hs
+++ b/src/Control/Lens/Lens.hs
-@@ -120,7 +120,7 @@ import Data.Profunctor
- import Data.Profunctor.Rep
+@@ -126,7 +126,7 @@ import Data.Profunctor.Rep
import Data.Profunctor.Unsafe
+ import Data.Void
-{-# ANN module "HLint: ignore Use ***" #-}
+
@@ -223,17 +302,17 @@ index ff2a45f..5401ec4 100644
-- $setup
-- >>> :set -XNoOverloadedStrings
diff --git a/src/Control/Lens/Operators.hs b/src/Control/Lens/Operators.hs
-index d88cb49..fa7b37e 100644
+index 11868e0..475c945 100644
--- a/src/Control/Lens/Operators.hs
+++ b/src/Control/Lens/Operators.hs
-@@ -107,4 +107,4 @@ import Control.Lens.Review
+@@ -108,4 +108,4 @@ import Control.Lens.Review
import Control.Lens.Setter
import Control.Lens.Zipper
-{-# ANN module "HLint: ignore Use import/export shortcut" #-}
+
diff --git a/src/Control/Lens/Plated.hs b/src/Control/Lens/Plated.hs
-index 07d9212..27070c0 100644
+index a8c4d20..cef574e 100644
--- a/src/Control/Lens/Plated.hs
+++ b/src/Control/Lens/Plated.hs
@@ -95,7 +95,7 @@ import Data.Data.Lens
@@ -245,6 +324,19 @@ index 07d9212..27070c0 100644
-- | A 'Plated' type is one where we know how to extract its immediate self-similar children.
--
+diff --git a/src/Control/Lens/Prism.hs b/src/Control/Lens/Prism.hs
+index 45b5cfe..88c7ff9 100644
+--- a/src/Control/Lens/Prism.hs
++++ b/src/Control/Lens/Prism.hs
+@@ -53,8 +53,6 @@ import Unsafe.Coerce
+ import Data.Profunctor.Unsafe
+ #endif
+
+-{-# ANN module "HLint: ignore Use camelCase" #-}
+-
+ -- $setup
+ -- >>> :set -XNoOverloadedStrings
+ -- >>> import Control.Lens
diff --git a/src/Control/Lens/Setter.hs b/src/Control/Lens/Setter.hs
index 2acbfa6..4a12c6b 100644
--- a/src/Control/Lens/Setter.hs
@@ -259,7 +351,7 @@ index 2acbfa6..4a12c6b 100644
-- >>> import Control.Lens
-- >>> import Control.Monad.State
diff --git a/src/Control/Lens/TH.hs b/src/Control/Lens/TH.hs
-index fbf4adb..ee723d7 100644
+index a05eb07..49218b5 100644
--- a/src/Control/Lens/TH.hs
+++ b/src/Control/Lens/TH.hs
@@ -87,7 +87,7 @@ import Language.Haskell.TH
@@ -289,5 +381,5 @@ index cf1e7c9..b39dacf 100644
-- $setup
-- >>> :set -XNoOverloadedStrings
--
-1.8.2.rc3
+1.7.10.4
diff --git a/standalone/android/haskell-patches/libxml-sax_0.7.3-0001-static-link-with-libxml2.patch b/standalone/android/haskell-patches/libxml-sax_0.7.3-0001-static-link-with-libxml2.patch
deleted file mode 100644
index 752f601cc..000000000
--- a/standalone/android/haskell-patches/libxml-sax_0.7.3-0001-static-link-with-libxml2.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 9d53e3fa4516a948a6e84987e9c1c9fd07f973bf Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Sun, 21 Apr 2013 15:44:51 -0400
-Subject: [PATCH] static link with libxml2
-
-This requires libxml2.a (and no .so) be installed in the ugly hardcoded
-lib dir. When built this way, the haskell library will link the
-C library into executables with no further options.
----
- libxml-sax.cabal | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/libxml-sax.cabal b/libxml-sax.cabal
-index 5edfdb6..338bc55 100644
---- a/libxml-sax.cabal
-+++ b/libxml-sax.cabal
-@@ -31,6 +31,7 @@ library
- hs-source-dirs: lib
- ghc-options: -Wall -O2
- cc-options: -Wall
-+ LD-Options: -L /home/joey/.ghc/android-14/arm-linux-androideabi-4.7/arm-linux-androideabi/sysroot/usr/lib/
-
- build-depends:
- base >= 4.1 && < 5.0
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/lifted-base_0.2.0.2_0001-hacked-for-newer-ghc.patch b/standalone/android/haskell-patches/lifted-base_0.2.0.2_0001-hacked-for-newer-ghc.patch
deleted file mode 100644
index b61dc17ba..000000000
--- a/standalone/android/haskell-patches/lifted-base_0.2.0.2_0001-hacked-for-newer-ghc.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-From 4bb0de1e6213ec925820c8b9cc3ff5f3c3c72d7a Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:31:27 -0400
-Subject: [PATCH] hacked for newer ghc
-
----
- Control/Concurrent/Lifted.hs | 2 +-
- Control/Exception/Lifted.hs | 11 ++--------
- Setup.hs | 46 ++----------------------------------------
- lifted-base.cabal | 9 ++++-----
- 4 files changed, 9 insertions(+), 59 deletions(-)
-
-diff --git a/Control/Concurrent/Lifted.hs b/Control/Concurrent/Lifted.hs
-index 4bc58a8..e4445e6 100644
---- a/Control/Concurrent/Lifted.hs
-+++ b/Control/Concurrent/Lifted.hs
-@@ -124,7 +124,7 @@ import Control.Concurrent.SampleVar.Lifted
- #endif
- import Control.Exception.Lifted ( throwTo
- #if MIN_VERSION_base(4,6,0)
-- , SomeException, try, mask
-+ , SomeException, try
- #endif
- )
- #include "inlinable.h"
-diff --git a/Control/Exception/Lifted.hs b/Control/Exception/Lifted.hs
-index 871cda7..0b9d8b7 100644
---- a/Control/Exception/Lifted.hs
-+++ b/Control/Exception/Lifted.hs
-@@ -50,8 +50,8 @@ module Control.Exception.Lifted
- -- |The following functions allow a thread to control delivery of
- -- asynchronous exceptions during a critical region.
- #if MIN_VERSION_base(4,3,0)
-- , mask, mask_
-- , uninterruptibleMask, uninterruptibleMask_
-+ , mask_
-+ , uninterruptibleMask_
- , getMaskingState
- #if MIN_VERSION_base(4,4,0)
- , allowInterrupt
-@@ -266,10 +266,6 @@ evaluate = liftBase ∘ E.evaluate
- --------------------------------------------------------------------------------
-
- #if MIN_VERSION_base(4,3,0)
---- |Generalized version of 'E.mask'.
--mask ∷ MonadBaseControl IO m ⇒ ((∀ a. m a → m a) → m b) → m b
--mask = liftBaseOp E.mask ∘ liftRestore
--{-# INLINABLE mask #-}
-
- liftRestore ∷ MonadBaseControl IO m
- ⇒ ((∀ a. m a → m a) → b)
-@@ -283,9 +279,6 @@ mask_ = liftBaseOp_ E.mask_
- {-# INLINABLE mask_ #-}
-
- -- |Generalized version of 'E.uninterruptibleMask'.
--uninterruptibleMask ∷ MonadBaseControl IO m ⇒ ((∀ a. m a → m a) → m b) → m b
--uninterruptibleMask = liftBaseOp E.uninterruptibleMask ∘ liftRestore
--{-# INLINABLE uninterruptibleMask #-}
-
- -- |Generalized version of 'E.uninterruptibleMask_'.
- uninterruptibleMask_ ∷ MonadBaseControl IO m ⇒ m a → m a
-diff --git a/Setup.hs b/Setup.hs
-index 33956e1..9a994af 100644
---- a/Setup.hs
-+++ b/Setup.hs
-@@ -1,44 +1,2 @@
--#! /usr/bin/env runhaskell
--
--{-# LANGUAGE NoImplicitPrelude, UnicodeSyntax #-}
--
--module Main (main) where
--
--
---------------------------------------------------------------------------------
---- Imports
---------------------------------------------------------------------------------
--
---- from base
--import System.IO ( IO )
--
---- from cabal
--import Distribution.Simple ( defaultMainWithHooks
-- , simpleUserHooks
-- , UserHooks(haddockHook)
-- )
--
--import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) )
--import Distribution.Simple.Program ( userSpecifyArgs )
--import Distribution.Simple.Setup ( HaddockFlags )
--import Distribution.PackageDescription ( PackageDescription(..) )
--
--
---------------------------------------------------------------------------------
---- Cabal setup program which sets the CPP define '__HADDOCK __' when haddock is run.
---------------------------------------------------------------------------------
--
--main ∷ IO ()
--main = defaultMainWithHooks hooks
-- where
-- hooks = simpleUserHooks { haddockHook = haddockHook' }
--
---- Define __HADDOCK__ for CPP when running haddock.
--haddockHook' ∷ PackageDescription → LocalBuildInfo → UserHooks → HaddockFlags → IO ()
--haddockHook' pkg lbi =
-- haddockHook simpleUserHooks pkg (lbi { withPrograms = p })
-- where
-- p = userSpecifyArgs "haddock" ["--optghc=-D__HADDOCK__"] (withPrograms lbi)
--
--
---- The End ---------------------------------------------------------------------
-+import Distribution.Simple
-+main = defaultMain
-diff --git a/lifted-base.cabal b/lifted-base.cabal
-index 54ef418..8da5086 100644
---- a/lifted-base.cabal
-+++ b/lifted-base.cabal
-@@ -9,7 +9,7 @@ Copyright: (c) 2011-2012 Bas van Dijk, Anders Kaseorg
- Homepage: https://github.com/basvandijk/lifted-base
- Bug-reports: https://github.com/basvandijk/lifted-base/issues
- Category: Control
--Build-type: Custom
-+Build-type: Simple
- Cabal-version: >= 1.9.2
- Description: @lifted-base@ exports IO operations from the base library lifted to
- any instance of 'MonadBase' or 'MonadBaseControl'.
-@@ -37,7 +37,6 @@ Library
- Exposed-modules: Control.Exception.Lifted
- Control.Concurrent.MVar.Lifted
- Control.Concurrent.Chan.Lifted
-- Control.Concurrent.Lifted
- Data.IORef.Lifted
- System.Timeout.Lifted
- if impl(ghc < 7.6)
-@@ -46,7 +45,7 @@ Library
- Control.Concurrent.QSemN.Lifted
- Control.Concurrent.SampleVar.Lifted
-
-- Build-depends: base >= 3 && < 4.7
-+ Build-depends: base >= 3 && < 4.8
- , base-unicode-symbols >= 0.1.1 && < 0.3
- , transformers-base >= 0.4 && < 0.5
- , monad-control >= 0.3 && < 0.4
-@@ -64,7 +63,7 @@ test-suite test-lifted-base
- hs-source-dirs: test
-
- build-depends: lifted-base
-- , base >= 3 && < 4.7
-+ , base >= 3 && < 4.8
- , transformers >= 0.2 && < 0.4
- , transformers-base >= 0.4 && < 0.5
- , monad-control >= 0.3 && < 0.4
-@@ -87,7 +86,7 @@ benchmark bench-lifted-base
- ghc-options: -O2
-
- build-depends: lifted-base
-- , base >= 3 && < 4.7
-+ , base >= 3 && < 4.8
- , transformers >= 0.2 && < 0.4
- , criterion >= 0.5 && < 0.7
- , monad-control >= 0.3 && < 0.4
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/lifted-base_crossbuild.patch b/standalone/android/haskell-patches/lifted-base_crossbuild.patch
new file mode 100644
index 000000000..945aee491
--- /dev/null
+++ b/standalone/android/haskell-patches/lifted-base_crossbuild.patch
@@ -0,0 +1,25 @@
+From 8a98fa29048b508c64d5bb1e03ef89bfad8adc01 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 21:34:17 +0000
+Subject: [PATCH] crossbuild
+
+---
+ lifted-base.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lifted-base.cabal b/lifted-base.cabal
+index 24f2860..3bef225 100644
+--- a/lifted-base.cabal
++++ b/lifted-base.cabal
+@@ -9,7 +9,7 @@ Copyright: (c) 2011-2012 Bas van Dijk, Anders Kaseorg
+ Homepage: https://github.com/basvandijk/lifted-base
+ Bug-reports: https://github.com/basvandijk/lifted-base/issues
+ Category: Control
+-Build-type: Custom
++Build-type: Simple
+ Cabal-version: >= 1.8
+ Description: @lifted-base@ exports IO operations from the base library lifted to
+ any instance of 'MonadBase' or 'MonadBaseControl'.
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/monad-control_0.3.1.4_0001-build-with-newer-ghc.patch b/standalone/android/haskell-patches/monad-control_0.3.1.4_0001-build-with-newer-ghc.patch
deleted file mode 100644
index ee1c996d8..000000000
--- a/standalone/android/haskell-patches/monad-control_0.3.1.4_0001-build-with-newer-ghc.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 3dde0175096903207c9774d8f6bba9b81ab6c2f9 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:31:45 -0400
-Subject: [PATCH] build with newer ghc
-
----
- monad-control.cabal | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/monad-control.cabal b/monad-control.cabal
-index 2e3eb46..b12ffaf 100644
---- a/monad-control.cabal
-+++ b/monad-control.cabal
-@@ -56,7 +56,7 @@ Library
-
- Exposed-modules: Control.Monad.Trans.Control
-
-- Build-depends: base >= 3 && < 4.7
-+ Build-depends: base >= 3 && < 4.8
- , base-unicode-symbols >= 0.1.1 && < 0.3
- , transformers >= 0.2 && < 0.4
- , transformers-base >= 0.4.1 && < 0.5
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/monad-logger_0.2.3.2_0001-remove-TH-logging-stuff.patch b/standalone/android/haskell-patches/monad-logger_0.2.3.2_0001-remove-TH-logging-stuff.patch
deleted file mode 100644
index e684c67a7..000000000
--- a/standalone/android/haskell-patches/monad-logger_0.2.3.2_0001-remove-TH-logging-stuff.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From ca88563e63cc31f0b96b00d3a4fe1f0c56b1e1eb Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:32:01 -0400
-Subject: [PATCH] remove TH logging stuff
-
----
- Control/Monad/Logger.hs | 76 -----------------------------------------------
- monad-logger.cabal | 2 +-
- 2 files changed, 1 insertion(+), 77 deletions(-)
-
-diff --git a/Control/Monad/Logger.hs b/Control/Monad/Logger.hs
-index fd1282b..80b8ed9 100644
---- a/Control/Monad/Logger.hs
-+++ b/Control/Monad/Logger.hs
-@@ -27,18 +27,6 @@ module Control.Monad.Logger
- , LoggingT (..)
- , runStderrLoggingT
- , runStdoutLoggingT
-- -- * TH logging
-- , logDebug
-- , logInfo
-- , logWarn
-- , logError
-- , logOther
-- -- * TH logging with source
-- , logDebugS
-- , logInfoS
-- , logWarnS
-- , logErrorS
-- , logOtherS
- ) where
-
- import Language.Haskell.TH.Syntax (Lift (lift), Q, Exp, Loc (..), qLocation)
-@@ -91,13 +79,6 @@ import Control.Monad.Writer.Class ( MonadWriter (..) )
- data LogLevel = LevelDebug | LevelInfo | LevelWarn | LevelError | LevelOther Text
- deriving (Eq, Prelude.Show, Prelude.Read, Ord)
-
--instance Lift LogLevel where
-- lift LevelDebug = [|LevelDebug|]
-- lift LevelInfo = [|LevelInfo|]
-- lift LevelWarn = [|LevelWarn|]
-- lift LevelError = [|LevelError|]
-- lift (LevelOther x) = [|LevelOther $ pack $(lift $ unpack x)|]
--
- type LogSource = Text
-
- class Monad m => MonadLogger m where
-@@ -128,63 +109,6 @@ instance (MonadLogger m, Monoid w) => MonadLogger (Strict.WriterT w m) where DEF
- instance (MonadLogger m, Monoid w) => MonadLogger (Strict.RWST r w s m) where DEF
- #undef DEF
-
--logTH :: LogLevel -> Q Exp
--logTH level =
-- [|monadLoggerLog $(qLocation >>= liftLoc) $(lift level) . (id :: Text -> Text)|]
--
---- | Generates a function that takes a 'Text' and logs a 'LevelDebug' message. Usage:
----
---- > $(logDebug) "This is a debug log message"
--logDebug :: Q Exp
--logDebug = logTH LevelDebug
--
---- | See 'logDebug'
--logInfo :: Q Exp
--logInfo = logTH LevelInfo
---- | See 'logDebug'
--logWarn :: Q Exp
--logWarn = logTH LevelWarn
---- | See 'logDebug'
--logError :: Q Exp
--logError = logTH LevelError
--
---- | Generates a function that takes a 'Text' and logs a 'LevelOther' message. Usage:
----
---- > $(logOther "My new level") "This is a log message"
--logOther :: Text -> Q Exp
--logOther = logTH . LevelOther
--
--liftLoc :: Loc -> Q Exp
--liftLoc (Loc a b c (d1, d2) (e1, e2)) = [|Loc
-- $(lift a)
-- $(lift b)
-- $(lift c)
-- ($(lift d1), $(lift d2))
-- ($(lift e1), $(lift e2))
-- |]
--
---- | Generates a function that takes a 'LogSource' and 'Text' and logs a 'LevelDebug' message. Usage:
----
---- > $logDebug "SomeSource" "This is a debug log message"
--logDebugS :: Q Exp
--logDebugS = [|\a b -> monadLoggerLogSource $(qLocation >>= liftLoc) a LevelDebug (b :: Text)|]
--
---- | See 'logDebugS'
--logInfoS :: Q Exp
--logInfoS = [|\a b -> monadLoggerLogSource $(qLocation >>= liftLoc) a LevelInfo (b :: Text)|]
---- | See 'logDebugS'
--logWarnS :: Q Exp
--logWarnS = [|\a b -> monadLoggerLogSource $(qLocation >>= liftLoc) a LevelWarn (b :: Text)|]
---- | See 'logDebugS'
--logErrorS :: Q Exp
--logErrorS = [|\a b -> monadLoggerLogSource $(qLocation >>= liftLoc) a LevelError (b :: Text)|]
--
---- | Generates a function that takes a 'LogSource', a level name and a 'Text' and logs a 'LevelOther' message. Usage:
----
---- > $logOther "SomeSource" "My new level" "This is a log message"
--logOtherS :: Q Exp
--logOtherS = [|\src level msg -> monadLoggerLogSource $(qLocation >>= liftLoc) src (LevelOther level) (msg :: Text)|]
--
- -- | Monad transformer that adds a new logging function.
- --
- -- Since 0.2.2
-diff --git a/monad-logger.cabal b/monad-logger.cabal
-index ab71424..fa3d292 100644
---- a/monad-logger.cabal
-+++ b/monad-logger.cabal
-@@ -24,4 +24,4 @@ library
- , transformers-base
- , monad-control
- , mtl
-- , bytestring
-+ , bytestring >= 0.10.3.0
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/network-conduit_0.6.2.2_0001-NoDelay-does-not-work-on-Android.patch b/standalone/android/haskell-patches/network-conduit_0.6.2.2_0001-NoDelay-does-not-work-on-Android.patch
deleted file mode 100644
index 35bafa774..000000000
--- a/standalone/android/haskell-patches/network-conduit_0.6.2.2_0001-NoDelay-does-not-work-on-Android.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 3e05f3a3bf886c302fb6d6caa7ee92cf9736b6ad Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:33:45 -0400
-Subject: [PATCH] NoDelay does not work on Android
-
-(I think the other change is no-op)
----
- Data/Conduit/Network/Utils.hs | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/Data/Conduit/Network/Utils.hs b/Data/Conduit/Network/Utils.hs
-index 32a7286..01ff84e 100644
---- a/Data/Conduit/Network/Utils.hs
-+++ b/Data/Conduit/Network/Utils.hs
-@@ -6,14 +6,14 @@ module Data.Conduit.Network.Utils
- , getSocket
- ) where
-
--import Network.Socket (AddrInfo, Socket, SocketType)
-+import Network.Socket (Socket, SocketType)
- import qualified Network.Socket as NS
- import Data.String (IsString (fromString))
- import Control.Exception (bracketOnError, IOException)
- import qualified Control.Exception as E
-
- -- | Attempt to connect to the given host/port using given @SocketType@.
--getSocket :: String -> Int -> SocketType -> IO (Socket, AddrInfo)
-+getSocket :: String -> Int -> SocketType -> IO (Socket, NS.AddrInfo)
- getSocket host' port' sockettype = do
- let hints = NS.defaultHints {
- NS.addrFlags = [NS.AI_ADDRCONFIG]
-@@ -93,7 +93,7 @@ bindPort p s sockettype = do
- sockOpts =
- case sockettype of
- NS.Datagram -> [(NS.ReuseAddr,1)]
-- _ -> [(NS.NoDelay,1), (NS.ReuseAddr,1)]
-+ _ -> [(NS.ReuseAddr,1)] -- Android seems to not have NoDelay
-
- theBody addr =
- bracketOnError
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/network-protocol-xmpp_0.4.4-0001-avoid-using-gnuidn.patch b/standalone/android/haskell-patches/network-protocol-xmpp_0.4.4-0001-avoid-using-gnuidn.patch
deleted file mode 100644
index 26734fa70..000000000
--- a/standalone/android/haskell-patches/network-protocol-xmpp_0.4.4-0001-avoid-using-gnuidn.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From d15ae2193eff9cd38ebce641279996233434b50f Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Sun, 21 Apr 2013 16:05:53 -0400
-Subject: [PATCH] avoid using gnuidn
-
-IDN is only used to handle the domain name part of a XMPP server JID.
-Which seems not worth the bloat on Android.
----
- lib/Network/Protocol/XMPP/JID.hs | 11 ++++-------
- network-protocol-xmpp.cabal | 1 -
- 2 files changed, 4 insertions(+), 8 deletions(-)
-
-diff --git a/lib/Network/Protocol/XMPP/JID.hs b/lib/Network/Protocol/XMPP/JID.hs
-index 91745e0..2a50409 100644
---- a/lib/Network/Protocol/XMPP/JID.hs
-+++ b/lib/Network/Protocol/XMPP/JID.hs
-@@ -29,7 +29,6 @@ module Network.Protocol.XMPP.JID
-
- import qualified Data.Text
- import Data.Text (Text)
--import qualified Data.Text.IDN.StringPrep as SP
- import Data.String (IsString, fromString)
-
- newtype Node = Node { strNode :: Text }
-@@ -85,16 +84,14 @@ parseJID str = maybeJID where
- then Just Nothing
- else fmap Just (f x)
- maybeJID = do
-- preppedNode <- nullable node (stringprepM SP.xmppNode)
-- preppedDomain <- stringprepM SP.nameprep domain
-- preppedResource <- nullable resource (stringprepM SP.xmppResource)
-+ preppedNode <- nullable node (stringprepM id)
-+ preppedDomain <- stringprepM id domain
-+ preppedResource <- nullable resource (stringprepM id)
- return $ JID
- (fmap Node preppedNode)
- (Domain preppedDomain)
- (fmap Resource preppedResource)
-- stringprepM p x = case SP.stringprep p SP.defaultFlags x of
-- Left _ -> Nothing
-- Right y -> Just y
-+ stringprepM p x = Just x
-
- parseJID_ :: Text -> JID
- parseJID_ text = case parseJID text of
-diff --git a/network-protocol-xmpp.cabal b/network-protocol-xmpp.cabal
-index 807cda9..3aaad67 100644
---- a/network-protocol-xmpp.cabal
-+++ b/network-protocol-xmpp.cabal
-@@ -30,7 +30,6 @@ library
- build-depends:
- base >= 4.0 && < 5.0
- , bytestring >= 0.9
-- , gnuidn >= 0.2 && < 0.3
- , gnutls >= 0.1.4 && < 0.3
- , gsasl >= 0.3 && < 0.4
- , libxml-sax >= 0.7 && < 0.8
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/network_2.4.1.0_0003-configure-misdetects-accept4.patch b/standalone/android/haskell-patches/network_2.4.1.0_0003-configure-misdetects-accept4.patch
index 9be862b5a..116fa320e 100644
--- a/standalone/android/haskell-patches/network_2.4.1.0_0003-configure-misdetects-accept4.patch
+++ b/standalone/android/haskell-patches/network_2.4.1.0_0003-configure-misdetects-accept4.patch
@@ -1,26 +1,26 @@
-From 5b14dd83f9ff1d187871fc7c6e956cad95bc4e9b Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Fri, 19 Apr 2013 15:36:25 -0400
+From 63a7a97511266c1a9d2414d3314ee17fc88bb8f2 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Fri, 18 Oct 2013 15:58:35 +0000
Subject: [PATCH] configure misdetects accept4
---
- Network/Socket.hsc | 4 ++--
+ Network/Socket.hsc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Network/Socket.hsc b/Network/Socket.hsc
-index e6c0feb..49d090b 100644
+index 9af31f8..6c21209 100644
--- a/Network/Socket.hsc
+++ b/Network/Socket.hsc
-@@ -505,7 +505,7 @@ accept sock@(MkSocket s family stype protocol status) = do
+@@ -503,7 +503,7 @@ accept sock@(MkSocket s family stype protocol status) = do
+ return new_sock
#else
with (fromIntegral sz) $ \ ptr_len -> do
- new_sock <-
-# ifdef HAVE_ACCEPT4
-+# if 0
- throwSocketErrorIfMinus1RetryMayBlock "accept"
++#if 0
+ new_sock <- throwSocketErrorIfMinus1RetryMayBlock "accept"
(threadWaitRead (fromIntegral s))
(c_accept4 s sockaddr ptr_len (#const SOCK_NONBLOCK))
-@@ -1589,7 +1589,7 @@ foreign import CALLCONV SAFE_ON_WIN "connect"
+@@ -1615,7 +1615,7 @@ foreign import CALLCONV SAFE_ON_WIN "connect"
c_connect :: CInt -> Ptr SockAddr -> CInt{-CSockLen???-} -> IO CInt
foreign import CALLCONV unsafe "accept"
c_accept :: CInt -> Ptr SockAddr -> Ptr CInt{-CSockLen???-} -> IO CInt
@@ -30,5 +30,5 @@ index e6c0feb..49d090b 100644
c_accept4 :: CInt -> Ptr SockAddr -> Ptr CInt{-CSockLen???-} -> CInt -> IO CInt
#endif
--
-1.8.2.rc3
+1.7.10.4
diff --git a/standalone/android/haskell-patches/persistent-template_stub-out.patch b/standalone/android/haskell-patches/persistent-template_stub-out.patch
new file mode 100644
index 000000000..6b7b62bd4
--- /dev/null
+++ b/standalone/android/haskell-patches/persistent-template_stub-out.patch
@@ -0,0 +1,25 @@
+From 0b9df0de3aa45918a2a9226a2da6be4680276419 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 03:31:55 +0000
+Subject: [PATCH] stub out
+
+---
+ persistent-template.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/persistent-template.cabal b/persistent-template.cabal
+index 8216ce7..f23234b 100644
+--- a/persistent-template.cabal
++++ b/persistent-template.cabal
+@@ -23,7 +23,7 @@ library
+ , containers
+ , aeson
+ , monad-logger
+- exposed-modules: Database.Persist.TH
++ exposed-modules:
+ ghc-options: -Wall
+ if impl(ghc >= 7.4)
+ cpp-options: -DGHC_7_4
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/persistent_1.1.5.1_0001-disable-TH.patch b/standalone/android/haskell-patches/persistent_1.1.5.1_0001-disable-TH.patch
index 38cecc5c7..300975b83 100644
--- a/standalone/android/haskell-patches/persistent_1.1.5.1_0001-disable-TH.patch
+++ b/standalone/android/haskell-patches/persistent_1.1.5.1_0001-disable-TH.patch
@@ -1,71 +1,32 @@
-From 8fddef803ee9191ca15363283b7e4d5af4c70f3a Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:34:10 -0400
+From 760fa2c5044ae38bee8114ff84c625ac59f35c6f Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 00:03:55 +0000
Subject: [PATCH] disable TH
---
- Database/Persist/GenericSql/Internal.hs | 6 +-----
- Database/Persist/GenericSql/Raw.hs | 5 ++---
- 2 files changed, 3 insertions(+), 8 deletions(-)
+ Database/Persist/Sql/Raw.hs | 2 --
+ 1 file changed, 2 deletions(-)
-diff --git a/Database/Persist/GenericSql/Internal.hs b/Database/Persist/GenericSql/Internal.hs
-index f109887..5273398 100644
---- a/Database/Persist/GenericSql/Internal.hs
-+++ b/Database/Persist/GenericSql/Internal.hs
-@@ -14,7 +14,6 @@ module Database.Persist.GenericSql.Internal
- , createSqlPool
- , mkColumns
- , Column (..)
-- , logSQL
- , InsertSqlResult (..)
- ) where
-
-@@ -33,7 +32,7 @@ import Data.Monoid (Monoid, mappend, mconcat)
- import Database.Persist.EntityDef
- import qualified Data.Conduit as C
- import Language.Haskell.TH.Syntax (Q, Exp)
--import Control.Monad.Logger (logDebugS)
-+
- import Data.Maybe (mapMaybe, listToMaybe)
- import Data.Int (Int64)
-
-@@ -197,6 +196,3 @@ tableColumn t s = go $ entityColumns t
- | x == s = ColumnDef x y z
- | otherwise = go rest
- -}
--
--logSQL :: Q Exp
--logSQL = [|\sql_foo params_foo -> $logDebugS (T.pack "SQL") $ T.pack $ show (sql_foo :: Text) ++ " " ++ show (params_foo :: [PersistValue])|]
-diff --git a/Database/Persist/GenericSql/Raw.hs b/Database/Persist/GenericSql/Raw.hs
-index e4bf9f4..3da8fa0 100644
---- a/Database/Persist/GenericSql/Raw.hs
-+++ b/Database/Persist/GenericSql/Raw.hs
-@@ -26,7 +26,6 @@ import Database.Persist.GenericSql.Internal hiding (execute, withStmt)
- import Database.Persist.Store (PersistValue)
- import Data.IORef
- import Control.Monad.IO.Class
--import Control.Monad.Logger (logDebugS)
- import Control.Monad.Trans.Reader
- import qualified Data.Map as Map
- import Control.Applicative (Applicative)
-@@ -134,7 +133,7 @@ withStmt :: (MonadSqlPersist m, MonadResource m)
+diff --git a/Database/Persist/Sql/Raw.hs b/Database/Persist/Sql/Raw.hs
+index 73189dd..6efebea 100644
+--- a/Database/Persist/Sql/Raw.hs
++++ b/Database/Persist/Sql/Raw.hs
+@@ -22,7 +22,6 @@ rawQuery :: (MonadSqlPersist m, MonadResource m)
-> [PersistValue]
-> Source m [PersistValue]
- withStmt sql vals = do
+ rawQuery sql vals = do
- lift $ $logDebugS (pack "SQL") $ pack $ show sql ++ " " ++ show vals
-+ -- lift $ pack $ show sql ++ " " ++ show vals
conn <- lift askSqlConn
bracketP
- (getStmt' conn sql)
-@@ -146,7 +145,7 @@ execute x y = liftM (const ()) $ executeCount x y
+ (getStmtConn conn sql)
+@@ -34,7 +33,6 @@ rawExecute x y = liftM (const ()) $ rawExecuteCount x y
- executeCount :: MonadSqlPersist m => Text -> [PersistValue] -> m Int64
- executeCount sql vals = do
+ rawExecuteCount :: MonadSqlPersist m => Text -> [PersistValue] -> m Int64
+ rawExecuteCount sql vals = do
- $logDebugS (pack "SQL") $ pack $ show sql ++ " " ++ show vals
-+ -- pack $ show sql ++ " " ++ show vals
stmt <- getStmt sql
- res <- liftIO $ I.execute stmt vals
- liftIO $ reset stmt
+ res <- liftIO $ stmtExecute stmt vals
+ liftIO $ stmtReset stmt
--
1.7.10.4
diff --git a/standalone/android/haskell-patches/process_fix-build-with-new-ghc.patch b/standalone/android/haskell-patches/process_fix-build-with-new-ghc.patch
new file mode 100644
index 000000000..a790a316d
--- /dev/null
+++ b/standalone/android/haskell-patches/process_fix-build-with-new-ghc.patch
@@ -0,0 +1,24 @@
+From 0b0d4250cfce44b1a03b50458b4122370ab349ce Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 21:50:51 +0000
+Subject: [PATCH] fix build with new ghc
+
+---
+ System/Process/Internals.hs | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/System/Process/Internals.hs b/System/Process/Internals.hs
+index a73c6fc..6676a72 100644
+--- a/System/Process/Internals.hs
++++ b/System/Process/Internals.hs
+@@ -61,6 +61,7 @@ import Control.Concurrent
+ import Control.Exception
+ import Foreign.C
+ import Foreign
++import System.IO.Unsafe
+
+ # ifdef __GLASGOW_HASKELL__
+
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/resourcet_0.4.4_0001-hack-to-build-with-hacked-up-lifted-base-which-is-cu.patch b/standalone/android/haskell-patches/resourcet_0.4.4_0001-hack-to-build-with-hacked-up-lifted-base-which-is-cu.patch
deleted file mode 100644
index bcf3439fa..000000000
--- a/standalone/android/haskell-patches/resourcet_0.4.4_0001-hack-to-build-with-hacked-up-lifted-base-which-is-cu.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From c10ab80793a21dce0c7516725e1ca3b36a87aa25 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:35:08 -0400
-Subject: [PATCH] hack to build with hacked up lifted-base, which is currently
- lacking a mask
-
----
- Control/Monad/Trans/Resource.hs | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/Control/Monad/Trans/Resource.hs b/Control/Monad/Trans/Resource.hs
-index d209dd8..61ab349 100644
---- a/Control/Monad/Trans/Resource.hs
-+++ b/Control/Monad/Trans/Resource.hs
-@@ -5,7 +5,7 @@
- {-# LANGUAGE TypeFamilies #-}
- {-# LANGUAGE RankNTypes #-}
- {-# LANGUAGE CPP #-}
--{-# LANGUAGE DeriveDataTypeable #-}
-+{-# LANGUAGE DeriveDataTypeable, ImpredicativeTypes #-}
- #if __GLASGOW_HASKELL__ >= 704
- {-# LANGUAGE ConstraintKinds #-}
- #endif
-@@ -554,7 +554,7 @@ GOX(Monoid w, Strict.WriterT w)
- --
- -- Since 0.3.0
- resourceForkIO :: MonadBaseControl IO m => ResourceT m () -> ResourceT m ThreadId
--resourceForkIO (ResourceT f) = ResourceT $ \r -> L.mask $ \restore ->
-+resourceForkIO (ResourceT f) = ResourceT $ \r ->
- -- We need to make sure the counter is incremented before this call
- -- returns. Otherwise, the parent thread may call runResourceT before
- -- the child thread increments, and all resources will be freed
-@@ -565,7 +565,7 @@ resourceForkIO (ResourceT f) = ResourceT $ \r -> L.mask $ \restore ->
- (liftBaseDiscard forkIO $ bracket_
- (return ())
- (stateCleanup r)
-- (restore $ f r))
-+ (return ()))
-
- -- | A @Monad@ based on some monad which allows running of some 'IO' actions,
- -- via unsafe calls. This applies to 'IO' and 'ST', for instance.
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/shakespeare-css_1.0.2_0001-remove-TH.patch b/standalone/android/haskell-patches/shakespeare-css_1.0.2_0001-remove-TH.patch
index f868197a8..1c82eaead 100644
--- a/standalone/android/haskell-patches/shakespeare-css_1.0.2_0001-remove-TH.patch
+++ b/standalone/android/haskell-patches/shakespeare-css_1.0.2_0001-remove-TH.patch
@@ -1,15 +1,13 @@
-From 8f058e84892a8c4202275f524f74bd6a7097ad40 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Wed, 8 May 2013 02:07:15 -0400
+From 05d0b6e6d2f84cd8ff53b8ee3e42021fa02fe8e4 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sat, 21 Sep 2013 23:21:52 +0000
Subject: [PATCH] remove TH
---
- Text/Cassius.hs | 23 --------------
- Text/Css.hs | 84 -------------------------------------------------
- Text/CssCommon.hs | 4 ---
- Text/Lucius.hs | 30 +-----------------
- shakespeare-css.cabal | 2 +-
- 5 files changed, 2 insertions(+), 141 deletions(-)
+ Text/Cassius.hs | 23 -----------------------
+ Text/CssCommon.hs | 4 ----
+ Text/Lucius.hs | 30 +-----------------------------
+ 3 files changed, 1 insertion(+), 56 deletions(-)
diff --git a/Text/Cassius.hs b/Text/Cassius.hs
index ce05374..ae56b0a 100644
@@ -64,117 +62,6 @@ index ce05374..ae56b0a 100644
-- | Determine which identifiers are used by the given template, useful for
-- creating systems like yesod devel.
cassiusUsedIdentifiers :: String -> [(Deref, VarType)]
-diff --git a/Text/Css.hs b/Text/Css.hs
-index 8e6fc09..401a166 100644
---- a/Text/Css.hs
-+++ b/Text/Css.hs
-@@ -108,19 +108,6 @@ cssUsedIdentifiers toi2b parseBlocks s' =
- (scope, rest') = go rest
- go' (k, v) = k ++ v
-
--cssFileDebug :: Bool -- ^ perform the indent-to-brace conversion
-- -> Q Exp -> Parser [TopLevel] -> FilePath -> Q Exp
--cssFileDebug toi2b parseBlocks' parseBlocks fp = do
-- s <- fmap TL.unpack $ qRunIO $ readUtf8File fp
--#ifdef GHC_7_4
-- qAddDependentFile fp
--#endif
-- let vs = cssUsedIdentifiers toi2b parseBlocks s
-- c <- mapM vtToExp vs
-- cr <- [|cssRuntime toi2b|]
-- parseBlocks'' <- parseBlocks'
-- return $ cr `AppE` parseBlocks'' `AppE` (LitE $ StringL fp) `AppE` ListE c
--
- combineSelectors :: Selector -> Selector -> Selector
- combineSelectors a b = do
- a' <- a
-@@ -202,17 +189,6 @@ cssRuntime toi2b parseBlocks fp cd render' = unsafePerformIO $ do
-
- addScope scope = map (DerefIdent . Ident *** CDPlain . fromString) scope ++ cd
-
--vtToExp :: (Deref, VarType) -> Q Exp
--vtToExp (d, vt) = do
-- d' <- lift d
-- c' <- c vt
-- return $ TupE [d', c' `AppE` derefToExp [] d]
-- where
-- c :: VarType -> Q Exp
-- c VTPlain = [|CDPlain . toCss|]
-- c VTUrl = [|CDUrl|]
-- c VTUrlParam = [|CDUrlParam|]
--
- getVars :: Monad m => [(String, String)] -> Content -> m [(Deref, VarType)]
- getVars _ ContentRaw{} = return []
- getVars scope (ContentVar d) =
-@@ -268,68 +244,8 @@ compressBlock (Block x y blocks) =
- cc (ContentRaw a:ContentRaw b:c) = cc $ ContentRaw (a ++ b) : c
- cc (a:b) = a : cc b
-
--blockToCss :: Name -> Scope -> Block -> Q Exp
--blockToCss r scope (Block sel props subblocks) =
-- [|(:) (Css' $(selectorToBuilder r scope sel) $(listE $ map go props))
-- . foldr (.) id $(listE $ map subGo subblocks)
-- |]
-- where
-- go (x, y) = tupE [contentsToBuilder r scope x, contentsToBuilder r scope y]
-- subGo (Block sel' b c) =
-- blockToCss r scope $ Block sel'' b c
-- where
-- sel'' = combineSelectors sel sel'
--
--selectorToBuilder :: Name -> Scope -> Selector -> Q Exp
--selectorToBuilder r scope sels =
-- contentsToBuilder r scope $ intercalate [ContentRaw ","] sels
--
--contentsToBuilder :: Name -> Scope -> [Content] -> Q Exp
--contentsToBuilder r scope contents =
-- appE [|mconcat|] $ listE $ map (contentToBuilder r scope) contents
--
--contentToBuilder :: Name -> Scope -> Content -> Q Exp
--contentToBuilder _ _ (ContentRaw x) =
-- [|fromText . pack|] `appE` litE (StringL x)
--contentToBuilder _ scope (ContentVar d) =
-- case d of
-- DerefIdent (Ident s)
-- | Just val <- lookup s scope -> [|fromText . pack|] `appE` litE (StringL val)
-- _ -> [|toCss|] `appE` return (derefToExp [] d)
--contentToBuilder r _ (ContentUrl u) =
-- [|fromText|] `appE`
-- (varE r `appE` return (derefToExp [] u) `appE` listE [])
--contentToBuilder r _ (ContentUrlParam u) =
-- [|fromText|] `appE`
-- ([|uncurry|] `appE` varE r `appE` return (derefToExp [] u))
--
- type Scope = [(String, String)]
-
--topLevelsToCassius :: [TopLevel] -> Q Exp
--topLevelsToCassius a = do
-- r <- newName "_render"
-- lamE [varP r] $ appE [|CssNoWhitespace . foldr ($) []|] $ fmap ListE $ go r [] a
-- where
-- go _ _ [] = return []
-- go r scope (TopBlock b:rest) = do
-- e <- [|(++) $ map Css ($(blockToCss r scope b) [])|]
-- es <- go r scope rest
-- return $ e : es
-- go r scope (TopAtBlock name s b:rest) = do
-- let s' = contentsToBuilder r scope s
-- e <- [|(:) $ AtBlock $(lift name) $(s') $(blocksToCassius r scope b)|]
-- es <- go r scope rest
-- return $ e : es
-- go r scope (TopAtDecl dec cs:rest) = do
-- e <- [|(:) $ AtDecl $(lift dec) $(contentsToBuilder r scope cs)|]
-- es <- go r scope rest
-- return $ e : es
-- go r scope (TopVar k v:rest) = go r ((k, v) : scope) rest
--
--blocksToCassius :: Name -> Scope -> [Block] -> Q Exp
--blocksToCassius r scope a = do
-- appE [|foldr ($) []|] $ listE $ map (blockToCss r scope) a
--
- renderCss :: Css -> TL.Text
- renderCss css =
- toLazyText $ mconcat $ map go tops-- FIXME use a foldr
diff --git a/Text/CssCommon.hs b/Text/CssCommon.hs
index 719e0a8..8c40e8c 100644
--- a/Text/CssCommon.hs
@@ -192,10 +79,10 @@ index 719e0a8..8c40e8c 100644
-mkSizeType "ExSize" "ex"
-mkSizeType "PixelSize" "px"
diff --git a/Text/Lucius.hs b/Text/Lucius.hs
-index b71614e..a902e1c 100644
+index 89328bd..0a1cf5e 100644
--- a/Text/Lucius.hs
+++ b/Text/Lucius.hs
-@@ -6,12 +6,8 @@
+@@ -8,12 +8,8 @@
{-# OPTIONS_GHC -fno-warn-missing-fields #-}
module Text.Lucius
( -- * Parsing
@@ -203,13 +90,13 @@ index b71614e..a902e1c 100644
- , luciusFile
- , luciusFileDebug
- , luciusFileReload
+ -- ** Mixins
+- , luciusMixin
++ luciusMixin
+ , Mixin
-- ** Runtime
-- , luciusRT
-+ luciusRT
- , luciusRT'
- , -- * Datatypes
- Css
-@@ -31,11 +27,8 @@ module Text.Lucius
+ , luciusRT
+@@ -40,11 +36,8 @@ module Text.Lucius
, AbsoluteUnit (..)
, AbsoluteSize (..)
, absoluteSize
@@ -221,9 +108,9 @@ index b71614e..a902e1c 100644
-- * Internal
, parseTopLevels
, luciusUsedIdentifiers
-@@ -57,18 +50,6 @@ import Data.Either (partitionEithers)
- import Data.Monoid (mconcat)
+@@ -66,18 +59,6 @@ import Data.Monoid (mconcat)
import Data.List (isSuffixOf)
+ import Control.Arrow (second)
--- |
---
@@ -240,7 +127,7 @@ index b71614e..a902e1c 100644
whiteSpace :: Parser ()
whiteSpace = many whiteSpace1 >> return ()
-@@ -179,15 +160,6 @@ parseComment = do
+@@ -217,15 +198,6 @@ parseComment = do
_ <- manyTill anyChar $ try $ string "*/"
return $ ContentRaw ""
@@ -253,22 +140,9 @@ index b71614e..a902e1c 100644
-luciusFileDebug = cssFileDebug False [|parseTopLevels|] parseTopLevels
-luciusFileReload = luciusFileDebug
-
- parseTopLevels :: Parser [TopLevel]
+ parseTopLevels :: Parser [TopLevel Unresolved]
parseTopLevels =
go id
-diff --git a/shakespeare-css.cabal b/shakespeare-css.cabal
-index de2497b..874a3b5 100644
---- a/shakespeare-css.cabal
-+++ b/shakespeare-css.cabal
-@@ -33,7 +33,7 @@ library
- , shakespeare >= 1.0 && < 1.1
- , template-haskell
- , text >= 0.11.1.1 && < 0.12
-- , process >= 1.0 && < 1.2
-+ , process >= 1.0 && < 1.3
- , parsec >= 2 && < 4
- , transformers
-
--
1.7.10.4
diff --git a/standalone/android/haskell-patches/shakespeare-i18n_1.0.0.2_0001-remove-TH.patch b/standalone/android/haskell-patches/shakespeare-i18n_1.0.0.2_0001-remove-TH.patch
deleted file mode 100644
index 60528db0d..000000000
--- a/standalone/android/haskell-patches/shakespeare-i18n_1.0.0.2_0001-remove-TH.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From b128412ecee9677b788abecbbf1fd1edd447eea2 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:35:59 -0400
-Subject: [PATCH] remove TH
-
----
- Text/Shakespeare/I18N.hs | 130 +---------------------------------------------
- 1 file changed, 1 insertion(+), 129 deletions(-)
-
-diff --git a/Text/Shakespeare/I18N.hs b/Text/Shakespeare/I18N.hs
-index 1b486ed..aa5e358 100644
---- a/Text/Shakespeare/I18N.hs
-+++ b/Text/Shakespeare/I18N.hs
-@@ -51,10 +51,7 @@
- --
- -- You can also adapt those instructions for use with other systems.
- module Text.Shakespeare.I18N
-- ( mkMessage
-- , mkMessageFor
-- , mkMessageVariant
-- , RenderMessage (..)
-+ ( RenderMessage (..)
- , ToMessage (..)
- , SomeMessage (..)
- , Lang
-@@ -115,133 +112,8 @@ type Lang = Text
- --
- -- 3. create a 'RenderMessage' instance
- --
--mkMessage :: String -- ^ base name to use for translation type
-- -> FilePath -- ^ subdirectory which contains the translation files
-- -> Lang -- ^ default translation language
-- -> Q [Dec]
--mkMessage dt folder lang =
-- mkMessageCommon True "Msg" "Message" dt dt folder lang
-
-
---- | create 'RenderMessage' instance for an existing data-type
--mkMessageFor :: String -- ^ master translation data type
-- -> String -- ^ existing type to add translations for
-- -> FilePath -- ^ path to translation folder
-- -> Lang -- ^ default language
-- -> Q [Dec]
--mkMessageFor master dt folder lang = mkMessageCommon False "" "" master dt folder lang
--
---- | create an additional set of translations for a type created by `mkMessage`
--mkMessageVariant :: String -- ^ master translation data type
-- -> String -- ^ existing type to add translations for
-- -> FilePath -- ^ path to translation folder
-- -> Lang -- ^ default language
-- -> Q [Dec]
--mkMessageVariant master dt folder lang = mkMessageCommon False "Msg" "Message" master dt folder lang
--
---- |used by 'mkMessage' and 'mkMessageFor' to generate a 'RenderMessage' and possibly a message data type
--mkMessageCommon :: Bool -- ^ generate a new datatype from the constructors found in the .msg files
-- -> String -- ^ string to append to constructor names
-- -> String -- ^ string to append to datatype name
-- -> String -- ^ base name of master datatype
-- -> String -- ^ base name of translation datatype
-- -> FilePath -- ^ path to translation folder
-- -> Lang -- ^ default lang
-- -> Q [Dec]
--mkMessageCommon genType prefix postfix master dt folder lang = do
-- files <- qRunIO $ getDirectoryContents folder
-- (_files', contents) <- qRunIO $ fmap (unzip . catMaybes) $ mapM (loadLang folder) files
--#ifdef GHC_7_4
-- mapM_ qAddDependentFile _files'
--#endif
-- sdef <-
-- case lookup lang contents of
-- Nothing -> error $ "Did not find main language file: " ++ unpack lang
-- Just def -> toSDefs def
-- mapM_ (checkDef sdef) $ map snd contents
-- let mname = mkName $ dt ++ postfix
-- c1 <- fmap concat $ mapM (toClauses prefix dt) contents
-- c2 <- mapM (sToClause prefix dt) sdef
-- c3 <- defClause
-- return $
-- ( if genType
-- then ((DataD [] mname [] (map (toCon dt) sdef) []) :)
-- else id)
-- [ InstanceD
-- []
-- (ConT ''RenderMessage `AppT` (ConT $ mkName master) `AppT` ConT mname)
-- [ FunD (mkName "renderMessage") $ c1 ++ c2 ++ [c3]
-- ]
-- ]
--
--toClauses :: String -> String -> (Lang, [Def]) -> Q [Clause]
--toClauses prefix dt (lang, defs) =
-- mapM go defs
-- where
-- go def = do
-- a <- newName "lang"
-- (pat, bod) <- mkBody dt (prefix ++ constr def) (map fst $ vars def) (content def)
-- guard <- fmap NormalG [|$(return $ VarE a) == pack $(lift $ unpack lang)|]
-- return $ Clause
-- [WildP, ConP (mkName ":") [VarP a, WildP], pat]
-- (GuardedB [(guard, bod)])
-- []
--
--mkBody :: String -- ^ datatype
-- -> String -- ^ constructor
-- -> [String] -- ^ variable names
-- -> [Content]
-- -> Q (Pat, Exp)
--mkBody dt cs vs ct = do
-- vp <- mapM go vs
-- let pat = RecP (mkName cs) (map (varName dt *** VarP) vp)
-- let ct' = map (fixVars vp) ct
-- pack' <- [|Data.Text.pack|]
-- tomsg <- [|toMessage|]
-- let ct'' = map (toH pack' tomsg) ct'
-- mapp <- [|mappend|]
-- let app a b = InfixE (Just a) mapp (Just b)
-- e <-
-- case ct'' of
-- [] -> [|mempty|]
-- [x] -> return x
-- (x:xs) -> return $ foldl' app x xs
-- return (pat, e)
-- where
-- toH pack' _ (Raw s) = pack' `AppE` SigE (LitE (StringL s)) (ConT ''String)
-- toH _ tomsg (Var d) = tomsg `AppE` derefToExp [] d
-- go x = do
-- let y = mkName $ '_' : x
-- return (x, y)
-- fixVars vp (Var d) = Var $ fixDeref vp d
-- fixVars _ (Raw s) = Raw s
-- fixDeref vp (DerefIdent (Ident i)) = DerefIdent $ Ident $ fixIdent vp i
-- fixDeref vp (DerefBranch a b) = DerefBranch (fixDeref vp a) (fixDeref vp b)
-- fixDeref _ d = d
-- fixIdent vp i =
-- case lookup i vp of
-- Nothing -> i
-- Just y -> nameBase y
--
--sToClause :: String -> String -> SDef -> Q Clause
--sToClause prefix dt sdef = do
-- (pat, bod) <- mkBody dt (prefix ++ sconstr sdef) (map fst $ svars sdef) (scontent sdef)
-- return $ Clause
-- [WildP, ConP (mkName "[]") [], pat]
-- (NormalB bod)
-- []
--
--defClause :: Q Clause
--defClause = do
-- a <- newName "sub"
-- c <- newName "langs"
-- d <- newName "msg"
-- rm <- [|renderMessage|]
-- return $ Clause
-- [VarP a, ConP (mkName ":") [WildP, VarP c], VarP d]
-- (NormalB $ rm `AppE` VarE a `AppE` VarE c `AppE` VarE d)
-- []
--
- toCon :: String -> SDef -> Con
- toCon dt (SDef c vs _) =
- RecC (mkName $ "Msg" ++ c) $ map go vs
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/shakespeare-js_1.1.2_0001-remove-TH.patch b/standalone/android/haskell-patches/shakespeare-js_1.1.2_0001-remove-TH.patch
deleted file mode 100644
index 98a16ae07..000000000
--- a/standalone/android/haskell-patches/shakespeare-js_1.1.2_0001-remove-TH.patch
+++ /dev/null
@@ -1,308 +0,0 @@
-From 332c71b3f6bc4786b914e675020a23c492beee5a Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Tue, 7 May 2013 19:28:06 -0400
-Subject: [PATCH] remove TH
-
----
- Text/Coffee.hs | 54 -------------------------------------------------
- Text/Julius.hs | 56 ++++-----------------------------------------------
- Text/Roy.hs | 54 -------------------------------------------------
- Text/TypeScript.hs | 57 +---------------------------------------------------
- 4 files changed, 5 insertions(+), 216 deletions(-)
-
-diff --git a/Text/Coffee.hs b/Text/Coffee.hs
-index 2481936..3f7f9c3 100644
---- a/Text/Coffee.hs
-+++ b/Text/Coffee.hs
-@@ -51,14 +51,6 @@ module Text.Coffee
- -- ** Template-Reading Functions
- -- | These QuasiQuoter and Template Haskell methods return values of
- -- type @'JavascriptUrl' url@. See the Yesod book for details.
-- coffee
-- , coffeeFile
-- , coffeeFileReload
-- , coffeeFileDebug
--
--#ifdef TEST_EXPORT
-- , coffeeSettings
--#endif
- ) where
-
- import Language.Haskell.TH.Quote (QuasiQuoter (..))
-@@ -66,49 +58,3 @@ import Language.Haskell.TH.Syntax
- import Text.Shakespeare
- import Text.Julius
-
--coffeeSettings :: Q ShakespeareSettings
--coffeeSettings = do
-- jsettings <- javascriptSettings
-- return $ jsettings { varChar = '%'
-- , preConversion = Just PreConvert {
-- preConvert = ReadProcess "coffee" ["-spb"]
-- , preEscapeIgnoreBalanced = "'\"`" -- don't insert backtacks for variable already inside strings or backticks.
-- , preEscapeIgnoreLine = "#" -- ignore commented lines
-- , wrapInsertion = Just WrapInsertion {
-- wrapInsertionIndent = Just " "
-- , wrapInsertionStartBegin = "(("
-- , wrapInsertionSeparator = ", "
-- , wrapInsertionStartClose = ") =>"
-- , wrapInsertionEnd = ")"
-- , wrapInsertionApplyBegin = "("
-- , wrapInsertionApplyClose = ")\n"
-- }
-- }
-- }
--
---- | Read inline, quasiquoted CoffeeScript.
--coffee :: QuasiQuoter
--coffee = QuasiQuoter { quoteExp = \s -> do
-- rs <- coffeeSettings
-- quoteExp (shakespeare rs) s
-- }
--
---- | Read in a CoffeeScript template file. This function reads the file once, at
---- compile time.
--coffeeFile :: FilePath -> Q Exp
--coffeeFile fp = do
-- rs <- coffeeSettings
-- shakespeareFile rs fp
--
---- | Read in a CoffeeScript template file. This impure function uses
---- unsafePerformIO to re-read the file on every call, allowing for rapid
---- iteration.
--coffeeFileReload :: FilePath -> Q Exp
--coffeeFileReload fp = do
-- rs <- coffeeSettings
-- shakespeareFileReload rs fp
--
---- | Deprecated synonym for 'coffeeFileReload'
--coffeeFileDebug :: FilePath -> Q Exp
--coffeeFileDebug = coffeeFileReload
--{-# DEPRECATED coffeeFileDebug "Please use coffeeFileReload instead." #-}
-diff --git a/Text/Julius.hs b/Text/Julius.hs
-index 230eac3..1a0376f 100644
---- a/Text/Julius.hs
-+++ b/Text/Julius.hs
-@@ -14,17 +14,8 @@ module Text.Julius
- -- ** Template-Reading Functions
- -- | These QuasiQuoter and Template Haskell methods return values of
- -- type @'JavascriptUrl' url@. See the Yesod book for details.
-- js
-- , julius
-- , juliusFile
-- , jsFile
-- , juliusFileDebug
-- , jsFileDebug
-- , juliusFileReload
-- , jsFileReload
--
- -- * Datatypes
-- , JavascriptUrl
-+ JavascriptUrl
- , Javascript (..)
- , RawJavascript (..)
-
-@@ -37,9 +28,11 @@ module Text.Julius
- , renderJavascriptUrl
-
- -- ** internal, used by 'Text.Coffee'
-- , javascriptSettings
- -- ** internal
- , juliusUsedIdentifiers
-+
-+ -- used by TH splices
-+ , asJavascriptUrl
- ) where
-
- import Language.Haskell.TH.Quote (QuasiQuoter (..))
-@@ -101,47 +94,6 @@ instance RawJS TL.Text where rawJS = RawJavascript . fromLazyText
- instance RawJS Builder where rawJS = RawJavascript
- instance RawJS Bool where rawJS = RawJavascript . toJavascript
-
--javascriptSettings :: Q ShakespeareSettings
--javascriptSettings = do
-- toJExp <- [|toJavascript|]
-- wrapExp <- [|Javascript|]
-- unWrapExp <- [|unJavascript|]
-- asJavascriptUrl' <- [|asJavascriptUrl|]
-- return $ defaultShakespeareSettings { toBuilder = toJExp
-- , wrap = wrapExp
-- , unwrap = unWrapExp
-- , modifyFinalValue = Just asJavascriptUrl'
-- }
--
--js, julius :: QuasiQuoter
--js = QuasiQuoter { quoteExp = \s -> do
-- rs <- javascriptSettings
-- quoteExp (shakespeare rs) s
-- }
--
--julius = js
--
--jsFile, juliusFile :: FilePath -> Q Exp
--jsFile fp = do
-- rs <- javascriptSettings
-- shakespeareFile rs fp
--
--juliusFile = jsFile
--
--
--jsFileReload, juliusFileReload :: FilePath -> Q Exp
--jsFileReload fp = do
-- rs <- javascriptSettings
-- shakespeareFileReload rs fp
--
--juliusFileReload = jsFileReload
--
--jsFileDebug, juliusFileDebug :: FilePath -> Q Exp
--juliusFileDebug = jsFileReload
--{-# DEPRECATED juliusFileDebug "Please use juliusFileReload instead." #-}
--jsFileDebug = jsFileReload
--{-# DEPRECATED jsFileDebug "Please use jsFileReload instead." #-}
--
- -- | Determine which identifiers are used by the given template, useful for
- -- creating systems like yesod devel.
- juliusUsedIdentifiers :: String -> [(Deref, VarType)]
-diff --git a/Text/Roy.hs b/Text/Roy.hs
-index cf09cec..870c9f6 100644
---- a/Text/Roy.hs
-+++ b/Text/Roy.hs
-@@ -23,13 +23,6 @@ module Text.Roy
- -- ** Template-Reading Functions
- -- | These QuasiQuoter and Template Haskell methods return values of
- -- type @'JavascriptUrl' url@. See the Yesod book for details.
-- roy
-- , royFile
-- , royFileReload
--
--#ifdef TEST_EXPORT
-- , roySettings
--#endif
- ) where
-
- import Language.Haskell.TH.Quote (QuasiQuoter (..))
-@@ -37,50 +30,3 @@ import Language.Haskell.TH.Syntax
- import Text.Shakespeare
- import Text.Julius
-
---- | The Roy language compiles down to Javascript.
---- We do this compilation once at compile time to avoid needing to do it during the request.
---- We call this a preConversion because other shakespeare modules like Lucius use Haskell to compile during the request instead rather than a system call.
--roySettings :: Q ShakespeareSettings
--roySettings = do
-- jsettings <- javascriptSettings
-- return $ jsettings { varChar = '#'
-- , preConversion = Just PreConvert {
-- preConvert = ReadProcess "roy" ["--stdio"]
-- , preEscapeIgnoreBalanced = "'\""
-- , preEscapeIgnoreLine = "//"
-- , wrapInsertion = Nothing
-- {-
-- Just WrapInsertion {
-- wrapInsertionIndent = Just " "
-- , wrapInsertionStartBegin = "(\\"
-- , wrapInsertionSeparator = " "
-- , wrapInsertionStartClose = " ->\n"
-- , wrapInsertionEnd = ")"
-- , wrapInsertionApplyBegin = " "
-- , wrapInsertionApplyClose = ")\n"
-- }
-- -}
-- }
-- }
--
---- | Read inline, quasiquoted Roy.
--roy :: QuasiQuoter
--roy = QuasiQuoter { quoteExp = \s -> do
-- rs <- roySettings
-- quoteExp (shakespeare rs) s
-- }
--
---- | Read in a Roy template file. This function reads the file once, at
---- compile time.
--royFile :: FilePath -> Q Exp
--royFile fp = do
-- rs <- roySettings
-- shakespeareFile rs fp
--
---- | Read in a Roy template file. This impure function uses
---- unsafePerformIO to re-read the file on every call, allowing for rapid
---- iteration.
--royFileReload :: FilePath -> Q Exp
--royFileReload fp = do
-- rs <- roySettings
-- shakespeareFileReload rs fp
-diff --git a/Text/TypeScript.hs b/Text/TypeScript.hs
-index 34bf4bf..30c5388 100644
---- a/Text/TypeScript.hs
-+++ b/Text/TypeScript.hs
-@@ -53,65 +53,10 @@
- --
- -- 2. TypeScript: <http://typescript.codeplex.com/>
- module Text.TypeScript
-- ( -- * Functions
-- -- ** Template-Reading Functions
-- -- | These QuasiQuoter and Template Haskell methods return values of
-- -- type @'JavascriptUrl' url@. See the Yesod book for details.
-- tsc
-- , typeScriptFile
-- , typeScriptFileReload
--
--#ifdef TEST_EXPORT
-- , typeScriptSettings
--#endif
-+ (
- ) where
-
- import Language.Haskell.TH.Quote (QuasiQuoter (..))
- import Language.Haskell.TH.Syntax
- import Text.Shakespeare
- import Text.Julius
--
---- | The TypeScript language compiles down to Javascript.
---- We do this compilation once at compile time to avoid needing to do it during the request.
---- We call this a preConversion because other shakespeare modules like Lucius use Haskell to compile during the request instead rather than a system call.
--typeScriptSettings :: Q ShakespeareSettings
--typeScriptSettings = do
-- jsettings <- javascriptSettings
-- return $ jsettings { varChar = '#'
-- , preConversion = Just PreConvert {
-- preConvert = ReadProcess "sh" ["-c", "TMP_IN=$(mktemp XXXXXXXXXX.ts); TMP_OUT=$(mktemp XXXXXXXXXX.js); cat /dev/stdin > ${TMP_IN} && tsc --out ${TMP_OUT} ${TMP_IN} && cat ${TMP_OUT}; rm ${TMP_IN} && rm ${TMP_OUT}"]
-- , preEscapeIgnoreBalanced = "'\""
-- , preEscapeIgnoreLine = "//"
-- , wrapInsertion = Just WrapInsertion {
-- wrapInsertionIndent = Nothing
-- , wrapInsertionStartBegin = ";(function("
-- , wrapInsertionSeparator = ", "
-- , wrapInsertionStartClose = "){"
-- , wrapInsertionEnd = "})"
-- , wrapInsertionApplyBegin = "("
-- , wrapInsertionApplyClose = ");\n"
-- }
-- }
-- }
--
---- | Read inline, quasiquoted TypeScript
--tsc :: QuasiQuoter
--tsc = QuasiQuoter { quoteExp = \s -> do
-- rs <- typeScriptSettings
-- quoteExp (shakespeare rs) s
-- }
--
---- | Read in a Roy template file. This function reads the file once, at
---- compile time.
--typeScriptFile :: FilePath -> Q Exp
--typeScriptFile fp = do
-- rs <- typeScriptSettings
-- shakespeareFile rs fp
--
---- | Read in a Roy template file. This impure function uses
---- unsafePerformIO to re-read the file on every call, allowing for rapid
---- iteration.
--typeScriptFileReload :: FilePath -> Q Exp
--typeScriptFileReload fp = do
-- rs <- typeScriptSettings
-- shakespeareFileReload rs fp
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/shakespeare_1.0.3_0001-export-symbol-used-by-TH-splices.patch b/standalone/android/haskell-patches/shakespeare_1.0.3_0001-export-symbol-used-by-TH-splices.patch
index aa30b255a..51443b5d4 100644
--- a/standalone/android/haskell-patches/shakespeare_1.0.3_0001-export-symbol-used-by-TH-splices.patch
+++ b/standalone/android/haskell-patches/shakespeare_1.0.3_0001-export-symbol-used-by-TH-splices.patch
@@ -1,139 +1,26 @@
-From 3cb1056782c29b0b68bdcff8fa49d3ea92126956 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 16:46:15 -0400
-Subject: [PATCH] export symbol used by TH splices
+From 4a75a2f0d77168aa3115b991284a5120484e18f0 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 04:59:21 +0000
+Subject: [PATCH] TH exports
---
- Text/.Shakespeare.hs.swp | Bin 24576 -> 0 bytes
- Text/Shakespeare.hs | 2 ++
- 2 files changed, 2 insertions(+)
- delete mode 100644 Text/.Shakespeare.hs.swp
-
-diff --git a/Text/.Shakespeare.hs.swp b/Text/.Shakespeare.hs.swp
-deleted file mode 100644
-index 4d6cd6a0295fdfb59f32a66b4af556c0630dd5b0..0000000000000000000000000000000000000000
-GIT binary patch
-literal 0
-HcmV?d00001
-
-literal 24576
-zcmeI4e~et$RmWd`KnqD)L_(BS5xTW4?M$;fu@g0M7u$*LtdmXsW9?l#wDxBEJo9Gf
-z#WU|s-h1QO^^dk7RGJp46wwy`NCj0Y(S!!1AgEe}NKk}8ErJRNG@z(KqJ@T13Q|#9
-zR6ghact2*x>kWSanvuTVnRm}U_uO;OJ@?*o&-2-xr{<5SdmDFqe16RHu3haOfAZ_E
-z_a3<Dd5^`xx;(zxXEhpJjYOBfM;P9j_4;?F9sgXA_5(i&W_C4pHtxQ2DOk(yTr3_p
-zI_Z{pPKYKNm}p=N8W?2lncX*eci**Z=k{%HQ8)ki$t_fxkW4f%(ZECl6Aer>Fwww7
-z0}~BQG%(S?|0fM({p-CS(4lL=qu?5g>-pOOzWx0}{5=c)#QwgHzc+z9s33JFpNR%0
-z8klHcqJfD9CK{M%V4{JE1|}MqXkem&i3TPb_}{AmzvX$m5$_9fi0A%aVgN6{(es`I
-zzX&dZcYzu3y*GH??}AT&_ks{CfP2BM;5zUML4hxWFM!X2XTa0o<KXAP`#=U#umonn
-zH*WO2=fM+T70iL#!MASkynh0}2c7~Kz&pX+;8ySx;0HhIc`t#lfM>xI;GN(`@b5q3
-zdEW+q1)c*R0v`lD@F2Ja+zkHk^`6%R`@wf#=Xt*dj)L33^FQo)>);_U2fj-n<a6LW
-zI1H`<&k-!?f&<__@MVG{?*jitQ04pJW$--sD0mzk0{4Uaz?;FV=w9^yS?~$)BrqSv
-zXIc#tzds+PL6U`Ww3zuxb|5I1l)qQ0R>Mfm&Z@;M38Pg{=v0;4eAEh}Oh1S2h`)X|
-zaMUe7^VK8erq$k&-{go$)yw+d5jmw@!>_`_lJ=8eE^Ye#V16}<li+X|1ybSk!H%CS
-zkEc1{cm1dtv_|MIDtH}?qw}aoiWc0j6lHn36ZxZz9uz+?z8R^!L6D)JD!<jDsVr8Z
-z7Em?gUJp&Bsy6I|&5lB`2jg}-2-0Q}_A_-h5M2+$tfPE2wSB5C%$sG3Vc6}ej^FQx
-z-F3$`>jZGhf}|gJeHq<!TKQ2+o%NgNvaoqBRl|7DZK)`h7F3o5euh}cN4tKXK@~x=
-zj-SyMeAcqYm`>%I3sW^nO}B(&sBOwLMuVwp$B8=cC!v3~8z{d^Yb`{L(y$e%RNGLh
-zAjzeZ#-zQ6{PbKv@6P+(K>$gF-lS_ukPf=ptg3Cl=wH?vSz7N0i$-HjKN78?4mw5;
-zOwXx?8hL_1s6wHyZrIeiQE^+iN`qM^PJ>+3lor~9s3{7pl~RjV=*x;<zo;6GhT8C4
-zo?4-7n<7!a>o-N7V6;={*;lR=J&F23q6JsMS|4#z5o|G5(pQD1n;kz|g;l(<X`y^z
-zAahc;gbmIxd|0s9tn|JeCTXU6aVu=EGZ5We7&ByIC`JuIuc4MY(i*a3A+4B+q^;16
-zW2(+Y@em_1L&6+d9r&w(wv#2g*-v6dyC;G~BDQorZ$(sI9o$(FFABs6RVQZXuo*-V
-zX()&zY+IMo9QvV9bG8F*hml#Vo1bq>OBq%sbz3nkM^ph9XCf`ziHH63zL|5=(x`Mn
-zie|KtTKTh}$2ewz>J3mMYOzdOnp9L#a8WHY5CQ66$6_DHg3T-nGbNrt&#s}ru6lkb
-z-IGZY_?REM327$~zo2`jJM~D%8MJ5<9Wdo_Co1*Z*bC;I#D23gt@Z4;&imBGN+6XP
-zsb?pa)=zw_xf#q#7j=VczBC0NJ;&&fxCMG<hDzqNIDv{wGOokv4>wcpwjF=k?Vx@c
-z^g<ZTs%&+3UJrw$)S$LeE#Tn*zu1%tuwxA4G%MM&bOEP(K8yz`>SLsbekfjS5M^Ok
-zH?374L@iuErXM8y2=x3&wR$SnL?fnCh0-rodOocRH)Fg?Oa~L?Y~R(#Rc*AYhUbaj
-zJH#lS%-XwEyU(K0?)iPSbht5y`r?;%U?+Y{iiHf4Y86%?dA{JY7|iTb^T*thiY9vT
-zdF>O*sg4J*ru&L!kDE3hKQV}?YT7D^lecwTmb-F8$G6r_-%qe!=~gm`7UW05uhYw(
-zDS)YZFmMG~d`_MAcP%rnbY(FfB+cNc-wWi|X$qI+%N)xdOf;{#Bw>R1GU}J40Wk>E
-zhFu)7@r2bxrYAG#wAq_1dl@T(;gHBGEmfMfKLwFyx_@g7Jtk+&o?vku7t?DjBylrH
-zS-)lI><_&p$@IeQU{lTmv$Hi-B`LKrI#RCi@qynB+aZSh06V3IrakOmz+b1B$|h8r
-zV9^m+@#c>;PDbJ*RBfRDE*S4Qf2{5(bu&leC=OedM|sPQ1B0;3yiqm#Wm>h9xF_Xx
-zZ#z>eY`cnw-7;Xkdt>RL#^O4@Xst0X`;o}+rr!3jt=@8E{^-i7xf6@?$BwQzzq-;f
-z3x4gc>D|*ia{;f+bdzRP4WBr-DUaiW7-Oj&ANXmgzth7;qn_8%3NRMKFo!)=Gb<-s
-z<t&)Cwls!1IT-iOhLNAeN!qX$*9lv)EZ1a5I&BQia!7IxdLU${s%l}nzuWKlM+d!W
-zoZlkeA*hla4q1U}dXGoGGe%uEd*-?tGGzicEbOA$=wpV=XVfpMZv}0&G`G04GWXL9
-z$4)GnYEBlrMScJlZTtO{pNQMDzfNcmdNS$S-=*!(Nw$FVvh5e^O;Sz3#Cogh#>1H|
-z>!7QH1U~z>(gauxvJCZ@I>=JqYwIzwtyQ-C<$}BhN?`~!c}<OJ!4xx&101X#;1ZE>
-zE{B-7?AFeS8}V5SGZd#He3NYVwAbM~&%z7LQMb8*_TfP{9Hb5J;>>n+Y+(t*UR-(b
-zp@V9s9mO+4KZ$0-NEVnbm1p|Cu#Hl+edh8eHF{y1qL>*p+HDoYhxZ?S@Z|mn=hTUy
-z87Hkrn4SmyWE{c4g@wF{yw;&^uokjAn`f6KXP+^Q@zg<rBchK-gP}N4Y$7}_HtZzM
-z*)7>^k=xM;ft>&Uh%@+2oZaR8&sXp3ob|s5J`T=;IZy}Jf|sECb?^k}fd_!py%9`4
-z6Aer>Fwww70}~BQG%(S?L<18IOf)djz(fQ8M>L>HpA`x01v;3wgBy%^s9NfdJJhyW
-zx$X#>62P5160U{OHhqY9H6NCUd(D)nUR{{<h?Yt?cPb}rO8C4R$L9upxHemy;C0z*
-ztZE149xKXVty*=pH?JcNY(*wQ9)xoIUR5lq?P6g%q^bo{1J(DW$bGEzjt8+gf--gK
-zh381NAbVc@f7*en?1fNjpcOi{BgAiCn}|lea{hl4=J_SLbLRXnIsbpdIsdo8hruei
-z54;`h2CoDE%31$a@D1?K;Pc>9;KN`YoCT5>um`*e{2M`qFM*!{_kdf#8^BHACGPou
-z1AGkp97w=%@HTKOxCPt{zQ$euv*118GB^YFfZM@$xa)rryZ}B0o&uM^Nw5TN0sqN8
-z|I6S>@KMkK?*O-gf8gH#x4_dN0Y|_bxB<LO4!|eD$G{Qbfp3uq@B;WCcmmuHzDXXy
-zzkpZ4?|}D%E_esH9lSzbz_XwO_JZrdSFb~N;Aepk-VDA;KEOYM-v<{!1m?l_7@t1_
-zGEQHVu^Rhv7Ql6d1TeYLC6+#jy83&A8>~K08cP4p&4sIOn+8zRrWWd)0Op?18#c8w
-zQbi`SDO7v*X(n~$Lc(LX9p%<V;!t}>iA>~EWHsD^mWxa&Bf&6~)(g3Ij7?e?hPu%W
-zJjS+Lv?=YnPo3y<t3~8ARlQ*-7s_1O$<;&4geD!G`Fo<cIglHup4`;?$!aQkDcvem
-z%DgHI`8D4%6|zARDODoi;!odquU7?nx7<FxTh+AZF}D<%^Oyy9Beo10BwU!Q)g&JD
-zO{BJ<(mmwjM{Yau!HN7XNl*}0zY)NefN^P{P}evWRjaAdksmEC|E}pC;QkRUs|Ju|
-zY>17Q8zeZZYNm_RrW;~1!6FNlzJW^d@|vON+Tb$7Tv6&MeJ+{YH%2H#kA|~m6?9V*
-zNmqo6S<z_y{#q$`?S^56HAz%atPsxnv`ti)YDx4U!p-zk-}kfl@xTQB$A-c$lBiI~
-zySGHmU0o?G?xOQzUgla&z7^Mx<_badVN}fx#uQ3J6j^ak_(Nq)4a;8NrD_q$1jo3d
-z!${<|V_FT8uKB`!hJ0BrMnrSu>PQ#{<~p#%*M5~n-8SLqaRHiDA)Cn8G$OH(sv5V#
-zOUWRR;k9gv_0<z%_Zg{lh%2m-TB_waV)CH${fqmp<$>{d`Ae+J@{4=}qZ2iCU$MW@
-z%$UUEnb}@YUQvepwwkt5j*(C^-E(Q589^;?{!42=|0UyNB+}B@M#q|qwlA~Os?c89
-zx)#JoCT=_s*N9rKoibj=jvCh7%$RyrqOG=Jyp&dq+|7_#l-e$FrMot}F6ObOX2thb
-z3)ihO#i&M#cDN3R>DSg|dkddgb>Rxl*an4qZMO7def9#)kFRuk8Nuw{Y=Z!FKJNrG
-z)qRIkG4vZM?HK3fRPH@xDyJ$*>nc^L*EC8$#5J(>2&`}n&6t7}wQZY`bz`L~k5b`h
-zPFwMpJ+JJBb9YcPhY88ViidT@C3cyN7B*%PG{t{4Nf?#f0H+<1F>gxo;b>tlylUe8
-zr`6o!g<Fzx@(?V&_@Cm+RF_rCnNL`@-@6*orsXn^O(QMIptMaRwf!dMW3*;FR`THD
-zO`yy#Z}o3<VDIydBC4f(IiyetqT>THn6&(I>#27oON%-$p>8UU5}?SMrNGBpQikuc
-zCzsLY4*d}K<K0t|*N0qoZPUfoHLP0p7)vH<z#$cxja1hjSy#4BpJ!8#ij&Hh7I|{N
-zaa-0G%9HI=-j(m7At-4uUjr|0R%N_Bn>9#!uau<f1b)Q+wLR$Cb8ru*L$VfE$Ckom
-zSdoS0vMR|XvDt&#WVvjX%qkAd;;$sPk3^<U(Cy<H&yk%*=Bs1%sM=3@ryr%T=$Sk@
-zo%+Zzn>xa!EhACl)lf%Bv|=O3jF)t>(74Dk14nO7ChpvtIqvFA1I*D~isu9iZex;Z
-zxu(_Fk%as}9J?%mK{O;uSaOjH_8XsMu}e;=5IRHPp)6RoRSa5w3D5lLMYlNSPxbT~
-zH}qo-g7Z>kv#s3c5*zZ7JYhXlG7a-gA-A8()0MQO##BZUpZAlox_+=L3986%XSy^t
-zj_!a?8{U*|j#I{_1f;nn*%lgH3|M+4*+rH3$@!lny7#o4DLMb2<<DPo#$N-sfxn>e
-z&%v|cBj8bR8~6@q_s@Y}1-}B;z%rNyH-OJ@X8#57UJ!s5m<BI#UjGXCG<X8+15@A)
-z;3jYlc$xG1AAny5LvRSpft}!1@O{qguYk{h$3O`7fWPOw{&zs~`9BHX4^D&K;9hVo
-z_+!rRAFyZnDgM65+5NA<=fN}JLm&e^&;|E^w}BhMw>iiEDR>HGK=S|PeE(MPM(`qM
-z`ric4fEDm|@HNi#zXU!4?ganAS^jUq3*ZCbeV_^M0Y3?@1z%+>WIR4CW0HTwgxqH<
-zfv|-x`Kn_hNxDR_LtxP;PJdenY{}A=$FxepI$6?SN1mijH{<ZddZKeBO#=|iWH!4I
-zY1gf2<*klAgzd<WuzbU_P<IELH+@JM*~oaJkW}r_dHnVSB^#W~coP0fnViifPtxXd
-zdTH_BOp;@ng=8~Qi9}B#kv3FGUq;gKkf9Zit15G|V3@Bz^ikS$NuZ}|dQUK|&>?<O
-z7WTT%oh;RrhrAh6FdNC#QmIY9LOS%pA^(V|Cy=!^C9JbiN3OzVOs_1z@m(@nW$7i!
-ztiCKMSWOfw>0m0=DV8ZAAy&2ZAdN}1mOL_@WPFL;5c`0h1d!~z6GieF@e{jxo?X|g
-z+-i89<G4GAvoA;kS%6s;t0zPm_)9hdt=RbG|DUMVtS80g52PpE=1%rY(_^<jBl|`e
-zn0k6(^m0>-9%C?PCXzE{&yB=r44bw%#GYEx;c`?rN|#F}bITFChvVt>G%S&hp>mVe
-zQE6dIbapZ_cQ0O+W(&EhGj+_^o8^)Q#1^P~YRPEg65o&;t?9pJFD*ZG&pnsyD2aDR
-zkIf%FJb!eKvtjexl+INflWw|})pky+UAv~$U3CtQLb=y@7W-SwSHGGfc4{}VRa2=(
-zGisZJGvoxwdCR=$!*}!UPfDh#vn5v0G|)%ug3wZx?kY5uK8{PMO)~#ZgsUCiKH9T~
-z{=$JWE41AJRU1Hu($TS1DYI1vSBX4~t<Ip?>gP>Vr`j^bQ{t&>jNO<7?7G{}<h2x1
-z>L}L^GBEY)W==6B601}3#WEPUQX5)|f}sSMOQePggeLaXEY>HZdNVpwNi`+JfKOKT
-zW0~=A+nMAHOJ816)<n$=MVcit*-DARs&)pI=wlOwv+}*J_U)5|aoa)Bm<dnH3R4(G
-zh5g~6o#|qwM^IOVx)4UBHGPo?jYJkVynr_H%)P&r_orY{QpZRots<g98!KtU99yF8
-zZfuFRi*kv)45Mv?Z2fBAa&?(`ad4JbROAIR=F@5WXt^TP3ZvbW?Y=Fo6xzxgEax?{
-z(yz+}EiJKYr))hY-jcU$`%q)xrWwp)s5x*U3JzT7mgn?JZ&Yd-ZxA)it9iDq`snz&
-zvDE4)lvrqlCfz*QCHtOE%zHp;hi=MF0UaUN$02Kt#j#D9Se{Ia4K=DUb#v3QB9oxP
-zwzU1w@6WNRu*bx!Fm!?M5q`vZteUtpl5-)+%;rs24mL%JOcA9&qh!VLrXZ-fOO729
-zKPK3rQ|qhji{p;jMqasN`rfA);}JIIeOp|cZr)uN8TD0FD!Q+0X5s+sdf+Oou)><h
-z@^6Kg)7(m_yy$C1XT{;NAb4%c(0;9`ypg*;l3D_HPgH9qao@bzRy$*&a%wMunV*_c
-zmoB*%A5@d;G*^Q@+GSJ180JQ6>pIJ;jMG|PctyQ!GSmbiv3Qr)u&ouEmum^pkkc@$
-zw#m&VrMmx{u&J%gPF<Xum0rTGOo$t96J~@>TffSIcHAo>@*W5;6-uS6@+S&5%ay{F
-cT45AdikYcun%oMsfwvWjb+Ig{u-NAPH%ay)TmS$7
+ Text/Shakespeare.hs | 3 +++
+ 1 file changed, 3 insertions(+)
diff --git a/Text/Shakespeare.hs b/Text/Shakespeare.hs
-index d300951..fabbf66 100644
+index 9eb06a2..1290ab1 100644
--- a/Text/Shakespeare.hs
+++ b/Text/Shakespeare.hs
-@@ -22,6 +22,8 @@ module Text.Shakespeare
+@@ -23,6 +23,9 @@ module Text.Shakespeare
+ , Deref
+ , Parser
+
++ -- used by TH
++ , pack'
++
#ifdef TEST_EXPORT
, preFilter
#endif
-+ -- used by TH splices
-+ , pack'
- ) where
-
- import Data.List (intersperse)
--
-1.8.2.rc3
+1.7.10.4
diff --git a/standalone/android/haskell-patches/shakespeare_1.0.3_0001-remove-TH.patch b/standalone/android/haskell-patches/shakespeare_1.0.3_0001-remove-TH.patch
deleted file mode 100644
index 5a5b8eeb8..000000000
--- a/standalone/android/haskell-patches/shakespeare_1.0.3_0001-remove-TH.patch
+++ /dev/null
@@ -1,208 +0,0 @@
-From 10484c5f68431349b249f07517c392c4a90bdb05 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Wed, 8 May 2013 01:47:19 -0400
-Subject: [PATCH] remove TH
-
----
- Text/Shakespeare.hs | 109 ----------------------------------------------
- Text/Shakespeare/Base.hs | 28 ------------
- shakespeare.cabal | 2 +-
- 3 files changed, 1 insertion(+), 138 deletions(-)
-
-diff --git a/Text/Shakespeare.hs b/Text/Shakespeare.hs
-index 7750135..fabbf66 100644
---- a/Text/Shakespeare.hs
-+++ b/Text/Shakespeare.hs
-@@ -12,11 +12,7 @@ module Text.Shakespeare
- , WrapInsertion (..)
- , PreConversion (..)
- , defaultShakespeareSettings
-- , shakespeare
-- , shakespeareFile
-- , shakespeareFileReload
- -- * low-level
-- , shakespeareFromString
- , shakespeareUsedIdentifiers
- , RenderUrl
- , VarType
-@@ -135,39 +131,6 @@ defaultShakespeareSettings = ShakespeareSettings {
- , modifyFinalValue = Nothing
- }
-
--instance Lift PreConvert where
-- lift (PreConvert convert ignore comment wrapInsertion) =
-- [|PreConvert $(lift convert) $(lift ignore) $(lift comment) $(lift wrapInsertion)|]
--
--instance Lift WrapInsertion where
-- lift (WrapInsertion indent sb sep sc e ab ac) =
-- [|WrapInsertion $(lift indent) $(lift sb) $(lift sep) $(lift sc) $(lift e) $(lift ab) $(lift ac)|]
--
--instance Lift PreConversion where
-- lift (ReadProcess command args) =
-- [|ReadProcess $(lift command) $(lift args)|]
-- lift Id = [|Id|]
--
--instance Lift ShakespeareSettings where
-- lift (ShakespeareSettings x1 x2 x3 x4 x5 x6 x7 x8 x9) =
-- [|ShakespeareSettings
-- $(lift x1) $(lift x2) $(lift x3)
-- $(liftExp x4) $(liftExp x5) $(liftExp x6) $(lift x7) $(lift x8) $(liftMExp x9)|]
-- where
-- liftExp (VarE n) = [|VarE $(liftName n)|]
-- liftExp (ConE n) = [|ConE $(liftName n)|]
-- liftExp _ = error "liftExp only supports VarE and ConE"
-- liftMExp Nothing = [|Nothing|]
-- liftMExp (Just e) = [|Just|] `appE` liftExp e
-- liftName (Name (OccName a) b) = [|Name (OccName $(lift a)) $(liftFlavour b)|]
-- liftFlavour NameS = [|NameS|]
-- liftFlavour (NameQ (ModName a)) = [|NameQ (ModName $(lift a))|]
-- liftFlavour (NameU _) = error "liftFlavour NameU" -- [|NameU $(lift $ fromIntegral a)|]
-- liftFlavour (NameL _) = error "liftFlavour NameL" -- [|NameU $(lift $ fromIntegral a)|]
-- liftFlavour (NameG ns (PkgName p) (ModName m)) = [|NameG $(liftNS ns) (PkgName $(lift p)) (ModName $(lift m))|]
-- liftNS VarName = [|VarName|]
-- liftNS DataName = [|DataName|]
--
- type QueryParameters = [(TS.Text, TS.Text)]
- type RenderUrl url = (url -> QueryParameters -> TS.Text)
- type Shakespeare url = RenderUrl url -> Builder
-@@ -302,54 +265,6 @@ pack' = TS.pack
- {-# NOINLINE pack' #-}
- #endif
-
--contentsToShakespeare :: ShakespeareSettings -> [Content] -> Q Exp
--contentsToShakespeare rs a = do
-- r <- newName "_render"
-- c <- mapM (contentToBuilder r) a
-- compiledTemplate <- case c of
-- -- Make sure we convert this mempty using toBuilder to pin down the
-- -- type appropriately
-- [] -> fmap (AppE $ wrap rs) [|mempty|]
-- [x] -> return x
-- _ -> do
-- mc <- [|mconcat|]
-- return $ mc `AppE` ListE c
-- fmap (maybe id AppE $ modifyFinalValue rs) $
-- if justVarInterpolation rs
-- then return compiledTemplate
-- else return $ LamE [VarP r] compiledTemplate
-- where
-- contentToBuilder :: Name -> Content -> Q Exp
-- contentToBuilder _ (ContentRaw s') = do
-- ts <- [|fromText . pack'|]
-- return $ wrap rs `AppE` (ts `AppE` LitE (StringL s'))
-- contentToBuilder _ (ContentVar d) =
-- return $ wrap rs `AppE` (toBuilder rs `AppE` derefToExp [] d)
-- contentToBuilder r (ContentUrl d) = do
-- ts <- [|fromText|]
-- return $ wrap rs `AppE` (ts `AppE` (VarE r `AppE` derefToExp [] d `AppE` ListE []))
-- contentToBuilder r (ContentUrlParam d) = do
-- ts <- [|fromText|]
-- up <- [|\r' (u, p) -> r' u p|]
-- return $ wrap rs `AppE` (ts `AppE` (up `AppE` VarE r `AppE` derefToExp [] d))
-- contentToBuilder r (ContentMix d) =
-- return $ derefToExp [] d `AppE` VarE r
--
--shakespeare :: ShakespeareSettings -> QuasiQuoter
--shakespeare r = QuasiQuoter { quoteExp = shakespeareFromString r }
--
--shakespeareFromString :: ShakespeareSettings -> String -> Q Exp
--shakespeareFromString r str = do
-- s <- qRunIO $ preFilter r str
-- contentsToShakespeare r $ contentFromString r s
--
--shakespeareFile :: ShakespeareSettings -> FilePath -> Q Exp
--shakespeareFile r fp = do
--#ifdef GHC_7_4
-- qAddDependentFile fp
--#endif
-- readFileQ fp >>= shakespeareFromString r
--
- data VarType = VTPlain | VTUrl | VTUrlParam | VTMixin
-
- getVars :: Content -> [(Deref, VarType)]
-@@ -369,30 +284,6 @@ data VarExp url = EPlain Builder
- shakespeareUsedIdentifiers :: ShakespeareSettings -> String -> [(Deref, VarType)]
- shakespeareUsedIdentifiers settings = concatMap getVars . contentFromString settings
-
--shakespeareFileReload :: ShakespeareSettings -> FilePath -> Q Exp
--shakespeareFileReload rs fp = do
-- str <- readFileQ fp
-- s <- qRunIO $ preFilter rs str
-- let b = shakespeareUsedIdentifiers rs s
-- c <- mapM vtToExp b
-- rt <- [|shakespeareRuntime|]
-- wrap' <- [|\x -> $(return $ wrap rs) . x|]
-- r' <- lift rs
-- return $ wrap' `AppE` (rt `AppE` r' `AppE` (LitE $ StringL fp) `AppE` ListE c)
-- where
-- vtToExp :: (Deref, VarType) -> Q Exp
-- vtToExp (d, vt) = do
-- d' <- lift d
-- c' <- c vt
-- return $ TupE [d', c' `AppE` derefToExp [] d]
-- where
-- c :: VarType -> Q Exp
-- c VTPlain = [|EPlain . $(return $ toBuilder rs)|]
-- c VTUrl = [|EUrl|]
-- c VTUrlParam = [|EUrlParam|]
-- c VTMixin = [|\x -> EMixin $ \r -> $(return $ unwrap rs) $ x r|]
--
--
- shakespeareRuntime :: ShakespeareSettings -> FilePath -> [(Deref, VarExp url)] -> Shakespeare url
- shakespeareRuntime rs fp cd render' = unsafePerformIO $ do
- str <- readFileUtf8 fp
-diff --git a/Text/Shakespeare/Base.hs b/Text/Shakespeare/Base.hs
-index 7c96898..ef769b1 100644
---- a/Text/Shakespeare/Base.hs
-+++ b/Text/Shakespeare/Base.hs
-@@ -52,34 +52,6 @@ data Deref = DerefModulesIdent [String] Ident
- | DerefTuple [Deref]
- deriving (Show, Eq, Read, Data, Typeable, Ord)
-
--instance Lift Ident where
-- lift (Ident s) = [|Ident|] `appE` lift s
--instance Lift Deref where
-- lift (DerefModulesIdent v s) = do
-- dl <- [|DerefModulesIdent|]
-- v' <- lift v
-- s' <- lift s
-- return $ dl `AppE` v' `AppE` s'
-- lift (DerefIdent s) = do
-- dl <- [|DerefIdent|]
-- s' <- lift s
-- return $ dl `AppE` s'
-- lift (DerefBranch x y) = do
-- x' <- lift x
-- y' <- lift y
-- db <- [|DerefBranch|]
-- return $ db `AppE` x' `AppE` y'
-- lift (DerefIntegral i) = [|DerefIntegral|] `appE` lift i
-- lift (DerefRational r) = do
-- n <- lift $ numerator r
-- d <- lift $ denominator r
-- per <- [|(%) :: Int -> Int -> Ratio Int|]
-- dr <- [|DerefRational|]
-- return $ dr `AppE` InfixE (Just n) per (Just d)
-- lift (DerefString s) = [|DerefString|] `appE` lift s
-- lift (DerefList x) = [|DerefList $(lift x)|]
-- lift (DerefTuple x) = [|DerefTuple $(lift x)|]
--
- derefParens, derefCurlyBrackets :: UserParser a Deref
- derefParens = between (char '(') (char ')') parseDeref
- derefCurlyBrackets = between (char '{') (char '}') parseDeref
-diff --git a/shakespeare.cabal b/shakespeare.cabal
-index 01c8d5d..0fff966 100644
---- a/shakespeare.cabal
-+++ b/shakespeare.cabal
-@@ -27,7 +27,7 @@ library
- , template-haskell
- , parsec >= 2 && < 4
- , text >= 0.7 && < 0.12
-- , process >= 1.0 && < 1.2
-+ , process >= 1.0 && < 1.3
-
- exposed-modules:
- Text.Shakespeare
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/skein_hardcode_little-endian.patch b/standalone/android/haskell-patches/skein_hardcode_little-endian.patch
new file mode 100644
index 000000000..788d8e521
--- /dev/null
+++ b/standalone/android/haskell-patches/skein_hardcode_little-endian.patch
@@ -0,0 +1,24 @@
+From 3a04b41ffce4e4e87b0fedd3a1e3434a3f06cc76 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 00:18:12 +0000
+Subject: [PATCH] hardcode little endian
+
+---
+ c_impl/optimized/skein_port.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/c_impl/optimized/skein_port.h b/c_impl/optimized/skein_port.h
+index a2d0fc2..6929bb0 100644
+--- a/c_impl/optimized/skein_port.h
++++ b/c_impl/optimized/skein_port.h
+@@ -45,6 +45,7 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */
+ * platform-specific code instead (e.g., for big-endian CPUs).
+ *
+ */
++#define SKEIN_NEED_SWAP (0)
+ #ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */
+
+ #include "brg_endian.h" /* get endianness selection */
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/socks_0.4.2_0001-remove-IPv6-stuff.patch b/standalone/android/haskell-patches/socks_0.4.2_0001-remove-IPv6-stuff.patch
index 5a343d875..c9723f3f7 100644
--- a/standalone/android/haskell-patches/socks_0.4.2_0001-remove-IPv6-stuff.patch
+++ b/standalone/android/haskell-patches/socks_0.4.2_0001-remove-IPv6-stuff.patch
@@ -1,43 +1,29 @@
-From abab0f8202998a3e88c5dc5f67a8245da6c174b3 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:36:20 -0400
-Subject: [PATCH] remove IPv6 stuff
+From e1a2f80f6bec25921ab645a0aaf1c6422a8917ab Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Mon, 11 Nov 2013 01:06:58 +0000
+Subject: [PATCH] fix
---
- Network/Socks5.hs | 1 -
- Network/Socks5/Command.hs | 16 ++--------------
- Network/Socks5/Types.hs | 3 +--
- Network/Socks5/Wire.hs | 2 --
- 4 files changed, 3 insertions(+), 19 deletions(-)
+ Network/Socks5/Command.hs | 8 +-------
+ Network/Socks5/Conf.hs | 1 -
+ Network/Socks5/Lowlevel.hs | 1 -
+ Network/Socks5/Types.hs | 18 +-----------------
+ Network/Socks5/Wire.hs | 2 --
+ 5 files changed, 2 insertions(+), 28 deletions(-)
-diff --git a/Network/Socks5.hs b/Network/Socks5.hs
-index 67b0060..80efb9c 100644
---- a/Network/Socks5.hs
-+++ b/Network/Socks5.hs
-@@ -54,7 +54,6 @@ socksConnectAddr :: Socket -> SockAddr -> SockAddr -> IO ()
- socksConnectAddr sock sockserver destaddr = withSocks sock sockserver $ do
- case destaddr of
- SockAddrInet p h -> socks5ConnectIPV4 sock h p >> return ()
-- SockAddrInet6 p _ h _ -> socks5ConnectIPV6 sock h p >> return ()
- _ -> error "unsupported unix sockaddr type"
-
- -- | connect a new socket to the socks server, and connect the stream to a FQDN
diff --git a/Network/Socks5/Command.hs b/Network/Socks5/Command.hs
-index 2952706..db994c9 100644
+index db95fbd..fdba5ec 100644
--- a/Network/Socks5/Command.hs
+++ b/Network/Socks5/Command.hs
-@@ -9,9 +9,8 @@
- --
- module Network.Socks5.Command
- ( socks5Establish
-- , socks5ConnectIPV4
-- , socks5ConnectIPV6
- , socks5ConnectDomainName
-+ , socks5ConnectIPV4
- -- * lowlevel interface
- , socks5Rpc
- ) where
-@@ -23,7 +22,7 @@ import qualified Data.ByteString as B
+@@ -13,7 +13,6 @@ module Network.Socks5.Command
+ , Connect(..)
+ , Command(..)
+ , connectIPV4
+- , connectIPV6
+ , connectDomainName
+ -- * lowlevel interface
+ , rpc
+@@ -29,7 +28,7 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import Data.Serialize
@@ -46,54 +32,96 @@ index 2952706..db994c9 100644
import Network.Socket.ByteString
import Network.Socks5.Types
-@@ -46,17 +45,6 @@ socks5ConnectIPV4 socket hostaddr port = onReply <$> socks5Rpc socket request
- onReply (SocksAddrIPV4 h, p) = (h, p)
- onReply _ = error "ipv4 requested, got something different"
+@@ -65,11 +64,6 @@ connectIPV4 socket hostaddr port = onReply <$> rpc_ socket (Connect $ SocksAddre
+ where onReply (SocksAddrIPV4 h, p) = (h, p)
+ onReply _ = error "ipv4 requested, got something different"
--socks5ConnectIPV6 :: Socket -> HostAddress6 -> PortNumber -> IO (HostAddress6, PortNumber)
--socks5ConnectIPV6 socket hostaddr6 port = onReply <$> socks5Rpc socket request
-- where
-- request = SocksRequest
-- { requestCommand = SocksCommandConnect
-- , requestDstAddr = SocksAddrIPV6 hostaddr6
-- , requestDstPort = fromIntegral port
-- }
-- onReply (SocksAddrIPV6 h, p) = (h, p)
-- onReply _ = error "ipv6 requested, got something different"
+-connectIPV6 :: Socket -> HostAddress6 -> PortNumber -> IO (HostAddress6, PortNumber)
+-connectIPV6 socket hostaddr6 port = onReply <$> rpc_ socket (Connect $ SocksAddress (SocksAddrIPV6 hostaddr6) port)
+- where onReply (SocksAddrIPV6 h, p) = (h, p)
+- onReply _ = error "ipv6 requested, got something different"
-
-- TODO: FQDN should only be ascii, maybe putting a "fqdn" data type
-- in front to make sure and make the BC.pack safe.
- socks5ConnectDomainName :: Socket -> String -> PortNumber -> IO (SocksAddr, PortNumber)
+ connectDomainName :: Socket -> String -> PortNumber -> IO (SocksHostAddress, PortNumber)
+diff --git a/Network/Socks5/Conf.hs b/Network/Socks5/Conf.hs
+index c29ff7b..007d382 100644
+--- a/Network/Socks5/Conf.hs
++++ b/Network/Socks5/Conf.hs
+@@ -47,5 +47,4 @@ defaultSocksConfFromSockAddr sockaddr = SocksConf server SocksVer5
+ where server = SocksAddress haddr port
+ (haddr,port) = case sockaddr of
+ SockAddrInet p h -> (SocksAddrIPV4 h, p)
+- SockAddrInet6 p _ h _ -> (SocksAddrIPV6 h, p)
+ _ -> error "unsupported unix sockaddr type"
+diff --git a/Network/Socks5/Lowlevel.hs b/Network/Socks5/Lowlevel.hs
+index c10d9b9..2c3d59c 100644
+--- a/Network/Socks5/Lowlevel.hs
++++ b/Network/Socks5/Lowlevel.hs
+@@ -17,7 +17,6 @@ resolveToSockAddr :: SocksAddress -> IO SockAddr
+ resolveToSockAddr (SocksAddress sockHostAddr port) =
+ case sockHostAddr of
+ SocksAddrIPV4 ha -> return $ SockAddrInet port ha
+- SocksAddrIPV6 ha6 -> return $ SockAddrInet6 port 0 ha6 0
+ SocksAddrDomainName bs -> do he <- getHostByName (BC.unpack bs)
+ return $ SockAddrInet port (hostAddress he)
+
diff --git a/Network/Socks5/Types.hs b/Network/Socks5/Types.hs
-index 5dc7d5e..12dea99 100644
+index 7fbec25..17c7c83 100644
--- a/Network/Socks5/Types.hs
+++ b/Network/Socks5/Types.hs
-@@ -17,7 +17,7 @@ module Network.Socks5.Types
+@@ -19,7 +19,7 @@ module Network.Socks5.Types
import Data.ByteString (ByteString)
import Data.Word
import Data.Data
--import Network.Socket (HostAddress, HostAddress6)
-+import Network.Socket (HostAddress)
+-import Network.Socket (HostAddress, HostAddress6, PortNumber)
++import Network.Socket (HostAddress, PortNumber)
import Control.Exception
+ import qualified Data.ByteString.Char8 as BC
+ import Numeric (showHex)
+@@ -53,12 +53,10 @@ data SocksMethod =
+ data SocksHostAddress =
+ SocksAddrIPV4 !HostAddress
+ | SocksAddrDomainName !ByteString
+- | SocksAddrIPV6 !HostAddress6
+ deriving (Eq,Ord)
- data SocksCommand =
-@@ -38,7 +38,6 @@ data SocksMethod =
- data SocksAddr =
- SocksAddrIPV4 HostAddress
- | SocksAddrDomainName ByteString
-- | SocksAddrIPV6 HostAddress6
- deriving (Show,Eq)
+ instance Show SocksHostAddress where
+ show (SocksAddrIPV4 ha) = "SocksAddrIPV4(" ++ showHostAddress ha ++ ")"
+- show (SocksAddrIPV6 ha6) = "SocksAddrIPV6(" ++ showHostAddress6 ha6 ++ ")"
+ show (SocksAddrDomainName dn) = "SocksAddrDomainName(" ++ BC.unpack dn ++ ")"
- data SocksReply =
+ -- | Converts a HostAddress to a String in dot-decimal notation
+@@ -69,20 +67,6 @@ showHostAddress num = concat [show q1, ".", show q2, ".", show q3, ".", show q4]
+ (num''',q3) = num'' `quotRem` 256
+ (_,q4) = num''' `quotRem` 256
+
+--- | Converts a IPv6 HostAddress6 to standard hex notation
+-showHostAddress6 :: HostAddress6 -> String
+-showHostAddress6 (a,b,c,d) =
+- (concat . intersperse ":" . map (flip showHex ""))
+- [p1,p2,p3,p4,p5,p6,p7,p8]
+- where (a',p2) = a `quotRem` 65536
+- (_,p1) = a' `quotRem` 65536
+- (b',p4) = b `quotRem` 65536
+- (_,p3) = b' `quotRem` 65536
+- (c',p6) = c `quotRem` 65536
+- (_,p5) = c' `quotRem` 65536
+- (d',p8) = d `quotRem` 65536
+- (_,p7) = d' `quotRem` 65536
+-
+ -- | Describe a Socket address on the SOCKS protocol
+ data SocksAddress = SocksAddress !SocksHostAddress !PortNumber
+ deriving (Show,Eq,Ord)
diff --git a/Network/Socks5/Wire.hs b/Network/Socks5/Wire.hs
-index 2cfed52..d3bd9c5 100644
+index 10bd262..a30f32e 100644
--- a/Network/Socks5/Wire.hs
+++ b/Network/Socks5/Wire.hs
-@@ -41,12 +41,10 @@ data SocksResponse = SocksResponse
+@@ -46,12 +46,10 @@ data SocksResponse = SocksResponse
- getAddr 1 = SocksAddrIPV4 <$> getWord32be
+ getAddr 1 = SocksAddrIPV4 <$> getWord32host
getAddr 3 = SocksAddrDomainName <$> (getWord8 >>= getByteString . fromIntegral)
--getAddr 4 = SocksAddrIPV6 <$> (liftM4 (,,,) getWord32le getWord32le getWord32le getWord32le)
+-getAddr 4 = SocksAddrIPV6 <$> (liftM4 (,,,) getWord32host getWord32host getWord32host getWord32host)
getAddr n = error ("cannot get unknown socket address type: " ++ show n)
putAddr (SocksAddrIPV4 h) = putWord8 1 >> putWord32host h
@@ -101,7 +129,7 @@ index 2cfed52..d3bd9c5 100644
-putAddr (SocksAddrIPV6 (a,b,c,d)) = putWord8 4 >> mapM_ putWord32host [a,b,c,d]
getSocksRequest 5 = do
- cmd <- toEnum . fromIntegral <$> getWord8
+ cmd <- toEnum . fromIntegral <$> getWord8
--
1.7.10.4
diff --git a/standalone/android/haskell-patches/split_0.2.1.2_0001-modify-to-build-with-unreleased-ghc.patch b/standalone/android/haskell-patches/split_0.2.1.2_0001-modify-to-build-with-unreleased-ghc.patch
deleted file mode 100644
index 472ccd678..000000000
--- a/standalone/android/haskell-patches/split_0.2.1.2_0001-modify-to-build-with-unreleased-ghc.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 2feaef797641587a3da83753ee17d20e712c79cf Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:36:30 -0400
-Subject: [PATCH] modify to build with unreleased ghc
-
----
- split.cabal | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/split.cabal b/split.cabal
-index 2183c3e..29b9b32 100644
---- a/split.cabal
-+++ b/split.cabal
-@@ -51,7 +51,7 @@ Source-repository head
-
- Library
- ghc-options: -Wall
-- build-depends: base <4.7
-+ build-depends: base <4.8
- exposed-modules: Data.List.Split, Data.List.Split.Internals
- default-language: Haskell2010
- Hs-source-dirs: src
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/stm-chans_cross-build.patch b/standalone/android/haskell-patches/stm-chans_cross-build.patch
new file mode 100644
index 000000000..f0964d693
--- /dev/null
+++ b/standalone/android/haskell-patches/stm-chans_cross-build.patch
@@ -0,0 +1,25 @@
+From c1b166ad1dbed80f7eed7b9c1b2dc5c668eeb8fc Mon Sep 17 00:00:00 2001
+From: androidbuilder <androidbuilder@example.com>
+Date: Fri, 18 Oct 2013 23:28:56 +0000
+Subject: [PATCH] cross build
+
+---
+ stm-chans.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/stm-chans.cabal b/stm-chans.cabal
+index 89d4780..2119a74 100644
+--- a/stm-chans.cabal
++++ b/stm-chans.cabal
+@@ -6,7 +6,7 @@
+ -- and source-repository:.
+ Cabal-Version: >= 1.6
+ -- We need a custom build in order to define __HADDOCK__
+-Build-Type: Custom
++Build-Type: Simple
+
+ Name: stm-chans
+ Version: 3.0.0
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/syb_0.3.7_0001-hack-for-cross-compiling.patch b/standalone/android/haskell-patches/syb_0.3.7_0001-hack-for-cross-compiling.patch
deleted file mode 100644
index e18d6127f..000000000
--- a/standalone/android/haskell-patches/syb_0.3.7_0001-hack-for-cross-compiling.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From c40fe2c484096c5de4cac8ca14a0ca5d892999f7 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:36:43 -0400
-Subject: [PATCH] hack for cross-compiling
-
----
- syb.cabal | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/syb.cabal b/syb.cabal
-index 0aee93d..0a645c6 100644
---- a/syb.cabal
-+++ b/syb.cabal
-@@ -17,7 +17,7 @@ description:
-
- category: Generics
- stability: provisional
--build-type: Custom
-+build-type: Simple
- cabal-version: >= 1.6
-
- extra-source-files: tests/*.hs,
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/unix-time_0.1.4_0001-hacks-for-android.patch b/standalone/android/haskell-patches/unix-time_0.1.4_0001-hacks-for-android.patch
deleted file mode 100644
index cff7e76e3..000000000
--- a/standalone/android/haskell-patches/unix-time_0.1.4_0001-hacks-for-android.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 4023b952871ad2bc248db887716d06932ac0dbb9 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Wed, 8 May 2013 14:00:19 -0400
-Subject: [PATCH] hacks for android
-
----
- cbits/conv.c | 4 +---
- unix-time.cabal | 28 ++--------------------------
- 2 files changed, 3 insertions(+), 29 deletions(-)
-
-diff --git a/cbits/conv.c b/cbits/conv.c
-index 3b6a129..5a68f91 100644
---- a/cbits/conv.c
-+++ b/cbits/conv.c
-@@ -1,5 +1,3 @@
--#include "config.h"
--
- #if IS_LINUX
- /* Linux cheats AC_CHECK_FUNCS(strptime_l), sigh. */
- #define THREAD_SAFE 0
-@@ -51,7 +49,7 @@ time_t c_parse_unix_time_gmt(char *fmt, char *src) {
- #else
- strptime(src, fmt, &dst);
- #endif
-- return timegm(&dst);
-+ return NULL; /* timegm(&dst); */
- }
-
- void c_format_unix_time(char *fmt, time_t src, char* dst, int siz) {
-diff --git a/unix-time.cabal b/unix-time.cabal
-index a905d63..f32d952 100644
---- a/unix-time.cabal
-+++ b/unix-time.cabal
-@@ -8,7 +8,7 @@ Synopsis: Unix time parser/formatter and utilities
- Description: Fast parser\/formatter\/utilities for Unix time
- Category: Data
- Cabal-Version: >= 1.10
--Build-Type: Configure
-+Build-Type: Simple
- Extra-Source-Files: cbits/conv.c cbits/config.h.in configure configure.ac
- Extra-Tmp-Files: config.log config.status autom4te.cache cbits/config.h
-
-@@ -21,34 +21,10 @@ Library
- Data.UnixTime.Types
- Data.UnixTime.Sys
- Build-Depends: base >= 4 && < 5
-- , bytestring
-+ , bytestring (>= 0.10.3.0)
- , old-time
- C-Sources: cbits/conv.c
-
--Test-Suite doctests
-- Type: exitcode-stdio-1.0
-- HS-Source-Dirs: test
-- Ghc-Options: -threaded -Wall
-- Main-Is: doctests.hs
-- Build-Depends: base
-- , doctest >= 0.9.3
--
--Test-Suite spec
-- Type: exitcode-stdio-1.0
-- Default-Language: Haskell2010
-- Hs-Source-Dirs: test
-- Ghc-Options: -Wall
-- Main-Is: Spec.hs
-- Other-Modules: UnixTimeSpec
-- Build-Depends: base
-- , bytestring
-- , hspec
-- , old-locale
-- , old-time
-- , QuickCheck
-- , time
-- , unix-time
--
- Source-Repository head
- Type: git
- Location: https://github.com/kazu-yamamoto/unix-time
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/unix-time_hack-for-Bionic.patch b/standalone/android/haskell-patches/unix-time_hack-for-Bionic.patch
new file mode 100644
index 000000000..be7956bea
--- /dev/null
+++ b/standalone/android/haskell-patches/unix-time_hack-for-Bionic.patch
@@ -0,0 +1,56 @@
+From e6d5c141186dbdbe97c698294485ffc4dcd3a843 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Fri, 18 Oct 2013 16:45:50 +0000
+Subject: [PATCH] hack for bionic + cross build
+
+---
+ Data/UnixTime/Types.hsc | 12 ------------
+ cbits/conv.c | 2 +-
+ 2 files changed, 1 insertion(+), 13 deletions(-)
+
+diff --git a/Data/UnixTime/Types.hsc b/Data/UnixTime/Types.hsc
+index d30f39b..ec7ca4c 100644
+--- a/Data/UnixTime/Types.hsc
++++ b/Data/UnixTime/Types.hsc
+@@ -9,8 +9,6 @@ import Foreign.Storable
+
+ #include <sys/time.h>
+
+-#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
+-
+ -- |
+ -- Data structure for Unix time.
+ data UnixTime = UnixTime {
+@@ -20,16 +18,6 @@ data UnixTime = UnixTime {
+ , utMicroSeconds :: {-# UNPACK #-} !Int32
+ } deriving (Eq,Ord,Show)
+
+-instance Storable UnixTime where
+- sizeOf _ = (#size struct timeval)
+- alignment _ = (#alignment struct timeval)
+- peek ptr = UnixTime
+- <$> (#peek struct timeval, tv_sec) ptr
+- <*> (#peek struct timeval, tv_usec) ptr
+- poke ptr ut = do
+- (#poke struct timeval, tv_sec) ptr (utSeconds ut)
+- (#poke struct timeval, tv_usec) ptr (utMicroSeconds ut)
+-
+ -- |
+ -- Format of the strptime()/strftime() style.
+ type Format = ByteString
+diff --git a/cbits/conv.c b/cbits/conv.c
+index 7ff7b87..2e4c870 100644
+--- a/cbits/conv.c
++++ b/cbits/conv.c
+@@ -55,7 +55,7 @@ time_t c_parse_unix_time_gmt(char *fmt, char *src) {
+ #else
+ strptime(src, fmt, &dst);
+ #endif
+- return timegm(&dst);
++ return NULL; /* timegm(&dst); (not in Bionic) */
+ }
+
+ size_t c_format_unix_time(char *fmt, time_t src, char* dst, int siz) {
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/unix_2.6.0.1_0001-remove-stuff-not-available-on-Android.patch b/standalone/android/haskell-patches/unix_2.6.0.1_0001-remove-stuff-not-available-on-Android.patch
deleted file mode 100644
index ff1da944c..000000000
--- a/standalone/android/haskell-patches/unix_2.6.0.1_0001-remove-stuff-not-available-on-Android.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From abca378462337ca0eb13a7e4d3073cb96a50d36c Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:37:23 -0400
-Subject: [PATCH] remove stuff not available on Android
-
----
- System/Posix/Resource.hsc | 4 ++++
- System/Posix/Terminal/Common.hsc | 29 +++--------------------------
- 2 files changed, 7 insertions(+), 26 deletions(-)
-
-diff --git a/System/Posix/Resource.hsc b/System/Posix/Resource.hsc
-index 6651998..2615b1e 100644
---- a/System/Posix/Resource.hsc
-+++ b/System/Posix/Resource.hsc
-@@ -101,7 +101,9 @@ packResource ResourceTotalMemory = (#const RLIMIT_AS)
- #endif
-
- unpackRLimit :: CRLim -> ResourceLimit
-+#if 0
- unpackRLimit (#const RLIM_INFINITY) = ResourceLimitInfinity
-+#endif
- #ifdef RLIM_SAVED_MAX
- unpackRLimit (#const RLIM_SAVED_MAX) = ResourceLimitUnknown
- unpackRLimit (#const RLIM_SAVED_CUR) = ResourceLimitUnknown
-@@ -109,7 +111,9 @@ unpackRLimit (#const RLIM_SAVED_CUR) = ResourceLimitUnknown
- unpackRLimit other = ResourceLimit (fromIntegral other)
-
- packRLimit :: ResourceLimit -> Bool -> CRLim
-+#if 0
- packRLimit ResourceLimitInfinity _ = (#const RLIM_INFINITY)
-+#endif
- #ifdef RLIM_SAVED_MAX
- packRLimit ResourceLimitUnknown True = (#const RLIM_SAVED_CUR)
- packRLimit ResourceLimitUnknown False = (#const RLIM_SAVED_MAX)
-diff --git a/System/Posix/Terminal/Common.hsc b/System/Posix/Terminal/Common.hsc
-index 3a6254d..32a22f2 100644
---- a/System/Posix/Terminal/Common.hsc
-+++ b/System/Posix/Terminal/Common.hsc
-@@ -419,11 +419,7 @@ foreign import ccall unsafe "tcsendbreak"
- -- | @drainOutput fd@ calls @tcdrain@ to block until all output
- -- written to @Fd@ @fd@ has been transmitted.
- drainOutput :: Fd -> IO ()
--drainOutput (Fd fd) = throwErrnoIfMinus1_ "drainOutput" (c_tcdrain fd)
--
--foreign import ccall unsafe "tcdrain"
-- c_tcdrain :: CInt -> IO CInt
--
-+drainOutput (Fd fd) = error "drainOutput not implemented"
-
- data QueueSelector
- = InputQueue -- TCIFLUSH
-@@ -434,16 +430,7 @@ data QueueSelector
- -- pending input and\/or output for @Fd@ @fd@,
- -- as indicated by the @QueueSelector@ @queues@.
- discardData :: Fd -> QueueSelector -> IO ()
--discardData (Fd fd) queue =
-- throwErrnoIfMinus1_ "discardData" (c_tcflush fd (queue2Int queue))
-- where
-- queue2Int :: QueueSelector -> CInt
-- queue2Int InputQueue = (#const TCIFLUSH)
-- queue2Int OutputQueue = (#const TCOFLUSH)
-- queue2Int BothQueues = (#const TCIOFLUSH)
--
--foreign import ccall unsafe "tcflush"
-- c_tcflush :: CInt -> CInt -> IO CInt
-+discardData (Fd fd) queue = error "discardData not implemented"
-
- data FlowAction
- = SuspendOutput -- ^ TCOOFF
-@@ -455,17 +442,7 @@ data FlowAction
- -- flow of data on @Fd@ @fd@, as indicated by
- -- @action@.
- controlFlow :: Fd -> FlowAction -> IO ()
--controlFlow (Fd fd) action =
-- throwErrnoIfMinus1_ "controlFlow" (c_tcflow fd (action2Int action))
-- where
-- action2Int :: FlowAction -> CInt
-- action2Int SuspendOutput = (#const TCOOFF)
-- action2Int RestartOutput = (#const TCOON)
-- action2Int TransmitStop = (#const TCIOFF)
-- action2Int TransmitStart = (#const TCION)
--
--foreign import ccall unsafe "tcflow"
-- c_tcflow :: CInt -> CInt -> IO CInt
-+controlFlow (Fd fd) action = error "controlFlow not implemented"
-
- -- | @getTerminalProcessGroupID fd@ calls @tcgetpgrp@ to
- -- obtain the @ProcessGroupID@ of the foreground process group
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/uuid_build-without-v1-uuid-which-needs-network-info.patch b/standalone/android/haskell-patches/uuid_build-without-v1-uuid-which-needs-network-info.patch
new file mode 100644
index 000000000..12cb2a922
--- /dev/null
+++ b/standalone/android/haskell-patches/uuid_build-without-v1-uuid-which-needs-network-info.patch
@@ -0,0 +1,79 @@
+From 87283f9b6f992a7f0e36c7b1bafc288bf2bf106a Mon Sep 17 00:00:00 2001
+From: androidbuilder <androidbuilder@example.com>
+Date: Mon, 11 Nov 2013 02:46:27 +0000
+Subject: [PATCH] build without v1 uuid which needs network-ino
+
+---
+ Data/UUID/Util.hs | 11 -----------
+ Data/UUID/V1.hs | 2 --
+ uuid.cabal | 2 --
+ 3 files changed, 15 deletions(-)
+
+diff --git a/Data/UUID/Util.hs b/Data/UUID/Util.hs
+index 581391a..399e508 100644
+--- a/Data/UUID/Util.hs
++++ b/Data/UUID/Util.hs
+@@ -3,7 +3,6 @@ module Data.UUID.Util (
+ UnpackedUUID(..)
+ , unpack, pack
+ , version
+- , extractMac
+ , extractTime
+ , setTime
+ ) where
+@@ -13,7 +12,6 @@ import Data.Word
+ import Data.Word.Util
+ import Data.Bits
+ import Data.UUID.Internal
+-import Network.Info
+ import Data.Int (Int64)
+
+ version :: UUID -> Int
+@@ -43,12 +41,3 @@ extractTime uuid =
+ timeAndVersionToTime :: Word16 -> Word16
+ timeAndVersionToTime tv = tv .&. 0x0FFF
+
+-extractMac :: UUID -> Maybe MAC
+-extractMac uuid =
+- if version uuid == 1
+- then Just $
+- MAC (node_0 unpacked) (node_1 unpacked) (node_2 unpacked) (node_3 unpacked) (node_4 unpacked) (node_5 unpacked)
+- else Nothing
+- where
+- unpacked = unpack uuid
+-
+diff --git a/Data/UUID/V1.hs b/Data/UUID/V1.hs
+index 067e729..ca4c235 100644
+--- a/Data/UUID/V1.hs
++++ b/Data/UUID/V1.hs
+@@ -37,8 +37,6 @@ import System.IO.Unsafe
+
+ import qualified System.Random as R
+
+-import Network.Info
+-
+ import Data.UUID.Builder
+ import Data.UUID.Internal
+
+diff --git a/uuid.cabal b/uuid.cabal
+index 0a53059..57b1b86 100644
+--- a/uuid.cabal
++++ b/uuid.cabal
+@@ -32,14 +32,12 @@ Library
+ cryptohash >= 0.7 && < 0.12,
+ deepseq == 1.3.*,
+ hashable (>= 1.1.1.0 && < 1.2.0) || (>= 1.2.1 && < 1.3),
+- network-info == 0.2.*,
+ random >= 1.0.1 && < 1.1,
+ time >= 1.1 && < 1.5
+
+ Exposed-Modules:
+ Data.UUID
+ Data.UUID.Util
+- Data.UUID.V1
+ Data.UUID.V3
+ Data.UUID.V4
+ Data.UUID.V5
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/vector_0.10.0.1_0001-disable-optimisation-that-breaks-when-cross-compilin.patch b/standalone/android/haskell-patches/vector_hack-to-build-with-new-ghc.patch
index aa50d9c93..4d39e91cf 100644
--- a/standalone/android/haskell-patches/vector_0.10.0.1_0001-disable-optimisation-that-breaks-when-cross-compilin.patch
+++ b/standalone/android/haskell-patches/vector_hack-to-build-with-new-ghc.patch
@@ -1,9 +1,8 @@
-From 3a4ee8091ba9da44f9f4a04522a5ff45fabe70d9 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:37:56 -0400
-Subject: [PATCH] disable optimisation that breaks when cross-compiling
+From b0a79f4f98188ba5d43b7e3912b36d34d099ab65 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Fri, 18 Oct 2013 23:20:35 +0000
+Subject: [PATCH] cross build
-This needs TH to work actually.
---
Data/Vector/Fusion/Stream/Monadic.hs | 1 -
1 file changed, 1 deletion(-)
diff --git a/standalone/android/haskell-patches/wai-app-static_1.3.1-remove-TH.patch b/standalone/android/haskell-patches/wai-app-static_deal-with-TH.patch
index 30bf5256a..d9860f922 100644
--- a/standalone/android/haskell-patches/wai-app-static_1.3.1-remove-TH.patch
+++ b/standalone/android/haskell-patches/wai-app-static_deal-with-TH.patch
@@ -1,16 +1,19 @@
-From c18ae75852b1340ca502528138bf421659f61a3d Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 12:44:15 -0400
-Subject: [PATCH] remove TH
+From 432a8fc47bb11cf8fd0a832e033cfb94a6332dbe Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 07:29:39 +0000
+Subject: [PATCH] deal with TH
+
+Export modules referenced by it.
Should not need these icons in git-annex, so not worth using the Evil
Splicer.
---
- Network/Wai/Application/Static.hs | 4 ----
- 1 file changed, 4 deletions(-)
+ Network/Wai/Application/Static.hs | 4 ----
+ wai-app-static.cabal | 2 +-
+ 2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/Network/Wai/Application/Static.hs b/Network/Wai/Application/Static.hs
-index 3195fbb..b48aa01 100644
+index 3f07391..75709b7 100644
--- a/Network/Wai/Application/Static.hs
+++ b/Network/Wai/Application/Static.hs
@@ -33,8 +33,6 @@ import Control.Monad.IO.Class (liftIO)
@@ -31,6 +34,21 @@ index 3195fbb..b48aa01 100644
staticAppPieces ss rawPieces req = liftIO $ do
case toPieces rawPieces of
Just pieces -> checkPieces ss pieces req >>= response
+diff --git a/wai-app-static.cabal b/wai-app-static.cabal
+index ec22813..e944caa 100644
+--- a/wai-app-static.cabal
++++ b/wai-app-static.cabal
+@@ -56,9 +56,9 @@ library
+ WaiAppStatic.Storage.Embedded
+ WaiAppStatic.Listing
+ WaiAppStatic.Types
+- other-modules: Util
+ WaiAppStatic.Storage.Embedded.Runtime
+ WaiAppStatic.Storage.Embedded.TH
++ other-modules: Util
+ ghc-options: -Wall
+ extensions: CPP
+
--
-1.8.2.rc3
+1.7.10.4
diff --git a/standalone/android/haskell-patches/wai-extra_1.3.2.1_0001-disable-CGI-module.patch b/standalone/android/haskell-patches/wai-extra_1.3.2.1_0001-disable-CGI-module.patch
deleted file mode 100644
index 7d5d6e2ba..000000000
--- a/standalone/android/haskell-patches/wai-extra_1.3.2.1_0001-disable-CGI-module.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From dc6d0128e666dcab07ddee56a22a4177ebfc0c7b Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:38:33 -0400
-Subject: [PATCH] disable CGI module
-
-I don't need it and it failed to build.
----
- wai-extra.cabal | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/wai-extra.cabal b/wai-extra.cabal
-index 9e9f0fc..007dd0f 100644
---- a/wai-extra.cabal
-+++ b/wai-extra.cabal
-@@ -44,7 +44,7 @@ Library
- , void >= 0.5 && < 0.6
- , stringsearch >= 0.3 && < 0.4
-
-- Exposed-modules: Network.Wai.Handler.CGI
-+ Exposed-modules:
- Network.Wai.Middleware.AcceptOverride
- Network.Wai.Middleware.Autohead
- Network.Wai.Middleware.CleanPath
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/xml-hamlet_0.4.0.3-0001-remove-TH-code.patch b/standalone/android/haskell-patches/xml-hamlet_0.4.0.3-0001-remove-TH-code.patch
deleted file mode 100644
index e6bda563d..000000000
--- a/standalone/android/haskell-patches/xml-hamlet_0.4.0.3-0001-remove-TH-code.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 3e988dec5ea248611d07d59914e3eb131dc6a165 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 18 Apr 2013 17:44:46 -0400
-Subject: [PATCH] remove TH code
-
----
- Text/Hamlet/XML.hs | 81 +-----------------------------------------------------
- 1 file changed, 1 insertion(+), 80 deletions(-)
-
-diff --git a/Text/Hamlet/XML.hs b/Text/Hamlet/XML.hs
-index f587410..bf8ce9e 100644
---- a/Text/Hamlet/XML.hs
-+++ b/Text/Hamlet/XML.hs
-@@ -1,8 +1,7 @@
- {-# LANGUAGE TemplateHaskell #-}
- {-# OPTIONS_GHC -fno-warn-missing-fields #-}
- module Text.Hamlet.XML
-- ( xml
-- , xmlFile
-+ (
- ) where
-
- import Language.Haskell.TH.Syntax
-@@ -18,81 +17,3 @@ import Data.String (fromString)
- import qualified Data.Foldable as F
- import Data.Maybe (fromMaybe)
- import qualified Data.Map as Map
--
--xml :: QuasiQuoter
--xml = QuasiQuoter { quoteExp = strToExp }
--
--xmlFile :: FilePath -> Q Exp
--xmlFile = strToExp . TL.unpack <=< qRunIO . readUtf8File
--
--strToExp :: String -> Q Exp
--strToExp s =
-- case parseDoc s of
-- Error e -> error e
-- Ok x -> docsToExp [] x
--
--docsToExp :: Scope -> [Doc] -> Q Exp
--docsToExp scope docs = [| concat $(fmap ListE $ mapM (docToExp scope) docs) |]
--
--docToExp :: Scope -> Doc -> Q Exp
--docToExp scope (DocTag name attrs cs) =
-- [| [ X.NodeElement (X.Element ($(liftName name)) $(mkAttrs scope attrs) $(docsToExp scope cs))
-- ] |]
--docToExp _ (DocContent (ContentRaw s)) = [| [ X.NodeContent (pack $(lift s)) ] |]
--docToExp scope (DocContent (ContentVar d)) = [| [ X.NodeContent $(return $ derefToExp scope d) ] |]
--docToExp scope (DocContent (ContentEmbed d)) = return $ derefToExp scope d
--docToExp scope (DocForall deref ident@(Ident ident') inside) = do
-- let list' = derefToExp scope deref
-- name <- newName ident'
-- let scope' = (ident, VarE name) : scope
-- inside' <- docsToExp scope' inside
-- let lam = LamE [VarP name] inside'
-- [| F.concatMap $(return lam) $(return list') |]
--docToExp scope (DocWith [] inside) = docsToExp scope inside
--docToExp scope (DocWith ((deref, ident@(Ident name)):dis) inside) = do
-- let deref' = derefToExp scope deref
-- name' <- newName name
-- let scope' = (ident, VarE name') : scope
-- inside' <- docToExp scope' (DocWith dis inside)
-- let lam = LamE [VarP name'] inside'
-- return $ lam `AppE` deref'
--docToExp scope (DocMaybe deref ident@(Ident name) just nothing) = do
-- let deref' = derefToExp scope deref
-- name' <- newName name
-- let scope' = (ident, VarE name') : scope
-- inside' <- docsToExp scope' just
-- let inside'' = LamE [VarP name'] inside'
-- nothing' <-
-- case nothing of
-- Nothing -> [| [] |]
-- Just n -> docsToExp scope n
-- [| maybe $(return nothing') $(return inside'') $(return deref') |]
--docToExp scope (DocCond conds final) = do
-- unit <- [| () |]
-- body <- fmap GuardedB $ mapM go $ conds ++ [(DerefIdent $ Ident "otherwise", fromMaybe [] final)]
-- return $ CaseE unit [Match (TupP []) body []]
-- where
-- go (deref, inside) = do
-- inside' <- docsToExp scope inside
-- return (NormalG $ derefToExp scope deref, inside')
--
--mkAttrs :: Scope -> [(Maybe Deref, String, [Content])] -> Q Exp
--mkAttrs _ [] = [| Map.empty |]
--mkAttrs scope ((mderef, name, value):rest) = do
-- rest' <- mkAttrs scope rest
-- this <- [| Map.insert $(liftName name) (T.concat $(fmap ListE $ mapM go value)) |]
-- let with = [| $(return this) $(return rest') |]
-- case mderef of
-- Nothing -> with
-- Just deref -> [| if $(return $ derefToExp scope deref) then $(with) else $(return rest') |]
-- where
-- go (ContentRaw s) = [| pack $(lift s) |]
-- go (ContentVar d) = return $ derefToExp scope d
-- go ContentEmbed{} = error "Cannot use embed interpolation in attribute value"
--
--liftName :: String -> Q Exp
--liftName s = do
-- X.Name local mns _ <- return $ fromString s
-- case mns of
-- Nothing -> [| X.Name (pack $(lift $ unpack local)) Nothing Nothing |]
-- Just ns -> [| X.Name (pack $(lift $ unpack local)) (Just $ pack $(lift $ unpack ns)) Nothing |]
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/yesod-auth_don-t-really-build.patch b/standalone/android/haskell-patches/yesod-auth_don-t-really-build.patch
new file mode 100644
index 000000000..7016e001c
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod-auth_don-t-really-build.patch
@@ -0,0 +1,34 @@
+From 3eb7b0a42099721dc19363ac41319efeed4ac5f9 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 05:19:53 +0000
+Subject: [PATCH] don't really build
+
+---
+ yesod-auth.cabal | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/yesod-auth.cabal b/yesod-auth.cabal
+index 591ced5..11217be 100644
+--- a/yesod-auth.cabal
++++ b/yesod-auth.cabal
+@@ -52,16 +52,7 @@ library
+ , safe
+ , time
+
+- exposed-modules: Yesod.Auth
+- Yesod.Auth.BrowserId
+- Yesod.Auth.Dummy
+- Yesod.Auth.Email
+- Yesod.Auth.OpenId
+- Yesod.Auth.Rpxnow
+- Yesod.Auth.HashDB
+- Yesod.Auth.Message
+- Yesod.Auth.GoogleEmail
+- other-modules: Yesod.Auth.Routes
++ exposed-modules:
+ ghc-options: -Wall
+
+ source-repository head
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod-core_1.1.8_0001-remove-TH.patch b/standalone/android/haskell-patches/yesod-core_1.1.8_0001-remove-TH.patch
deleted file mode 100644
index fd641a1aa..000000000
--- a/standalone/android/haskell-patches/yesod-core_1.1.8_0001-remove-TH.patch
+++ /dev/null
@@ -1,476 +0,0 @@
-From 801f6dea3be43113400e41aabb443456fffcd227 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:39:40 -0400
-Subject: [PATCH 1/2] remove TH
-
----
- Yesod/Core.hs | 10 ----
- Yesod/Dispatch.hs | 119 +----------------------------------------------
- Yesod/Handler.hs | 27 +----------
- Yesod/Internal/Cache.hs | 5 --
- Yesod/Internal/Core.hs | 119 +++++------------------------------------------
- Yesod/Widget.hs | 29 ------------
- 6 files changed, 13 insertions(+), 296 deletions(-)
-
-diff --git a/Yesod/Core.hs b/Yesod/Core.hs
-index 7268d6c..ce04b7d 100644
---- a/Yesod/Core.hs
-+++ b/Yesod/Core.hs
-@@ -21,16 +21,6 @@ module Yesod.Core
- , unauthorizedI
- -- * Logging
- , LogLevel (..)
-- , logDebug
-- , logInfo
-- , logWarn
-- , logError
-- , logOther
-- , logDebugS
-- , logInfoS
-- , logWarnS
-- , logErrorS
-- , logOtherS
- -- * Sessions
- , SessionBackend (..)
- , defaultClientSessionBackend
-diff --git a/Yesod/Dispatch.hs b/Yesod/Dispatch.hs
-index 1e19388..dd37475 100644
---- a/Yesod/Dispatch.hs
-+++ b/Yesod/Dispatch.hs
-@@ -6,20 +6,9 @@
- {-# LANGUAGE MultiParamTypeClasses #-}
- module Yesod.Dispatch
- ( -- * Quasi-quoted routing
-- parseRoutes
-- , parseRoutesNoCheck
-- , parseRoutesFile
-- , parseRoutesFileNoCheck
-- , mkYesod
-- , mkYesodSub
- -- ** More fine-grained
-- , mkYesodData
-- , mkYesodSubData
-- , mkYesodDispatch
-- , mkYesodSubDispatch
-- , mkDispatchInstance
- -- ** Path pieces
-- , PathPiece (..)
-+ PathPiece (..)
- , PathMultiPiece (..)
- , Texts
- -- * Convert to WAI
-@@ -52,117 +41,11 @@ import Data.Monoid (mappend)
- import qualified Data.ByteString as S
- import qualified Blaze.ByteString.Builder
- import Network.HTTP.Types (status301)
--import Yesod.Routes.TH
- import Yesod.Content (chooseRep)
--import Yesod.Routes.Parse
- import System.Log.FastLogger (Logger)
-
- type Texts = [Text]
-
---- | Generates URL datatype and site function for the given 'Resource's. This
---- is used for creating sites, /not/ subsites. See 'mkYesodSub' for the latter.
---- Use 'parseRoutes' to create the 'Resource's.
--mkYesod :: String -- ^ name of the argument datatype
-- -> [ResourceTree String]
-- -> Q [Dec]
--mkYesod name = fmap (uncurry (++)) . mkYesodGeneral name [] [] False
--
---- | Generates URL datatype and site function for the given 'Resource's. This
---- is used for creating subsites, /not/ sites. See 'mkYesod' for the latter.
---- Use 'parseRoutes' to create the 'Resource's. In general, a subsite is not
---- executable by itself, but instead provides functionality to
---- be embedded in other sites.
--mkYesodSub :: String -- ^ name of the argument datatype
-- -> Cxt
-- -> [ResourceTree String]
-- -> Q [Dec]
--mkYesodSub name clazzes =
-- fmap (uncurry (++)) . mkYesodGeneral name' rest clazzes True
-- where
-- (name':rest) = words name
--
---- | Sometimes, you will want to declare your routes in one file and define
---- your handlers elsewhere. For example, this is the only way to break up a
---- monolithic file into smaller parts. Use this function, paired with
---- 'mkYesodDispatch', to do just that.
--mkYesodData :: String -> [ResourceTree String] -> Q [Dec]
--mkYesodData name res = mkYesodDataGeneral name [] False res
--
--mkYesodSubData :: String -> Cxt -> [ResourceTree String] -> Q [Dec]
--mkYesodSubData name clazzes res = mkYesodDataGeneral name clazzes True res
--
--mkYesodDataGeneral :: String -> Cxt -> Bool -> [ResourceTree String] -> Q [Dec]
--mkYesodDataGeneral name clazzes isSub res = do
-- let (name':rest) = words name
-- (x, _) <- mkYesodGeneral name' rest clazzes isSub res
-- let rname = mkName $ "resources" ++ name
-- eres <- lift res
-- let y = [ SigD rname $ ListT `AppT` (ConT ''ResourceTree `AppT` ConT ''String)
-- , FunD rname [Clause [] (NormalB eres) []]
-- ]
-- return $ x ++ y
--
---- | See 'mkYesodData'.
--mkYesodDispatch :: String -> [ResourceTree String] -> Q [Dec]
--mkYesodDispatch name = fmap snd . mkYesodGeneral name [] [] False
--
--mkYesodSubDispatch :: String -> Cxt -> [ResourceTree String] -> Q [Dec]
--mkYesodSubDispatch name clazzes = fmap snd . mkYesodGeneral name' rest clazzes True
-- where (name':rest) = words name
--
--mkYesodGeneral :: String -- ^ foundation type
-- -> [String] -- ^ arguments for the type
-- -> Cxt -- ^ the type constraints
-- -> Bool -- ^ it this a subsite
-- -> [ResourceTree String]
-- -> Q([Dec],[Dec])
--mkYesodGeneral name args clazzes isSub resS = do
-- subsite <- sub
-- masterTypeSyns <- if isSub then return []
-- else sequence [handler, widget]
-- renderRouteDec <- mkRenderRouteInstance subsite res
-- dispatchDec <- mkDispatchInstance context sub master res
-- return (renderRouteDec ++ masterTypeSyns, dispatchDec)
-- where sub = foldl appT subCons subArgs
-- master = if isSub then (varT $ mkName "master") else sub
-- context = if isSub then cxt $ yesod : map return clazzes
-- else return []
-- yesod = classP ''Yesod [master]
-- handler = tySynD (mkName "Handler") [] [t| GHandler $master $master |]
-- widget = tySynD (mkName "Widget") [] [t| GWidget $master $master () |]
-- res = map (fmap parseType) resS
-- subCons = conT $ mkName name
-- subArgs = map (varT. mkName) args
--
---- | If the generation of @'YesodDispatch'@ instance require finer
---- control of the types, contexts etc. using this combinator. You will
---- hardly need this generality. However, in certain situations, like
---- when writing library/plugin for yesod, this combinator becomes
---- handy.
--mkDispatchInstance :: CxtQ -- ^ The context
-- -> TypeQ -- ^ The subsite type
-- -> TypeQ -- ^ The master site type
-- -> [ResourceTree a] -- ^ The resource
-- -> DecsQ
--mkDispatchInstance context sub master res = do
-- logger <- newName "logger"
-- let loggerE = varE logger
-- loggerP = VarP logger
-- yDispatch = conT ''YesodDispatch `appT` sub `appT` master
-- thisDispatch = do
-- Clause pat body decs <- mkDispatchClause
-- [|yesodRunner $loggerE |]
-- [|yesodDispatch $loggerE |]
-- [|fmap chooseRep|]
-- res
-- return $ FunD 'yesodDispatch
-- [ Clause (loggerP:pat)
-- body
-- decs
-- ]
-- in sequence [instanceD context yDispatch [thisDispatch]]
--
--
- -- | Convert the given argument into a WAI application, executable with any WAI
- -- handler. This is the same as 'toWaiAppPlain', except it includes two
- -- middlewares: GZIP compression and autohead. This is the
-diff --git a/Yesod/Handler.hs b/Yesod/Handler.hs
-index 1997bdb..98c915c 100644
---- a/Yesod/Handler.hs
-+++ b/Yesod/Handler.hs
-@@ -42,7 +42,6 @@ module Yesod.Handler
- , RedirectUrl (..)
- , redirect
- , redirectWith
-- , redirectToPost
- -- ** Errors
- , notFound
- , badMethod
-@@ -100,7 +99,6 @@ module Yesod.Handler
- , getMessageRender
- -- * Per-request caching
- , CacheKey
-- , mkCacheKey
- , cacheLookup
- , cacheInsert
- , cacheDelete
-@@ -172,7 +170,7 @@ import System.Log.FastLogger
- import Control.Monad.Logger
-
- import qualified Yesod.Internal.Cache as Cache
--import Yesod.Internal.Cache (mkCacheKey, CacheKey)
-+import Yesod.Internal.Cache (CacheKey)
- import qualified Data.IORef as I
- import Control.Exception.Lifted (catch)
- import Control.Monad.Trans.Control
-@@ -937,29 +935,6 @@ newIdent = do
- put x { ghsIdent = i' }
- return $ T.pack $ 'h' : show i'
-
---- | Redirect to a POST resource.
----
---- This is not technically a redirect; instead, it returns an HTML page with a
---- POST form, and some Javascript to automatically submit the form. This can be
---- useful when you need to post a plain link somewhere that needs to cause
---- changes on the server.
--redirectToPost :: RedirectUrl master url => url -> GHandler sub master a
--redirectToPost url = do
-- urlText <- toTextUrl url
-- hamletToRepHtml [hamlet|
--$newline never
--$doctype 5
--
--<html>
-- <head>
-- <title>Redirecting...
-- <body onload="document.getElementById('form').submit()">
-- <form id="form" method="post" action=#{urlText}>
-- <noscript>
-- <p>Javascript has been disabled; please click on the button below to be redirected.
-- <input type="submit" value="Continue">
--|] >>= sendResponse
--
- -- | Converts the given Hamlet template into 'Content', which can be used in a
- -- Yesod 'Response'.
- hamletToContent :: HtmlUrl (Route master) -> GHandler sub master Content
-diff --git a/Yesod/Internal/Cache.hs b/Yesod/Internal/Cache.hs
-index 4aec0d2..fdef9d7 100644
---- a/Yesod/Internal/Cache.hs
-+++ b/Yesod/Internal/Cache.hs
-@@ -3,7 +3,6 @@
- module Yesod.Internal.Cache
- ( Cache
- , CacheKey
-- , mkCacheKey
- , lookup
- , insert
- , delete
-@@ -24,10 +23,6 @@ newtype Cache = Cache (Map.IntMap Any)
-
- newtype CacheKey a = CacheKey Int
-
---- | Generate a new 'CacheKey'. Be sure to give a full type signature.
--mkCacheKey :: Q Exp
--mkCacheKey = [|CacheKey|] `appE` (LitE . IntegerL . fromIntegral . hashUnique <$> runIO newUnique)
--
- lookup :: CacheKey a -> Cache -> Maybe a
- lookup (CacheKey i) (Cache m) = unsafeCoerce <$> Map.lookup i m
-
-diff --git a/Yesod/Internal/Core.hs b/Yesod/Internal/Core.hs
-index c4a9796..90c05fc 100644
---- a/Yesod/Internal/Core.hs
-+++ b/Yesod/Internal/Core.hs
-@@ -44,7 +44,6 @@ module Yesod.Internal.Core
-
- import Yesod.Content
- import Yesod.Handler hiding (lift, getExpires)
--import Control.Monad.Logger (logErrorS)
-
- import Yesod.Routes.Class
- import Data.Time (UTCTime, addUTCTime, getCurrentTime)
-@@ -165,22 +164,7 @@ class RenderRoute a => Yesod a where
-
- -- | Applies some form of layout to the contents of a page.
- defaultLayout :: GWidget sub a () -> GHandler sub a RepHtml
-- defaultLayout w = do
-- p <- widgetToPageContent w
-- mmsg <- getMessage
-- hamletToRepHtml [hamlet|
--$newline never
--$doctype 5
--
--<html>
-- <head>
-- <title>#{pageTitle p}
-- ^{pageHead p}
-- <body>
-- $maybe msg <- mmsg
-- <p .message>#{msg}
-- ^{pageBody p}
--|]
-+ defaultLayout w = error "defaultLayout not implemented"
-
- -- | Override the rendering function for a particular URL. One use case for
- -- this is to offload static hosting to a different domain name to avoid
-@@ -521,46 +505,11 @@ applyLayout' title body = fmap chooseRep $ defaultLayout $ do
-
- -- | The default error handler for 'errorHandler'.
- defaultErrorHandler :: Yesod y => ErrorResponse -> GHandler sub y ChooseRep
--defaultErrorHandler NotFound = do
-- r <- waiRequest
-- let path' = TE.decodeUtf8With TEE.lenientDecode $ W.rawPathInfo r
-- applyLayout' "Not Found"
-- [hamlet|
--$newline never
--<h1>Not Found
--<p>#{path'}
--|]
--defaultErrorHandler (PermissionDenied msg) =
-- applyLayout' "Permission Denied"
-- [hamlet|
--$newline never
--<h1>Permission denied
--<p>#{msg}
--|]
--defaultErrorHandler (InvalidArgs ia) =
-- applyLayout' "Invalid Arguments"
-- [hamlet|
--$newline never
--<h1>Invalid Arguments
--<ul>
-- $forall msg <- ia
-- <li>#{msg}
--|]
--defaultErrorHandler (InternalError e) = do
-- $logErrorS "yesod-core" e
-- applyLayout' "Internal Server Error"
-- [hamlet|
--$newline never
--<h1>Internal Server Error
--<pre>#{e}
--|]
--defaultErrorHandler (BadMethod m) =
-- applyLayout' "Bad Method"
-- [hamlet|
--$newline never
--<h1>Method Not Supported
--<p>Method <code>#{S8.unpack m}</code> not supported
--|]
-+defaultErrorHandler NotFound = error "Not Found"
-+defaultErrorHandler (PermissionDenied msg) = error "Permission Denied"
-+defaultErrorHandler (InvalidArgs ia) = error "Invalid Arguments"
-+defaultErrorHandler (InternalError e) = error "Internal Server Error"
-+defaultErrorHandler (BadMethod m) = error "Bad Method"
-
- -- | Return the same URL if the user is authorized to see it.
- --
-@@ -616,45 +565,10 @@ widgetToPageContent w = do
- -- modernizr should be at the end of the <head> http://www.modernizr.com/docs/#installing
- -- the asynchronous loader means your page doesn't have to wait for all the js to load
- let (mcomplete, asyncScripts) = asyncHelper render scripts jscript jsLoc
-- regularScriptLoad = [hamlet|
--$newline never
--$forall s <- scripts
-- ^{mkScriptTag s}
--$maybe j <- jscript
-- $maybe s <- jsLoc
-- <script src="#{s}">
-- $nothing
-- <script>^{jelper j}
--|]
--
-- headAll = [hamlet|
--$newline never
--\^{head'}
--$forall s <- stylesheets
-- ^{mkLinkTag s}
--$forall s <- css
-- $maybe t <- right $ snd s
-- $maybe media <- fst s
-- <link rel=stylesheet media=#{media} href=#{t}>
-- $nothing
-- <link rel=stylesheet href=#{t}>
-- $maybe content <- left $ snd s
-- $maybe media <- fst s
-- <style media=#{media}>#{content}
-- $nothing
-- <style>#{content}
--$case jsLoader master
-- $of BottomOfBody
-- $of BottomOfHeadAsync asyncJsLoader
-- ^{asyncJsLoader asyncScripts mcomplete}
-- $of BottomOfHeadBlocking
-- ^{regularScriptLoad}
--|]
-- let bodyScript = [hamlet|
--$newline never
--^{body}
--^{regularScriptLoad}
--|]
-+ regularScriptLoad = error "TODO"
-+
-+ headAll = error "TODO"
-+ let bodyScript = error "TODO"
-
- return $ PageContent title headAll (case jsLoader master of
- BottomOfBody -> bodyScript
-@@ -696,18 +610,7 @@ jsonArray = unsafeLazyByteString . encode . Array . Vector.fromList . map String
-
- -- | For use with setting 'jsLoader' to 'BottomOfHeadAsync'
- loadJsYepnope :: Yesod master => Either Text (Route master) -> [Text] -> Maybe (HtmlUrl (Route master)) -> (HtmlUrl (Route master))
--loadJsYepnope eyn scripts mcomplete =
-- [hamlet|
--$newline never
-- $maybe yn <- left eyn
-- <script src=#{yn}>
-- $maybe yn <- right eyn
-- <script src=@{yn}>
-- $maybe complete <- mcomplete
-- <script>yepnope({load:#{jsonArray scripts},complete:function(){^{complete}}});
-- $nothing
-- <script>yepnope({load:#{jsonArray scripts}});
--|]
-+loadJsYepnope eyn scripts mcomplete = error "TODO"
-
- asyncHelper :: (url -> [x] -> Text)
- -> [Script (url)]
-diff --git a/Yesod/Widget.hs b/Yesod/Widget.hs
-index bd94bd3..bf79150 100644
---- a/Yesod/Widget.hs
-+++ b/Yesod/Widget.hs
-@@ -15,8 +15,6 @@ module Yesod.Widget
- GWidget
- , PageContent (..)
- -- * Special Hamlet quasiquoter/TH for Widgets
-- , whamlet
-- , whamletFile
- , ihamletToRepHtml
- -- * Convert to Widget
- , ToWidget (..)
-@@ -54,7 +52,6 @@ module Yesod.Widget
- , addScriptEither
- -- * Internal
- , unGWidget
-- , whamletFileWithSettings
- ) where
-
- import Data.Monoid
-@@ -274,32 +271,6 @@ data PageContent url = PageContent
- , pageBody :: HtmlUrl url
- }
-
--whamlet :: QuasiQuoter
--whamlet = NP.hamletWithSettings rules NP.defaultHamletSettings
--
--whamletFile :: FilePath -> Q Exp
--whamletFile = NP.hamletFileWithSettings rules NP.defaultHamletSettings
--
--whamletFileWithSettings :: NP.HamletSettings -> FilePath -> Q Exp
--whamletFileWithSettings = NP.hamletFileWithSettings rules
--
--rules :: Q NP.HamletRules
--rules = do
-- ah <- [|toWidget|]
-- let helper qg f = do
-- x <- newName "urender"
-- e <- f $ VarE x
-- let e' = LamE [VarP x] e
-- g <- qg
-- bind <- [|(>>=)|]
-- return $ InfixE (Just g) bind (Just e')
-- let ur f = do
-- let env = NP.Env
-- (Just $ helper [|liftW getUrlRenderParams|])
-- (Just $ helper [|liftM (toHtml .) $ liftW getMessageRender|])
-- f env
-- return $ NP.HamletRules ah ur $ \_ b -> return $ ah `AppE` b
--
- -- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
- ihamletToRepHtml :: RenderMessage master message
- => HtmlUrlI18n message (Route master)
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/yesod-core_1.1.8_0002-replaced-TH-in-Yesod.Internal.Core.patch b/standalone/android/haskell-patches/yesod-core_1.1.8_0002-replaced-TH-in-Yesod.Internal.Core.patch
deleted file mode 100644
index af0b3d15b..000000000
--- a/standalone/android/haskell-patches/yesod-core_1.1.8_0002-replaced-TH-in-Yesod.Internal.Core.patch
+++ /dev/null
@@ -1,267 +0,0 @@
-From 9ae3db0b3292b53715232fecec3c5e2bf03b89cd Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Fri, 1 Mar 2013 01:02:53 -0400
-Subject: [PATCH 2/2] replaced TH in Yesod.Internal.Core
-
-Done by running a build with -ddump-splices and manually pasting in the
-spliced code, and then modifying it until it compiles.
-
-(This predated the Evil Splicer, and both this and the previous patch need
-to be redone to use it.)
----
- Yesod/Internal/Core.hs | 211 +++++++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 201 insertions(+), 10 deletions(-)
-
-diff --git a/Yesod/Internal/Core.hs b/Yesod/Internal/Core.hs
-index 90c05fc..b9a0ae8 100644
---- a/Yesod/Internal/Core.hs
-+++ b/Yesod/Internal/Core.hs
-@@ -96,6 +96,9 @@ import System.Log.FastLogger (Logger, mkLogger, loggerDate, LogStr (..), loggerP
- import Control.Monad.Logger (LogLevel (LevelInfo, LevelOther), LogSource)
- import System.Log.FastLogger.Date (ZonedDate)
- import System.IO (stdout)
-+import qualified Data.Foldable
-+import qualified Text.Blaze.Internal
-+import qualified Text.Hamlet
-
- yesodVersion :: String
- yesodVersion = showVersion Paths_yesod_core.version
-@@ -164,7 +167,28 @@ class RenderRoute a => Yesod a where
-
- -- | Applies some form of layout to the contents of a page.
- defaultLayout :: GWidget sub a () -> GHandler sub a RepHtml
-- defaultLayout w = error "defaultLayout not implemented"
-+ defaultLayout w = do
-+ p <- widgetToPageContent w
-+ mmsg <- getMessage
-+ hamletToRepHtml $ \ _render_ay88 -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<!DOCTYPE html>\n<html><head><title>");
-+ id (TBH.toHtml (pageTitle p));
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</title>");
-+ id (pageHead p) _render_ay88;
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</head><body>");
-+ Text.Hamlet.maybeH
-+ mmsg
-+ (\ msg_ay89
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<p class=\"message\">");
-+ id (TBH.toHtml msg_ay89);
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") })
-+ Nothing;
-+ id (pageBody p) _render_ay88;
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "</body></html>") }
-
- -- | Override the rendering function for a particular URL. One use case for
- -- this is to offload static hosting to a different domain name to avoid
-@@ -505,11 +529,45 @@ applyLayout' title body = fmap chooseRep $ defaultLayout $ do
-
- -- | The default error handler for 'errorHandler'.
- defaultErrorHandler :: Yesod y => ErrorResponse -> GHandler sub y ChooseRep
--defaultErrorHandler NotFound = error "Not Found"
--defaultErrorHandler (PermissionDenied msg) = error "Permission Denied"
--defaultErrorHandler (InvalidArgs ia) = error "Invalid Arguments"
--defaultErrorHandler (InternalError e) = error "Internal Server Error"
--defaultErrorHandler (BadMethod m) = error "Bad Method"
-+defaultErrorHandler NotFound = do
-+ r <- waiRequest
-+ let path' = TE.decodeUtf8With TEE.lenientDecode $ W.rawPathInfo r
-+ applyLayout' "Not Found" $ \ _render_ayac -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<h1>Not Found</h1><p>");
-+ id (TBH.toHtml path');
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") }
-+defaultErrorHandler (PermissionDenied msg) =
-+ applyLayout' "Permission Denied" $ \ _render_ayah -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<h1>Permission denied</h1><p>");
-+ id (TBH.toHtml msg);
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") }
-+defaultErrorHandler (InvalidArgs ia) =
-+ applyLayout' "Invalid Arguments" $ \ _render_ayam -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<h1>Invalid Arguments</h1><ul>");
-+ Data.Foldable.mapM_
-+ (\ msg_ayan
-+ -> do { id ((Text.Blaze.Internal.preEscapedText . T.pack) "<li>");
-+ id (TBH.toHtml msg_ayan);
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</li>") })
-+ ia;
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</ul>") }
-+defaultErrorHandler (InternalError e) = do
-+ applyLayout' "Internal Server Error" $ \ _render_ayau -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<h1>Internal Server Error</h1><pre>");
-+ id (TBH.toHtml e);
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</pre>") }
-+defaultErrorHandler (BadMethod m) =
-+ applyLayout' "Bad Method" $ \ _render_ayaz -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<h1>Method Not Supported</h1><p>Method <code>");
-+ id (TBH.toHtml (S8.unpack m));
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "</code> not supported</p>") }
-
- -- | Return the same URL if the user is authorized to see it.
- --
-@@ -565,10 +623,99 @@ widgetToPageContent w = do
- -- modernizr should be at the end of the <head> http://www.modernizr.com/docs/#installing
- -- the asynchronous loader means your page doesn't have to wait for all the js to load
- let (mcomplete, asyncScripts) = asyncHelper render scripts jscript jsLoc
-- regularScriptLoad = error "TODO"
--
-- headAll = error "TODO"
-- let bodyScript = error "TODO"
-+ regularScriptLoad = \ _render_aybs -> do { Data.Foldable.mapM_
-+ (\ s_aybt
-+ -> id (mkScriptTag s_aybt) _render_aybs)
-+ scripts;
-+ Text.Hamlet.maybeH
-+ jscript
-+ (\ j_aybu
-+ -> Text.Hamlet.maybeH
-+ jsLoc
-+ (\ s_aybv
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<script src=\"");
-+ id (TBH.toHtml s_aybv);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "\"></script>") })
-+ (Just
-+ (do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "<script>");
-+ id (jelper j_aybu) _render_aybs;
-+ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</script>") })))
-+ Nothing }
-+
-+ headAll = \ _render_aybz -> do
-+ { id head' _render_aybz;
-+ Data.Foldable.mapM_
-+ (\ s_aybA -> id (mkLinkTag s_aybA) _render_aybz)
-+ stylesheets;
-+ Data.Foldable.mapM_
-+ (\ s_aybB
-+ -> do { Text.Hamlet.maybeH
-+ (right (snd s_aybB))
-+ (\ t_aybC
-+ -> Text.Hamlet.maybeH
-+ (fst s_aybB)
-+ (\ media_aybD
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<link rel=\"stylesheet\" media=\"");
-+ id (TBH.toHtml media_aybD);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "\" href=\"");
-+ id (TBH.toHtml t_aybC);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "\">") })
-+ (Just
-+ (do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<link rel=\"stylesheet\" href=\"");
-+ id (TBH.toHtml t_aybC);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "\">") })))
-+ Nothing;
-+ Text.Hamlet.maybeH
-+ (left (snd s_aybB))
-+ (\ content_aybE
-+ -> Text.Hamlet.maybeH
-+ (fst s_aybB)
-+ (\ media_aybF
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<style media=\"");
-+ id (TBH.toHtml media_aybF);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "\">");
-+ id (TBH.toHtml content_aybE);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "</style>") })
-+ (Just
-+ (do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<style>");
-+ id (TBH.toHtml content_aybE);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "</style>") })))
-+ Nothing })
-+ css;
-+ case jsLoader master of
-+ BottomOfBody -> return ()
-+ BottomOfHeadAsync asyncJsLoader -> id (asyncJsLoader asyncScripts mcomplete) _render_aybz
-+ BottomOfHeadBlocking -> id regularScriptLoad _render_aybz
-+ }
-+
-+ let bodyScript = \ _render_aybL -> do {
-+ id body _render_aybL;
-+ id regularScriptLoad _render_aybL }
-
- return $ PageContent title headAll (case jsLoader master of
- BottomOfBody -> bodyScript
-@@ -611,6 +758,50 @@ jsonArray = unsafeLazyByteString . encode . Array . Vector.fromList . map String
- -- | For use with setting 'jsLoader' to 'BottomOfHeadAsync'
- loadJsYepnope :: Yesod master => Either Text (Route master) -> [Text] -> Maybe (HtmlUrl (Route master)) -> (HtmlUrl (Route master))
- loadJsYepnope eyn scripts mcomplete = error "TODO"
-+{-
-+ \ _render_aybU
-+ -> do { Text.Hamlet.maybeH
-+ (left eyn)
-+ (\ yn_aybV
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "<script src=\"");
-+ id (TBH.toHtml yn_aybV);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "\"></script>") })
-+ Nothing;
-+ Text.Hamlet.maybeH
-+ (right eyn)
-+ (\ yn_aybW
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "<script src=\"");
-+ id
-+ (TBH.toHtml
-+ (\ u_aybX -> _render_aybU u_aybX [] yn_aybW));
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "\"></script>") })
-+ Nothing;
-+ Text.Hamlet.maybeH
-+ mcomplete
-+ (\ complete_aybY
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<script>yepnope({load:");
-+ id (TBH.toHtml (jsonArray scripts));
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ ",complete:function(){");
-+ id complete_aybY _render_aybU;
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack) "}});</script>") })
-+ (Just
-+ (do { id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "<script>yepnope({load:");
-+ id (TBH.toHtml (jsonArray scripts));
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . T.pack)
-+ "});</script>") })) }
-+-}
-
- asyncHelper :: (url -> [x] -> Text)
- -> [Script (url)]
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/yesod-core_1.1.8_0003-exports-for-TH-splices.patch b/standalone/android/haskell-patches/yesod-core_1.1.8_0003-exports-for-TH-splices.patch
deleted file mode 100644
index 440b57ac8..000000000
--- a/standalone/android/haskell-patches/yesod-core_1.1.8_0003-exports-for-TH-splices.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From b7e01a2fded6575678db234e1f2de1f104f11376 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 15:25:07 -0400
-Subject: [PATCH 3/3] exports for TH splices
-
----
- Yesod/Widget.hs | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/Yesod/Widget.hs b/Yesod/Widget.hs
-index bf79150..01ae294 100644
---- a/Yesod/Widget.hs
-+++ b/Yesod/Widget.hs
-@@ -52,6 +52,9 @@ module Yesod.Widget
- , addScriptEither
- -- * Internal
- , unGWidget
-+
-+ -- used by TH code
-+ , liftW
- ) where
-
- import Data.Monoid
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/yesod-core_expand_TH.patch b/standalone/android/haskell-patches/yesod-core_expand_TH.patch
new file mode 100644
index 000000000..1687ff0e4
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod-core_expand_TH.patch
@@ -0,0 +1,411 @@
+From 7583457fb410d07f480a2aa7d6c2f174324b3592 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Sat, 19 Oct 2013 02:03:18 +0000
+Subject: [PATCH] hackity
+
+---
+ Yesod/Core.hs | 2 -
+ Yesod/Core/Class/Yesod.hs | 247 ++++++++++++++++++++++++++++++--------------
+ Yesod/Core/Dispatch.hs | 7 --
+ Yesod/Core/Handler.hs | 24 ++---
+ Yesod/Core/Internal/Run.hs | 2 -
+ 5 files changed, 179 insertions(+), 103 deletions(-)
+
+diff --git a/Yesod/Core.hs b/Yesod/Core.hs
+index 12e59d5..f1ff21c 100644
+--- a/Yesod/Core.hs
++++ b/Yesod/Core.hs
+@@ -94,8 +94,6 @@ module Yesod.Core
+ , JavascriptUrl
+ , renderJavascriptUrl
+ -- ** Cassius/Lucius
+- , cassius
+- , lucius
+ , CssUrl
+ , renderCssUrl
+ ) where
+diff --git a/Yesod/Core/Class/Yesod.hs b/Yesod/Core/Class/Yesod.hs
+index cf02a1a..3f1e88e 100644
+--- a/Yesod/Core/Class/Yesod.hs
++++ b/Yesod/Core/Class/Yesod.hs
+@@ -9,6 +9,10 @@ import Yesod.Core.Content
+ import Yesod.Core.Handler
+
+ import Yesod.Routes.Class
++import qualified Text.Blaze.Internal
++import qualified Control.Monad.Logger
++import qualified Text.Hamlet
++import qualified Data.Foldable
+
+ import Blaze.ByteString.Builder (Builder)
+ import Blaze.ByteString.Builder.Char.Utf8 (fromText)
+@@ -87,18 +91,27 @@ class RenderRoute site => Yesod site where
+ defaultLayout w = do
+ p <- widgetToPageContent w
+ mmsg <- getMessage
+- giveUrlRenderer [hamlet|
+- $newline never
+- $doctype 5
+- <html>
+- <head>
+- <title>#{pageTitle p}
+- ^{pageHead p}
+- <body>
+- $maybe msg <- mmsg
+- <p .message>#{msg}
+- ^{pageBody p}
+- |]
++ giveUrlRenderer $ \ _render_aHra
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<!DOCTYPE html>\n<html><head><title>");
++ id (TBH.toHtml (pageTitle p));
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</title>");
++ Text.Hamlet.asHtmlUrl (pageHead p) _render_aHra;
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</head><body>");
++ Text.Hamlet.maybeH
++ mmsg
++ (\ msg_aHrb
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<p class=\"message\">");
++ id (TBH.toHtml msg_aHrb);
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") })
++ Nothing;
++ Text.Hamlet.asHtmlUrl (pageBody p) _render_aHra;
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack) "</body></html>") }
++
+
+ -- | Override the rendering function for a particular URL. One use case for
+ -- this is to offload static hosting to a different domain name to avoid
+@@ -356,45 +369,103 @@ widgetToPageContent w = do
+ -- modernizr should be at the end of the <head> http://www.modernizr.com/docs/#installing
+ -- the asynchronous loader means your page doesn't have to wait for all the js to load
+ let (mcomplete, asyncScripts) = asyncHelper render scripts jscript jsLoc
+- regularScriptLoad = [hamlet|
+- $newline never
+- $forall s <- scripts
+- ^{mkScriptTag s}
+- $maybe j <- jscript
+- $maybe s <- jsLoc
+- <script src="#{s}">
+- $nothing
+- <script>^{jelper j}
+- |]
+-
+- headAll = [hamlet|
+- $newline never
+- \^{head'}
+- $forall s <- stylesheets
+- ^{mkLinkTag s}
+- $forall s <- css
+- $maybe t <- right $ snd s
+- $maybe media <- fst s
+- <link rel=stylesheet media=#{media} href=#{t}>
+- $nothing
+- <link rel=stylesheet href=#{t}>
+- $maybe content <- left $ snd s
+- $maybe media <- fst s
+- <style media=#{media}>#{content}
+- $nothing
+- <style>#{content}
+- $case jsLoader master
+- $of BottomOfBody
+- $of BottomOfHeadAsync asyncJsLoader
+- ^{asyncJsLoader asyncScripts mcomplete}
+- $of BottomOfHeadBlocking
+- ^{regularScriptLoad}
+- |]
+- let bodyScript = [hamlet|
+- $newline never
+- ^{body}
+- ^{regularScriptLoad}
+- |]
++ regularScriptLoad = \ _render_aHsO
++ -> do { Data.Foldable.mapM_
++ (\ s_aHsP
++ -> Text.Hamlet.asHtmlUrl (mkScriptTag s_aHsP) _render_aHsO)
++ scripts;
++ Text.Hamlet.maybeH
++ jscript
++ (\ j_aHsQ
++ -> Text.Hamlet.maybeH
++ jsLoc
++ (\ s_aHsR
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<script src=\"");
++ id (TBH.toHtml s_aHsR);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\"></script>") })
++ (Just
++ (do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack) "<script>");
++ Text.Hamlet.asHtmlUrl (jelper j_aHsQ) _render_aHsO;
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</script>") })))
++ Nothing }
++
++
++ headAll = \ _render_aHsW
++ -> do { Text.Hamlet.asHtmlUrl head' _render_aHsW;
++ Data.Foldable.mapM_
++ (\ s_aHsX -> Text.Hamlet.asHtmlUrl (mkLinkTag s_aHsX) _render_aHsW)
++ stylesheets;
++ Data.Foldable.mapM_
++ (\ s_aHsY
++ -> do { Text.Hamlet.maybeH
++ (right (snd s_aHsY))
++ (\ t_aHsZ
++ -> Text.Hamlet.maybeH
++ (fst s_aHsY)
++ (\ media_aHt0
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<link rel=\"stylesheet\" media=\"");
++ id (TBH.toHtml media_aHt0);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\" href=\"");
++ id (TBH.toHtml t_aHsZ);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\">") })
++ (Just
++ (do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<link rel=\"stylesheet\" href=\"");
++ id (TBH.toHtml t_aHsZ);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\">") })))
++ Nothing;
++ Text.Hamlet.maybeH
++ (left (snd s_aHsY))
++ (\ content_aHt1
++ -> Text.Hamlet.maybeH
++ (fst s_aHsY)
++ (\ media_aHt2
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<style media=\"");
++ id (TBH.toHtml media_aHt2);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\">");
++ id (TBH.toHtml content_aHt1);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "</style>") })
++ (Just
++ (do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<style>");
++ id (TBH.toHtml content_aHt1);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "</style>") })))
++ Nothing })
++ css;
++ case jsLoader master of {
++ BottomOfBody -> return ()
++ ; BottomOfHeadAsync asyncJsLoader_aHt3
++ -> Text.Hamlet.asHtmlUrl
++ (asyncJsLoader_aHt3 asyncScripts mcomplete) _render_aHsW
++ ; BottomOfHeadBlocking
++ -> Text.Hamlet.asHtmlUrl regularScriptLoad _render_aHsW } }
++
++ let bodyScript = \ _render_aHt8 -> do { Text.Hamlet.asHtmlUrl body _render_aHt8;
++ Text.Hamlet.asHtmlUrl regularScriptLoad _render_aHt8 }
++
+
+ return $ PageContent title headAll $
+ case jsLoader master of
+@@ -424,10 +495,13 @@ defaultErrorHandler NotFound = selectRep $ do
+ r <- waiRequest
+ let path' = TE.decodeUtf8With TEE.lenientDecode $ W.rawPathInfo r
+ setTitle "Not Found"
+- toWidget [hamlet|
+- <h1>Not Found
+- <p>#{path'}
+- |]
++ toWidget $ \ _render_aHte
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Not Found</h1>\n<p>");
++ id (TBH.toHtml path');
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") }
++
+ provideRep $ return $ object ["message" .= ("Not Found" :: Text)]
+
+ -- For API requests.
+@@ -437,10 +511,11 @@ defaultErrorHandler NotFound = selectRep $ do
+ defaultErrorHandler NotAuthenticated = selectRep $ do
+ provideRep $ defaultLayout $ do
+ setTitle "Not logged in"
+- toWidget [hamlet|
+- <h1>Not logged in
+- <p style="display:none;">Set the authRoute and the user will be redirected there.
+- |]
++ toWidget $ \ _render_aHti
++ -> id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Not logged in</h1>\n<p style=\"none;\">Set the authRoute and the user will be redirected there.</p>")
++
+
+ provideRep $ do
+ -- 401 *MUST* include a WWW-Authenticate header
+@@ -462,10 +537,13 @@ defaultErrorHandler NotAuthenticated = selectRep $ do
+ defaultErrorHandler (PermissionDenied msg) = selectRep $ do
+ provideRep $ defaultLayout $ do
+ setTitle "Permission Denied"
+- toWidget [hamlet|
+- <h1>Permission denied
+- <p>#{msg}
+- |]
++ toWidget $ \ _render_aHtq
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Permission denied</h1>\n<p>");
++ id (TBH.toHtml msg);
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</p>") }
++
+ provideRep $
+ return $ object $ [
+ "message" .= ("Permission Denied. " <> msg)
+@@ -474,30 +552,43 @@ defaultErrorHandler (PermissionDenied msg) = selectRep $ do
+ defaultErrorHandler (InvalidArgs ia) = selectRep $ do
+ provideRep $ defaultLayout $ do
+ setTitle "Invalid Arguments"
+- toWidget [hamlet|
+- <h1>Invalid Arguments
+- <ul>
+- $forall msg <- ia
+- <li>#{msg}
+- |]
++ toWidget $ \ _render_aHtv
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Invalid Arguments</h1>\n<ul>");
++ Data.Foldable.mapM_
++ (\ msg_aHtw
++ -> do { id ((Text.Blaze.Internal.preEscapedText . T.pack) "<li>");
++ id (TBH.toHtml msg_aHtw);
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</li>") })
++ ia;
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</ul>") }
++
+ provideRep $ return $ object ["message" .= ("Invalid Arguments" :: Text), "errors" .= ia]
+ defaultErrorHandler (InternalError e) = do
+- $logErrorS "yesod-core" e
+ selectRep $ do
+ provideRep $ defaultLayout $ do
+ setTitle "Internal Server Error"
+- toWidget [hamlet|
+- <h1>Internal Server Error
+- <pre>#{e}
+- |]
++ toWidget $ \ _render_aHtC
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Internal Server Error</h1>\n<pre>");
++ id (TBH.toHtml e);
++ id ((Text.Blaze.Internal.preEscapedText . T.pack) "</pre>") }
++
+ provideRep $ return $ object ["message" .= ("Internal Server Error" :: Text), "error" .= e]
+ defaultErrorHandler (BadMethod m) = selectRep $ do
+ provideRep $ defaultLayout $ do
+ setTitle"Bad Method"
+- toWidget [hamlet|
+- <h1>Method Not Supported
+- <p>Method <code>#{S8.unpack m}</code> not supported
+- |]
++ toWidget $ \ _render_aHtH
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<h1>Method Not Supported</h1>\n<p>Method <code>");
++ id (TBH.toHtml (S8.unpack m));
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "</code> not supported</p>") }
++
+ provideRep $ return $ object ["message" .= ("Bad method" :: Text), "method" .= m]
+
+ asyncHelper :: (url -> [x] -> Text)
+diff --git a/Yesod/Core/Dispatch.hs b/Yesod/Core/Dispatch.hs
+index 335a15c..4ca05da 100644
+--- a/Yesod/Core/Dispatch.hs
++++ b/Yesod/Core/Dispatch.hs
+@@ -123,13 +123,6 @@ toWaiApp site = do
+ , yreSite = site
+ , yreSessionBackend = sb
+ }
+- messageLoggerSource
+- site
+- logger
+- $(qLocation >>= liftLoc)
+- "yesod-core"
+- LevelInfo
+- (toLogStr ("Application launched" :: S.ByteString))
+ middleware <- mkDefaultMiddlewares logger
+ return $ middleware $ toWaiAppYre yre
+
+diff --git a/Yesod/Core/Handler.hs b/Yesod/Core/Handler.hs
+index f3b1799..d819b04 100644
+--- a/Yesod/Core/Handler.hs
++++ b/Yesod/Core/Handler.hs
+@@ -152,7 +152,7 @@ import qualified Control.Monad.Trans.Writer as Writer
+
+ import Control.Monad.IO.Class (MonadIO, liftIO)
+ import Control.Monad.Trans.Resource (MonadResource, liftResourceT)
+-
++import qualified Text.Blaze.Internal
+ import qualified Network.HTTP.Types as H
+ import qualified Network.Wai as W
+ import Control.Monad.Trans.Class (lift)
+@@ -710,19 +710,15 @@ redirectToPost :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
+ -> m a
+ redirectToPost url = do
+ urlText <- toTextUrl url
+- giveUrlRenderer [hamlet|
+-$newline never
+-$doctype 5
+-
+-<html>
+- <head>
+- <title>Redirecting...
+- <body onload="document.getElementById('form').submit()">
+- <form id="form" method="post" action=#{urlText}>
+- <noscript>
+- <p>Javascript has been disabled; please click on the button below to be redirected.
+- <input type="submit" value="Continue">
+-|] >>= sendResponse
++ giveUrlRenderer $ \ _render_awps
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "<!DOCTYPE html>\n<html><head><title>Redirecting...</title></head><body onload=\"document.getElementById('form').submit()\"><form id=\"form\" method=\"post\" action=\"");
++ id (toHtml urlText);
++ id
++ ((Text.Blaze.Internal.preEscapedText . T.pack)
++ "\"><noscript><p>Javascript has been disabled; please click on the button below to be redirected.</p></noscript><input type=\"submit\" value=\"Continue\"></form></body></html>") }
++ >>= sendResponse
+
+ -- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
+ hamletToRepHtml :: MonadHandler m => HtmlUrl (Route (HandlerSite m)) -> m Html
+diff --git a/Yesod/Core/Internal/Run.hs b/Yesod/Core/Internal/Run.hs
+index 35f1d3f..8b92e99 100644
+--- a/Yesod/Core/Internal/Run.hs
++++ b/Yesod/Core/Internal/Run.hs
+@@ -122,8 +122,6 @@ safeEh :: (Loc -> LogSource -> LogLevel -> LogStr -> IO ())
+ -> ErrorResponse
+ -> YesodApp
+ safeEh log' er req = do
+- liftIO $ log' $(qLocation >>= liftLoc) "yesod-core" LevelError
+- $ toLogStr $ "Error handler errored out: " ++ show er
+ return $ YRPlain
+ H.status500
+ []
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod-default_1.1.3.2_0001-remove-TH.patch b/standalone/android/haskell-patches/yesod-default_1.1.3.2_0001-remove-TH.patch
deleted file mode 100644
index e6048ee0a..000000000
--- a/standalone/android/haskell-patches/yesod-default_1.1.3.2_0001-remove-TH.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From 8ff7908799eb69d440168ff3df1fe3187879df33 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:39:57 -0400
-Subject: [PATCH] remove TH
-
----
- Yesod/Default/Util.hs | 61 +------------------------------------------------
- 1 file changed, 1 insertion(+), 60 deletions(-)
-
-diff --git a/Yesod/Default/Util.hs b/Yesod/Default/Util.hs
-index 578b9bc..178e342 100644
---- a/Yesod/Default/Util.hs
-+++ b/Yesod/Default/Util.hs
-@@ -5,8 +5,6 @@
- module Yesod.Default.Util
- ( addStaticContentExternal
- , globFile
-- , widgetFileNoReload
-- , widgetFileReload
- , TemplateLanguage (..)
- , defaultTemplateLanguages
- , WidgetFileSettings
-@@ -21,9 +19,6 @@ import Yesod.Core -- purposely using complete import so that Haddock will see ad
- import Control.Monad (when, unless)
- import System.Directory (doesFileExist, createDirectoryIfMissing)
- import Language.Haskell.TH.Syntax
--import Text.Lucius (luciusFile, luciusFileReload)
--import Text.Julius (juliusFile, juliusFileReload)
--import Text.Cassius (cassiusFile, cassiusFileReload)
- import Text.Hamlet (HamletSettings, defaultHamletSettings)
- import Data.Maybe (catMaybes)
- import Data.Default (Default (def))
-@@ -72,13 +67,7 @@ data TemplateLanguage = TemplateLanguage
-
- defaultTemplateLanguages :: HamletSettings -> [TemplateLanguage]
- defaultTemplateLanguages hset =
-- [ TemplateLanguage False "hamlet" whamletFile' whamletFile'
-- , TemplateLanguage True "cassius" cassiusFile cassiusFileReload
-- , TemplateLanguage True "julius" juliusFile juliusFileReload
-- , TemplateLanguage True "lucius" luciusFile luciusFileReload
-- ]
-- where
-- whamletFile' = whamletFileWithSettings hset
-+ [ ]
-
- data WidgetFileSettings = WidgetFileSettings
- { wfsLanguages :: HamletSettings -> [TemplateLanguage]
-@@ -87,51 +76,3 @@ data WidgetFileSettings = WidgetFileSettings
-
- instance Default WidgetFileSettings where
- def = WidgetFileSettings defaultTemplateLanguages defaultHamletSettings
--
--widgetFileNoReload :: WidgetFileSettings -> FilePath -> Q Exp
--widgetFileNoReload wfs x = combine "widgetFileNoReload" x False $ wfsLanguages wfs $ wfsHamletSettings wfs
--
--widgetFileReload :: WidgetFileSettings -> FilePath -> Q Exp
--widgetFileReload wfs x = combine "widgetFileReload" x True $ wfsLanguages wfs $ wfsHamletSettings wfs
--
--combine :: String -> String -> Bool -> [TemplateLanguage] -> Q Exp
--combine func file isReload tls = do
-- mexps <- qmexps
-- case catMaybes mexps of
-- [] -> error $ concat
-- [ "Called "
-- , func
-- , " on "
-- , show file
-- , ", but no template were found."
-- ]
-- exps -> return $ DoE $ map NoBindS exps
-- where
-- qmexps :: Q [Maybe Exp]
-- qmexps = mapM go tls
--
-- go :: TemplateLanguage -> Q (Maybe Exp)
-- go tl = whenExists file (tlRequiresToWidget tl) (tlExtension tl) ((if isReload then tlReload else tlNoReload) tl)
--
--whenExists :: String
-- -> Bool -- ^ requires toWidget wrap
-- -> String -> (FilePath -> Q Exp) -> Q (Maybe Exp)
--whenExists = warnUnlessExists False
--
--warnUnlessExists :: Bool
-- -> String
-- -> Bool -- ^ requires toWidget wrap
-- -> String -> (FilePath -> Q Exp) -> Q (Maybe Exp)
--warnUnlessExists shouldWarn x wrap glob f = do
-- let fn = globFile glob x
-- e <- qRunIO $ doesFileExist fn
-- when (shouldWarn && not e) $ qRunIO $ putStrLn $ "widget file not found: " ++ fn
-- if e
-- then do
-- ex <- f fn
-- if wrap
-- then do
-- tw <- [|toWidget|]
-- return $ Just $ tw `AppE` ex
-- else return $ Just ex
-- else return Nothing
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/yesod-form_1.2.1.1-0001-prepare-for-Evil-Splicer.patch b/standalone/android/haskell-patches/yesod-form_1.2.1.1-0001-prepare-for-Evil-Splicer.patch
deleted file mode 100644
index c24055b1f..000000000
--- a/standalone/android/haskell-patches/yesod-form_1.2.1.1-0001-prepare-for-Evil-Splicer.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From a603bac40f0a0f6232fbfb056a778860270101de Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 15:59:56 -0400
-Subject: [PATCH 1/2] prepare for Evil Splicer
-
----
- Yesod/Form/Functions.hs | 3 +--
- evilsplicer-headers.hs | 9 +++++++++
- yesod-form.cabal | 5 +++--
- 3 files changed, 13 insertions(+), 4 deletions(-)
- create mode 100644 evilsplicer-headers.hs
-
-diff --git a/Yesod/Form/Functions.hs b/Yesod/Form/Functions.hs
-index db3e493..89eb1e8 100644
---- a/Yesod/Form/Functions.hs
-+++ b/Yesod/Form/Functions.hs
-@@ -54,10 +54,9 @@ import Text.Blaze (Markup, toMarkup)
- #define toHtml toMarkup
- import Yesod.Handler (GHandler, getRequest, runRequestBody, newIdent, getYesod)
- import Yesod.Core (RenderMessage, SomeMessage (..))
--import Yesod.Widget (GWidget, whamlet)
-+import Yesod.Widget (GWidget)
- import Yesod.Request (reqToken, reqWaiRequest, reqGetParams, languages)
- import Network.Wai (requestMethod)
--import Text.Hamlet (shamlet)
- import Data.Monoid (mempty)
- import Data.Maybe (listToMaybe, fromMaybe)
- import Yesod.Message (RenderMessage (..))
-diff --git a/evilsplicer-headers.hs b/evilsplicer-headers.hs
-new file mode 100644
-index 0000000..865d043
---- /dev/null
-+++ b/evilsplicer-headers.hs
-@@ -0,0 +1,9 @@
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Text.Hamlet
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified "blaze-markup" Text.Blaze as Text.Blaze.Markup
-+import qualified Yesod.Widget
-+import qualified Data.Foldable
-diff --git a/yesod-form.cabal b/yesod-form.cabal
-index a0d2a80..ae99ddc 100644
---- a/yesod-form.cabal
-+++ b/yesod-form.cabal
-@@ -18,7 +18,7 @@ library
- , yesod-persistent >= 1.1 && < 1.2
- , time >= 1.1.4
- , hamlet >= 1.1 && < 1.2
-- , shakespeare-css >= 1.0 && < 1.1
-+ , shakespeare-css == 1.0.2
- , shakespeare-js >= 1.0.2 && < 1.2
- , persistent >= 1.0 && < 1.2
- , template-haskell
-@@ -37,6 +37,7 @@ library
- , attoparsec >= 0.10 && < 0.11
- , crypto-api >= 0.8 && < 0.11
- , aeson
-+ , shakespeare
-
- exposed-modules: Yesod.Form
- Yesod.Form.Class
-@@ -45,7 +46,6 @@ library
- Yesod.Form.Input
- Yesod.Form.Fields
- Yesod.Form.Jquery
-- Yesod.Form.Nic
- Yesod.Form.MassInput
- Yesod.Form.I18n.English
- Yesod.Form.I18n.Portuguese
-@@ -56,6 +56,7 @@ library
- Yesod.Form.I18n.Japanese
- -- FIXME Yesod.Helpers.Crud
- ghc-options: -Wall
-+ Extensions: PackageImports
-
- test-suite test
- type: exitcode-stdio-1.0
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/yesod-form_1.2.1.1-0002-expand-TH.patch b/standalone/android/haskell-patches/yesod-form_1.2.1.1-0002-expand-TH.patch
deleted file mode 100644
index 3ce48e5fc..000000000
--- a/standalone/android/haskell-patches/yesod-form_1.2.1.1-0002-expand-TH.patch
+++ /dev/null
@@ -1,1606 +0,0 @@
-From f98c22ec71695537e0e008a0bd54affdf8a60f64 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 17:35:57 -0400
-Subject: [PATCH 2/2] expand TH
-
-Used the EvilSplicer, and then some manual fixups, as it is apparently
-buggy. Also a few module import fixes.
----
- Yesod/Form/Fields.hs | 623 ++++++++++++++++++++++++++++++++++++++----------
- Yesod/Form/Functions.hs | 240 +++++++++++++++----
- Yesod/Form/Jquery.hs | 141 ++++++++---
- Yesod/Form/MassInput.hs | 228 ++++++++++++++----
- Yesod/Form/Nic.hs | 59 ++++-
- 5 files changed, 1042 insertions(+), 249 deletions(-)
-
-diff --git a/Yesod/Form/Fields.hs b/Yesod/Form/Fields.hs
-index 7917ce2..db76ea2 100644
---- a/Yesod/Form/Fields.hs
-+++ b/Yesod/Form/Fields.hs
-@@ -46,11 +46,22 @@ module Yesod.Form.Fields
- , optionsEnum
- ) where
-
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified "blaze-markup" Text.Blaze as Text.Blaze.Internal
-+import qualified "blaze-html" Text.Blaze.Html
-+import qualified Yesod.Widget
-+import qualified Text.Css
-+import qualified Control.Monad
-+import qualified Data.Foldable
- import Yesod.Form.Types
- import Yesod.Form.I18n.English
- import Yesod.Form.Functions (parseHelper)
- import Yesod.Handler (getMessageRender)
--import Yesod.Widget (toWidget, whamlet, GWidget)
-+import Yesod.Widget (toWidget, GWidget)
- import Yesod.Message (RenderMessage (renderMessage), SomeMessage (..))
- import Text.Hamlet
- import Text.Blaze (ToMarkup (toMarkup), preEscapedToMarkup, unsafeByteString)
-@@ -108,10 +119,24 @@ intField = Field
- Right (a, "") -> Right a
- _ -> Left $ MsgInvalidInteger s
-
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="number" :isReq:required="" value="#{showVal val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amMY
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"number\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
- where
-@@ -125,10 +150,24 @@ doubleField = Field
- Right (a, "") -> Right a
- _ -> Left $ MsgInvalidNumber s
-
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{showVal val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amNa
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
- where showVal = either id (pack . show)
-@@ -136,10 +175,24 @@ $newline never
- dayField :: RenderMessage master FormMessage => Field sub master Day
- dayField = Field
- { fieldParse = parseHelper $ parseDate . unpack
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="date" :isReq:required="" value="#{showVal val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amNk
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"date\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
- where showVal = either id (pack . show)
-@@ -147,10 +200,23 @@ $newline never
- timeField :: RenderMessage master FormMessage => Field sub master TimeOfDay
- timeField = Field
- { fieldParse = parseHelper parseTime
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} :isReq:required="" value="#{showVal val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amNx
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
- where
-@@ -163,10 +229,18 @@ $newline never
- htmlField :: RenderMessage master FormMessage => Field sub master Html
- htmlField = Field
- { fieldParse = parseHelper $ Right . preEscapedText . sanitizeBalance
-- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
--$newline never
--<textarea id="#{theId}" name="#{name}" *{attrs}>#{showVal val}
--|]
-+ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_amNH
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<textarea id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
-+
- , fieldEnctype = UrlEncoded
- }
- where showVal = either id (pack . renderHtml)
-@@ -192,10 +266,18 @@ instance ToHtml Textarea where
- textareaField :: RenderMessage master FormMessage => Field sub master Textarea
- textareaField = Field
- { fieldParse = parseHelper $ Right . Textarea
-- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
--$newline never
--<textarea id="#{theId}" name="#{name}" *{attrs}>#{either id unTextarea val}
--|]
-+ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_amNQ
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<textarea id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ id (Text.Blaze.Html.toHtml (either id unTextarea val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -203,10 +285,19 @@ hiddenField :: (PathPiece p, RenderMessage master FormMessage)
- => Field sub master p
- hiddenField = Field
- { fieldParse = parseHelper $ maybe (Left MsgValueRequired) Right . fromPathPiece
-- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
--$newline never
--<input type="hidden" id="#{theId}" name="#{name}" *{attrs} value="#{either id toPathPiece val}">
--|]
-+ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_amNZ
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input type=\"hidden\" id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
-+ id (Text.Blaze.Html.toHtml (either id toPathPiece val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -214,20 +305,50 @@ textField :: RenderMessage master FormMessage => Field sub master Text
- textField = Field
- { fieldParse = parseHelper $ Right
- , fieldView = \theId name attrs val isReq ->
-- [whamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required value="#{either id id val}">
--|]
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ toWidget (Text.Blaze.Html.toHtml (either id id val));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
- passwordField :: RenderMessage master FormMessage => Field sub master Text
- passwordField = Field
- { fieldParse = parseHelper $ Right
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="password" :isReq:required="" value="#{either id id val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amOg
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\" type=\"password\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (either id id val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -305,10 +426,24 @@ emailField = Field
- then Right s
- else Left $ MsgInvalidEmail s
- #endif
-- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="email" :isReq:required="" value="#{either id id val}">
--|]
-+ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_amOO
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"email\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (either id id val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -317,20 +452,60 @@ searchField :: RenderMessage master FormMessage => AutoFocus -> Field sub master
- searchField autoFocus = Field
- { fieldParse = parseHelper Right
- , fieldView = \theId name attrs val isReq -> do
-- [whamlet|\
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="search" :isReq:required="" :autoFocus:autofocus="" value="#{either id id val}">
--|]
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"search\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(autoFocus,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " autofocus=\"\""))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ toWidget (Text.Blaze.Html.toHtml (either id id val));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- when autoFocus $ do
- -- we want this javascript to be placed immediately after the field
-- [whamlet|
--$newline never
--<script>if (!('autofocus' in document.createElement('input'))) {document.getElementById('#{theId}').focus();}
--|]
-- toWidget [cassius|
-- #{theId}
-- -webkit-appearance: textfield
-- |]
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<script>if (!('autofocus' in document.createElement('input'))) {document.getElementById('");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "').focus();}</script>") }
-+
-+ toWidget $ \ _render_amP5
-+ -> (Text.Css.CssNoWhitespace
-+ . (foldr ($) []))
-+ [((++)
-+ $ (map
-+ Text.Css.Css
-+ ((((:)
-+ (Text.Css.Css'
-+ (Data.Monoid.mconcat [toCss theId])
-+ [(Data.Monoid.mconcat
-+ [(Text.Css.fromText
-+ . Text.Css.pack)
-+ "-webkit-appearance"],
-+ Data.Monoid.mconcat
-+ [(Text.Css.fromText
-+ . Text.Css.pack)
-+ "textfield"])]))
-+ . (foldr (.) id []))
-+ [])))]
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -341,10 +516,25 @@ urlField = Field
- Nothing -> Left $ MsgInvalidUrl s
- Just _ -> Right s
- , fieldView = \theId name attrs val isReq ->
-- [whamlet|
--$newline never
--<input ##{theId} name=#{name} *{attrs} type=url :isReq:required value=#{either id id val}>
--|]
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"url\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ toWidget (Text.Blaze.Html.toHtml (either id id val));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -353,18 +543,48 @@ selectFieldList = selectField . optionsPairs
-
- selectField :: (Eq a, RenderMessage master FormMessage) => GHandler sub master (OptionList a) -> Field sub master a
- selectField = selectFieldHelper
-- (\theId name attrs inside -> [whamlet|
--$newline never
--<select ##{theId} name=#{name} *{attrs}>^{inside}
--|]) -- outside
-- (\_theId _name isSel -> [whamlet|
--$newline never
--<option value=none :isSel:selected>_{MsgSelectNone}
--|]) -- onOpt
-- (\_theId _name _attrs value isSel text -> [whamlet|
--$newline never
--<option value=#{value} :isSel:selected>#{text}
--|]) -- inside
-+ (\theId name attrs inside -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<select id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ toWidget inside;
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</select>") })
-+ -- outside
-+ (\_theId _name isSel -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<option value=\"none\"");
-+ Text.Hamlet.condH
-+ [(isSel,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ (((Control.Monad.liftM (Text.Blaze.Html.toHtml .))
-+ $ (Yesod.Widget.liftW getMessageRender))
-+ >>= (\ urender_amPs -> toWidget (urender_amPs MsgSelectNone)));
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
-+ -- onOpt
-+ (\_theId _name _attrs value isSel text -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<option value=\"");
-+ toWidget (Text.Blaze.Html.toHtml value);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ Text.Hamlet.condH
-+ [(isSel,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ toWidget (Text.Blaze.Html.toHtml text);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
-+ -- inside
-
- multiSelectFieldList :: (Eq a, RenderMessage master FormMessage, RenderMessage master msg) => [(msg, a)] -> Field sub master [a]
- multiSelectFieldList = multiSelectField . optionsPairs
-@@ -385,12 +605,40 @@ multiSelectField ioptlist =
- view theId name attrs val isReq = do
- opts <- fmap olOptions $ lift ioptlist
- let selOpts = map (id &&& (optselected val)) opts
-- [whamlet|
--$newline never
-- <select ##{theId} name=#{name} :isReq:required multiple *{attrs}>
-- $forall (opt, optsel) <- selOpts
-- <option value=#{optionExternalValue opt} :optsel:selected>#{optionDisplay opt}
-- |]
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<select id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " multiple");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ Data.Foldable.mapM_
-+ (\ (opt_amPV, optsel_amPW)
-+ -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<option value=\"");
-+ toWidget (Text.Blaze.Html.toHtml (optionExternalValue opt_amPV));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ Text.Hamlet.condH
-+ [(optsel_amPW,
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ toWidget (Text.Blaze.Html.toHtml (optionDisplay opt_amPV));
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
-+ selOpts;
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</select>") }
-+
- where
- optselected (Left _) _ = False
- optselected (Right vals) opt = (optionInternalValue opt) `elem` vals
-@@ -400,41 +648,140 @@ radioFieldList = radioField . optionsPairs
-
- radioField :: (Eq a, RenderMessage master FormMessage) => GHandler sub master (OptionList a) -> Field sub master a
- radioField = selectFieldHelper
-- (\theId _name _attrs inside -> [whamlet|
--$newline never
--<div ##{theId}>^{inside}
--|])
-- (\theId name isSel -> [whamlet|
--$newline never
--<label .radio for=#{theId}-none>
-- <div>
-- <input id=#{theId}-none type=radio name=#{name} value=none :isSel:checked>
-- _{MsgSelectNone}
--|])
-- (\theId name attrs value isSel text -> [whamlet|
--$newline never
--<label .radio for=#{theId}-#{value}>
-- <div>
-- <input id=#{theId}-#{value} type=radio name=#{name} value=#{value} :isSel:checked *{attrs}>
-- \#{text}
--|])
-+ (\theId _name _attrs inside -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<div id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\">");
-+ toWidget inside;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
-+
-+ (\theId name isSel -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<label class=\"radio\" for=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "-none\"><div><input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "-none\" type=\"radio\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"none\"");
-+ Text.Hamlet.condH
-+ [(isSel,
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
-+ Nothing;
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ (((Control.Monad.liftM (Text.Blaze.Html.toHtml .))
-+ $ (Yesod.Widget.liftW getMessageRender))
-+ >>= (\ urender_amQa -> toWidget (urender_amQa MsgSelectNone)));
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div></label>") })
-+
-+ (\theId name attrs value isSel text -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<label class=\"radio\" for=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "-");
-+ toWidget (Text.Blaze.Html.toHtml value);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\"><div><input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "-");
-+ toWidget (Text.Blaze.Html.toHtml value);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\" type=\"radio\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
-+ toWidget (Text.Blaze.Html.toHtml value);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ Text.Hamlet.condH
-+ [(isSel,
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
-+ Nothing;
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ toWidget (Text.Blaze.Html.toHtml text);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div></label>") })
-+
-
- boolField :: RenderMessage master FormMessage => Field sub master Bool
- boolField = Field
- { fieldParse = \e _ -> return $ boolParser e
-- , fieldView = \theId name attrs val isReq -> [whamlet|
--$newline never
-- $if not isReq
-- <input id=#{theId}-none *{attrs} type=radio name=#{name} value=none checked>
-- <label for=#{theId}-none>_{MsgSelectNone}
--
-+ , fieldView = \theId name attrs val isReq -> do { Text.Hamlet.condH
-+ [(not isReq,
-+ do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "-none\" type=\"radio\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\" value=\"none\" checked");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "-none\">");
-+ (((Control.Monad.liftM (Text.Blaze.Html.toHtml .))
-+ $ (Yesod.Widget.liftW getMessageRender))
-+ >>= (\ urender_amQx -> toWidget (urender_amQx MsgSelectNone)));
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</label>") })]
-+ Nothing;
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "-yes\" type=\"radio\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"yes\"");
-+ Text.Hamlet.condH
-+ [(showVal id val,
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
-+ Nothing;
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "-yes\">");
-+ (((Control.Monad.liftM (Text.Blaze.Html.toHtml .))
-+ $ (Yesod.Widget.liftW getMessageRender))
-+ >>= (\ urender_amQy -> toWidget (urender_amQy MsgBoolYes)));
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "</label><input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "-no\" type=\"radio\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"no\"");
-+ Text.Hamlet.condH
-+ [(showVal not val,
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
-+ Nothing;
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "-no\">");
-+ (((Control.Monad.liftM (Text.Blaze.Html.toHtml .))
-+ $ (Yesod.Widget.liftW getMessageRender))
-+ >>= (\ urender_amQz -> toWidget (urender_amQz MsgBoolNo)));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "</label>") }
-
--<input id=#{theId}-yes *{attrs} type=radio name=#{name} value=yes :showVal id val:checked>
--<label for=#{theId}-yes>_{MsgBoolYes}
--
--<input id=#{theId}-no *{attrs} type=radio name=#{name} value=no :showVal not val:checked>
--<label for=#{theId}-no>_{MsgBoolNo}
--|]
- , fieldEnctype = UrlEncoded
- }
- where
-@@ -458,10 +805,22 @@ $newline never
- checkBoxField :: RenderMessage m FormMessage => Field s m Bool
- checkBoxField = Field
- { fieldParse = \e _ -> return $ checkBoxParser e
-- , fieldView = \theId name attrs val _ -> [whamlet|
--$newline never
--<input id=#{theId} *{attrs} type=checkbox name=#{name} value=yes :showVal id val:checked>
--|]
-+ , fieldView = \theId name attrs val _ -> do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ toWidget (Text.Blaze.Html.toHtml theId);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\" type=\"checkbox\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"yes\"");
-+ Text.Hamlet.condH
-+ [(showVal id val,
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
-+ Nothing;
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = UrlEncoded
- }
-
-@@ -566,9 +925,21 @@ fileField = Field
- case files of
- [] -> Right Nothing
- file:_ -> Right $ Just file
-- , fieldView = \id' name attrs _ isReq -> toWidget [hamlet|
-- <input id=#{id'} name=#{name} *{attrs} type=file :isReq:required>
-- |]
-+ , fieldView = \id' name attrs _ isReq -> toWidget $ \ _render_amRu
-+ -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml id');
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"file\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
-+ Nothing;
-+ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fieldEnctype = Multipart
- }
-
-@@ -594,10 +965,16 @@ fileAFormReq fs = AForm $ \(master, langs) menvs ints -> do
- { fvLabel = toHtml $ renderMessage master langs $ fsLabel fs
- , fvTooltip = fmap (toHtml . renderMessage master langs) $ fsTooltip fs
- , fvId = id'
-- , fvInput = [whamlet|
--$newline never
--<input type=file name=#{name} ##{id'} *{fsAttrs fs}>
--|]
-+ , fvInput = do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input type=\"file\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\" id=\"");
-+ toWidget (Text.Blaze.Html.toHtml id');
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) (fsAttrs fs));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fvErrors = errs
- , fvRequired = True
- }
-@@ -623,10 +1000,16 @@ fileAFormOpt fs = AForm $ \(master, langs) menvs ints -> do
- { fvLabel = toHtml $ renderMessage master langs $ fsLabel fs
- , fvTooltip = fmap (toHtml . renderMessage master langs) $ fsTooltip fs
- , fvId = id'
-- , fvInput = [whamlet|
--$newline never
--<input type=file name=#{name} ##{id'} *{fsAttrs fs}>
--|]
-+ , fvInput = do { toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input type=\"file\" name=\"");
-+ toWidget (Text.Blaze.Html.toHtml name);
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\" id=\"");
-+ toWidget (Text.Blaze.Html.toHtml id');
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ toWidget ((Text.Hamlet.attrsToHtml . toAttributes) (fsAttrs fs));
-+ toWidget ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- , fvErrors = errs
- , fvRequired = False
- }
-diff --git a/Yesod/Form/Functions.hs b/Yesod/Form/Functions.hs
-index 89eb1e8..54974bb 100644
---- a/Yesod/Form/Functions.hs
-+++ b/Yesod/Form/Functions.hs
-@@ -42,6 +42,15 @@ module Yesod.Form.Functions
- , parseHelper
- ) where
-
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified "blaze-markup" Text.Blaze as Text.Blaze.Markup
-+import qualified Yesod.Widget
-+import qualified Data.Foldable
-+import qualified Text.Hamlet
- import Yesod.Form.Types
- import Data.Text (Text, pack)
- import Control.Arrow (second)
-@@ -191,10 +200,13 @@ postHelper form env = do
- let token =
- case reqToken req of
- Nothing -> mempty
-- Just n -> [shamlet|
--$newline never
--<input type=hidden name=#{tokenKey} value=#{n}>
--|]
-+ Just n -> do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input type=\"hidden\" name=\"");
-+ id (Text.Blaze.Html.toHtml tokenKey);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
-+ id (Text.Blaze.Html.toHtml n);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\">") }
- m <- getYesod
- langs <- languages
- ((res, xml), enctype) <- runFormGeneric (form token) m langs env
-@@ -253,10 +265,11 @@ getKey = "_hasdata"
-
- getHelper :: (Html -> MForm sub master a) -> Maybe (Env, FileEnv) -> GHandler sub master (a, Enctype)
- getHelper form env = do
-- let fragment = [shamlet|
--$newline never
--<input type=hidden name=#{getKey}>
--|]
-+ let fragment = do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input type=\"hidden\" name=\"");
-+ id (Text.Blaze.Html.toHtml getKey);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\">") }
- langs <- languages
- m <- getYesod
- runFormGeneric (form fragment) m langs env
-@@ -270,19 +283,64 @@ renderTable, renderDivs, renderDivsNoLabels :: FormRender sub master a
- renderTable aform fragment = do
- (res, views') <- aFormToForm aform
- let views = views' []
-- let widget = [whamlet|
--$newline never
--\#{fragment}
--$forall view <- views
-- <tr :fvRequired view:.required :not $ fvRequired view:.optional>
-- <td>
-- <label for=#{fvId view}>#{fvLabel view}
-- $maybe tt <- fvTooltip view
-- <div .tooltip>#{tt}
-- <td>^{fvInput view}
-- $maybe err <- fvErrors view
-- <td .errors>#{err}
--|]
-+ let widget = do { Yesod.Widget.toWidget (Text.Blaze.Html.toHtml fragment);
-+ Data.Foldable.mapM_
-+ (\ view_a9GR
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<tr");
-+ Text.Hamlet.condH
-+ [(or [fvRequired view_a9GR, not (fvRequired view_a9GR)],
-+ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " class=\"");
-+ Text.Hamlet.condH
-+ [(fvRequired view_a9GR,
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(not (fvRequired view_a9GR),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "optional"))]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\"") })]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "><td><label for=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvId view_a9GR));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvLabel view_a9GR));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</label>");
-+ Text.Hamlet.maybeH
-+ (fvTooltip view_a9GR)
-+ (\ tt_a9GS
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<div class=\"tooltip\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml tt_a9GS);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</td><td>");
-+ Yesod.Widget.toWidget (fvInput view_a9GR);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</td>");
-+ Text.Hamlet.maybeH
-+ (fvErrors view_a9GR)
-+ (\ err_a9GT
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<td class=\"errors\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml err_a9GT);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</td>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</tr>") })
-+ views }
- return (res, widget)
-
- -- | render a field inside a div
-@@ -295,19 +353,65 @@ renderDivsMaybeLabels :: Bool -> FormRender sub master a
- renderDivsMaybeLabels withLabels aform fragment = do
- (res, views') <- aFormToForm aform
- let views = views' []
-- let widget = [whamlet|
--$newline never
--\#{fragment}
--$forall view <- views
-- <div :fvRequired view:.required :not $ fvRequired view:.optional>
-- $if withLabels
-- <label for=#{fvId view}>#{fvLabel view}
-- $maybe tt <- fvTooltip view
-- <div .tooltip>#{tt}
-- ^{fvInput view}
-- $maybe err <- fvErrors view
-- <div .errors>#{err}
--|]
-+ let widget = do { Yesod.Widget.toWidget (Text.Blaze.Html.toHtml fragment);
-+ Data.Foldable.mapM_
-+ (\ view_a9Hr
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<div");
-+ Text.Hamlet.condH
-+ [(or [fvRequired view_a9Hr, not (fvRequired view_a9Hr)],
-+ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) " class=\"");
-+ Text.Hamlet.condH
-+ [(fvRequired view_a9Hr,
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(not (fvRequired view_a9Hr),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "optional"))]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\"") })]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ Text.Hamlet.condH
-+ [(withLabels,
-+ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<label for=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvId view_a9Hr));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvLabel view_a9Hr));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</label>") })]
-+ Nothing;
-+ Text.Hamlet.maybeH
-+ (fvTooltip view_a9Hr)
-+ (\ tt_a9Hs
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<div class=\"tooltip\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml tt_a9Hs);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget (fvInput view_a9Hr);
-+ Text.Hamlet.maybeH
-+ (fvErrors view_a9Hr)
-+ (\ err_a9Ht
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<div class=\"errors\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml err_a9Ht);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
-+ views }
- return (res, widget)
-
- -- | Render a form using Bootstrap-friendly shamlet syntax.
-@@ -331,19 +435,61 @@ renderBootstrap aform fragment = do
- let views = views' []
- has (Just _) = True
- has Nothing = False
-- let widget = [whamlet|
--$newline never
--\#{fragment}
--$forall view <- views
-- <div .control-group .clearfix :fvRequired view:.required :not $ fvRequired view:.optional :has $ fvErrors view:.error>
-- <label .control-label for=#{fvId view}>#{fvLabel view}
-- <div .controls .input>
-- ^{fvInput view}
-- $maybe tt <- fvTooltip view
-- <span .help-block>#{tt}
-- $maybe err <- fvErrors view
-- <span .help-block>#{err}
--|]
-+ let widget = do { Yesod.Widget.toWidget (Text.Blaze.Html.toHtml fragment);
-+ Data.Foldable.mapM_
-+ (\ view_a9HE
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<div class=\"control-group clearfix ");
-+ Text.Hamlet.condH
-+ [(fvRequired view_a9HE,
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(not (fvRequired view_a9HE),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "optional "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(has (fvErrors view_a9HE),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "error"))]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "\"><label class=\"control-label\" for=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvId view_a9HE));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvLabel view_a9HE));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "</label><div class=\"controls input\">");
-+ Yesod.Widget.toWidget (fvInput view_a9HE);
-+ Text.Hamlet.maybeH
-+ (fvTooltip view_a9HE)
-+ (\ tt_a9HF
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<span class=\"help-block\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml tt_a9HF);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</span>") })
-+ Nothing;
-+ Text.Hamlet.maybeH
-+ (fvErrors view_a9HE)
-+ (\ err_a9HG
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<span class=\"help-block\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml err_a9HG);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</span>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . pack) "</div></div>") })
-+ views }
- return (res, widget)
-
- check :: RenderMessage master msg
-diff --git a/Yesod/Form/Jquery.hs b/Yesod/Form/Jquery.hs
-index 85a0c76..70ac315 100644
---- a/Yesod/Form/Jquery.hs
-+++ b/Yesod/Form/Jquery.hs
-@@ -12,14 +12,22 @@ module Yesod.Form.Jquery
- , Default (..)
- ) where
-
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified "blaze-html" Text.Blaze.Html
-+import qualified Yesod.Widget
-+import qualified Text.Hamlet
-+import qualified Text.Julius
- import Yesod.Handler
- import Yesod.Core (Route)
- import Yesod.Form
- import Yesod.Widget
- import Data.Time (Day)
- import Data.Default
--import Text.Hamlet (shamlet)
--import Text.Julius (julius, rawJS)
-+import Text.Julius (rawJS)
- import Data.Text (Text, pack, unpack)
- import Data.Monoid (mconcat)
- import Yesod.Core (RenderMessage)
-@@ -64,27 +72,75 @@ jqueryDayField jds = Field
- . readMay
- . unpack
- , fieldView = \theId name attrs val isReq -> do
-- toWidget [shamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="date" :isReq:required="" value="#{showVal val}">
--|]
-+ toWidget $ do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"date\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- addScript' urlJqueryJs
- addScript' urlJqueryUiJs
- addStylesheet' urlJqueryUiCss
-- toWidget [julius|
--$(function(){
-- var i = document.getElementById("#{rawJS theId}");
-- if (i.type != "date") {
-- $(i).datepicker({
-- dateFormat:'yy-mm-dd',
-- changeMonth:#{jsBool $ jdsChangeMonth jds},
-- changeYear:#{jsBool $ jdsChangeYear jds},
-- numberOfMonths:#{rawJS $ mos $ jdsNumberOfMonths jds},
-- yearRange:#{toJSON $ jdsYearRange jds}
-- });
-- }
--});
--|]
-+ toWidget $ Text.Julius.asJavascriptUrl
-+ (\ _render_a1esc
-+ -> mconcat
-+ [Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\
-+ \$(function(){\
-+ \ var i = document.getElementById(\""),
-+ Text.Julius.Javascript (Text.Julius.toJavascript (rawJS theId)),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\");\
-+ \ if (i.type != \"date\") {\
-+ \ $(i).datepicker({\
-+ \ 'yy-mm-dd',\
-+ \ changeMonth:"),
-+ Text.Julius.Javascript
-+ (Text.Julius.toJavascript (jsBool (jdsChangeMonth jds))),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ ",\
-+ \ changeYear:"),
-+ Text.Julius.Javascript
-+ (Text.Julius.toJavascript (jsBool (jdsChangeYear jds))),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ ",\
-+ \ numberOfMonths:"),
-+ Text.Julius.Javascript
-+ (Text.Julius.toJavascript (rawJS (mos (jdsNumberOfMonths jds)))),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ ",\
-+ \ yearRange:"),
-+ Text.Julius.Javascript
-+ (Text.Julius.toJavascript (toJSON (jdsYearRange jds))),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\
-+ \ });\
-+ \ }\
-+ \});")])
-+
- , fieldEnctype = UrlEncoded
- }
- where
-@@ -105,16 +161,47 @@ jqueryAutocompleteField :: (RenderMessage master FormMessage, YesodJquery master
- jqueryAutocompleteField src = Field
- { fieldParse = parseHelper $ Right
- , fieldView = \theId name attrs val isReq -> do
-- toWidget [shamlet|
--$newline never
--<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{either id id val}" .autocomplete>
--|]
-+ toWidget $ do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<input class=\"autocomplete\" id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id
-+ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
-+ Text.Hamlet.condH
-+ [(isReq,
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
-+ Nothing;
-+ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
-+ id (Text.Blaze.Html.toHtml (either id id val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
-+
- addScript' urlJqueryJs
- addScript' urlJqueryUiJs
- addStylesheet' urlJqueryUiCss
-- toWidget [julius|
--$(function(){$("##{rawJS theId}").autocomplete({source:"@{src}",minLength:2})});
--|]
-+ toWidget $ Text.Julius.asJavascriptUrl
-+ (\ _render_a1esq
-+ -> mconcat
-+ [Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\
-+ \$(function(){$(\"#"),
-+ Text.Julius.Javascript (Text.Julius.toJavascript (rawJS theId)),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\").autocomplete({source:\""),
-+ Text.Julius.Javascript
-+ (Data.Text.Lazy.Builder.fromText (_render_a1esq src [])),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\",2})});")])
-+
- , fieldEnctype = UrlEncoded
- }
-
-diff --git a/Yesod/Form/MassInput.hs b/Yesod/Form/MassInput.hs
-index 62e89d6..22fdad5 100644
---- a/Yesod/Form/MassInput.hs
-+++ b/Yesod/Form/MassInput.hs
-@@ -9,10 +9,20 @@ module Yesod.Form.MassInput
- , massTable
- ) where
-
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified "blaze-html" Text.Blaze.Html
-+import qualified Yesod.Widget
-+import qualified Data.Text
-+import qualified Text.Hamlet
-+import qualified Data.Foldable
- import Yesod.Form.Types
- import Yesod.Form.Functions
- import Yesod.Form.Fields (boolField)
--import Yesod.Widget (GWidget, whamlet)
-+import Yesod.Widget (GWidget)
- import Yesod.Message (RenderMessage)
- import Yesod.Handler (newIdent, GHandler)
- import Text.Blaze.Html (Html)
-@@ -75,16 +85,27 @@ inputList label fixXml single mdef = formToAForm $ do
- { fvLabel = label
- , fvTooltip = Nothing
- , fvId = theId
-- , fvInput = [whamlet|
--$newline never
--^{fixXml views}
--<p>
-- $forall xml <- xmls
-- ^{xml}
-- <input .count type=hidden name=#{countName} value=#{count}>
-- <input type=checkbox name=#{addName}>
-- Add another row
--|]
-+ , fvInput = do { Yesod.Widget.toWidget (fixXml views);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<p>");
-+ Data.Foldable.mapM_
-+ (\ xml_aOR7 -> Yesod.Widget.toWidget xml_aOR7) xmls;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<input class=\"count\" type=\"hidden\" name=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml countName);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\" value=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml count);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\"><input type=\"checkbox\" name=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml addName);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\">Add another row</p>") }
-+
- , fvErrors = Nothing
- , fvRequired = False
- }])
-@@ -97,10 +118,14 @@ withDelete af = do
- deleteName <- newFormIdent
- (menv, _, _) <- ask
- res <- case menv >>= Map.lookup deleteName . fst of
-- Just ("yes":_) -> return $ Left [whamlet|
--$newline never
--<input type=hidden name=#{deleteName} value=yes>
--|]
-+ Just ("yes":_) -> return $ Left $ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<input type=\"hidden\" name=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml deleteName);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\" value=\"yes\">") }
-+
- _ -> do
- (_, xml2) <- aFormToForm $ areq boolField FieldSettings
- { fsLabel = SomeMessage MsgDelete
-@@ -126,32 +151,149 @@ fixme eithers =
- massDivs, massTable
- :: [[FieldView sub master]]
- -> GWidget sub master ()
--massDivs viewss = [whamlet|
--$newline never
--$forall views <- viewss
-- <fieldset>
-- $forall view <- views
-- <div :fvRequired view:.required :not $ fvRequired view:.optional>
-- <label for=#{fvId view}>#{fvLabel view}
-- $maybe tt <- fvTooltip view
-- <div .tooltip>#{tt}
-- ^{fvInput view}
-- $maybe err <- fvErrors view
-- <div .errors>#{err}
--|]
-+massDivs viewss = Data.Foldable.mapM_
-+ (\ views_aORq
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<fieldset>");
-+ Data.Foldable.mapM_
-+ (\ view_aORr
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<div");
-+ Text.Hamlet.condH
-+ [(or [fvRequired view_aORr, not (fvRequired view_aORr)],
-+ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ " class=\"");
-+ Text.Hamlet.condH
-+ [(fvRequired view_aORr,
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "required "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(not (fvRequired view_aORr),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "optional"))]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\"") })]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "><label for=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvId view_aORr));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvLabel view_aORr));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</label>");
-+ Text.Hamlet.maybeH
-+ (fvTooltip view_aORr)
-+ (\ tt_aORs
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<div class=\"tooltip\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml tt_aORs);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget (fvInput view_aORr);
-+ Text.Hamlet.maybeH
-+ (fvErrors view_aORr)
-+ (\ err_aORt
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<div class=\"errors\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml err_aORt);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</div>") })
-+ views_aORq;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</fieldset>") })
-+ viewss
-+
-+
-+massTable viewss = Data.Foldable.mapM_
-+ (\ views_aORy
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<fieldset><table>");
-+ Data.Foldable.mapM_
-+ (\ view_aORz
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<tr");
-+ Text.Hamlet.condH
-+ [(or [fvRequired view_aORz, not (fvRequired view_aORz)],
-+ do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ " class=\"");
-+ Text.Hamlet.condH
-+ [(fvRequired view_aORz,
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "required "))]
-+ Nothing;
-+ Text.Hamlet.condH
-+ [(not (fvRequired view_aORz),
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "optional"))]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "\"") })]
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "><td><label for=\"");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvId view_aORz));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml (fvLabel view_aORz));
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</label>");
-+ Text.Hamlet.maybeH
-+ (fvTooltip view_aORz)
-+ (\ tt_aORA
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<div class=\"tooltip\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml tt_aORA);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</div>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</td><td>");
-+ Yesod.Widget.toWidget (fvInput view_aORz);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</td>");
-+ Text.Hamlet.maybeH
-+ (fvErrors view_aORz)
-+ (\ err_aORB
-+ -> do { Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "<td class=\"errors\">");
-+ Yesod.Widget.toWidget (Text.Blaze.Html.toHtml err_aORB);
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</td>") })
-+ Nothing;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</tr>") })
-+ views_aORy;
-+ Yesod.Widget.toWidget
-+ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
-+ "</table></fieldset>") })
-+ viewss
-
--massTable viewss = [whamlet|
--$newline never
--$forall views <- viewss
-- <fieldset>
-- <table>
-- $forall view <- views
-- <tr :fvRequired view:.required :not $ fvRequired view:.optional>
-- <td>
-- <label for=#{fvId view}>#{fvLabel view}
-- $maybe tt <- fvTooltip view
-- <div .tooltip>#{tt}
-- <td>^{fvInput view}
-- $maybe err <- fvErrors view
-- <td .errors>#{err}
--|]
-diff --git a/Yesod/Form/Nic.hs b/Yesod/Form/Nic.hs
-index 7c65ce4..357532f 100644
---- a/Yesod/Form/Nic.hs
-+++ b/Yesod/Form/Nic.hs
-@@ -9,13 +9,19 @@ module Yesod.Form.Nic
- , nicHtmlField
- ) where
-
-+import qualified Data.Text.Lazy.Builder
-+import qualified Text.Shakespeare
-+import qualified Data.Monoid
-+import qualified Text.Julius
-+import qualified "blaze-markup" Text.Blaze.Internal
-+import qualified Yesod.Widget
- import Yesod.Handler
- import Yesod.Core (Route, ScriptLoadPosition(..), jsLoader, Yesod)
- import Yesod.Form
- import Yesod.Widget
- import Text.HTML.SanitizeXSS (sanitizeBalance)
--import Text.Hamlet (Html, shamlet)
--import Text.Julius (julius, rawJS)
-+import Text.Hamlet (Html)
-+import Text.Julius (rawJS)
- #if MIN_VERSION_blaze_html(0, 5, 0)
- import Text.Blaze (preEscapedToMarkup)
- import Text.Blaze.Html.Renderer.String (renderHtml)
-@@ -36,20 +42,49 @@ nicHtmlField :: YesodNic master => Field sub master Html
- nicHtmlField = Field
- { fieldParse = \e _ -> return . Right . fmap (preEscapedText . sanitizeBalance) . listToMaybe $ e
- , fieldView = \theId name attrs val _isReq -> do
-- toWidget [shamlet|
--$newline never
-- <textarea id="#{theId}" *{attrs} name="#{name}" .html>#{showVal val}
--|]
-+ toWidget $ do { id
-+ ((Text.Blaze.Internal.preEscapedText . pack)
-+ "<textarea class=\"html\" id=\"");
-+ id (Text.Blaze.Html.toHtml theId);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
-+ id (Text.Blaze.Html.toHtml name);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
-+ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
-+ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
-+ id (Text.Blaze.Html.toHtml (showVal val));
-+ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
-+
- addScript' urlNicEdit
- master <- lift getYesod
- toWidget $
- case jsLoader master of
-- BottomOfHeadBlocking -> [julius|
--bkLib.onDomLoaded(function(){new nicEditor({fullPanel:true}).panelInstance("#{rawJS theId}")});
--|]
-- _ -> [julius|
--(function(){new nicEditor({fullPanel:true}).panelInstance("#{rawJS theId}")})();
--|]
-+ BottomOfHeadBlocking -> Text.Julius.asJavascriptUrl
-+ (\ _render_a1itM
-+ -> Data.Monoid.mconcat
-+ [Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\
-+ \bkLib.onDomLoaded(function(){new nicEditor({true}).panelInstance(\""),
-+ Text.Julius.Javascript (Text.Julius.toJavascript (rawJS theId)),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\")});")])
-+
-+ _ -> Text.Julius.asJavascriptUrl
-+ (\ _render_a1itQ
-+ -> Data.Monoid.mconcat
-+ [Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "(function(){new nicEditor({true}).panelInstance(\""),
-+ Text.Julius.Javascript (Text.Julius.toJavascript (rawJS theId)),
-+ Text.Julius.Javascript
-+ ((Data.Text.Lazy.Builder.fromText
-+ . Text.Shakespeare.pack')
-+ "\")})();")])
-+
- , fieldEnctype = UrlEncoded
- }
- where
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/yesod-form_spliced-TH.patch b/standalone/android/haskell-patches/yesod-form_spliced-TH.patch
new file mode 100644
index 000000000..486d2aaee
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod-form_spliced-TH.patch
@@ -0,0 +1,1783 @@
+From f645acc0efbfcba7715cd2b6734f0e9df98f7020 Mon Sep 17 00:00:00 2001
+From: dummy <dummy@example.com>
+Date: Mon, 11 Nov 2013 01:26:56 +0000
+Subject: [PATCH] update
+
+---
+ Yesod/Form/Fields.hs | 771 +++++++++++++++++++++++++++++++++++------------
+ Yesod/Form/Functions.hs | 237 ++++++++++++---
+ Yesod/Form/Jquery.hs | 125 ++++++--
+ Yesod/Form/MassInput.hs | 233 +++++++++++---
+ Yesod/Form/Nic.hs | 61 +++-
+ yesod-form.cabal | 1 +
+ 6 files changed, 1122 insertions(+), 306 deletions(-)
+
+diff --git a/Yesod/Form/Fields.hs b/Yesod/Form/Fields.hs
+index 0689859..1e9d49b 100644
+--- a/Yesod/Form/Fields.hs
++++ b/Yesod/Form/Fields.hs
+@@ -1,4 +1,3 @@
+-{-# LANGUAGE QuasiQuotes #-}
+ {-# LANGUAGE TypeFamilies #-}
+ {-# LANGUAGE OverloadedStrings #-}
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+@@ -36,15 +35,11 @@ module Yesod.Form.Fields
+ , selectFieldList
+ , radioField
+ , radioFieldList
+- , checkboxesFieldList
+- , checkboxesField
+ , multiSelectField
+ , multiSelectFieldList
+ , Option (..)
+ , OptionList (..)
+ , mkOptionList
+- , optionsPersist
+- , optionsPersistKey
+ , optionsPairs
+ , optionsEnum
+ ) where
+@@ -70,6 +65,15 @@ import Text.HTML.SanitizeXSS (sanitizeBalance)
+ import Control.Monad (when, unless)
+ import Data.Maybe (listToMaybe, fromMaybe)
+
++import qualified Text.Blaze as Text.Blaze.Internal
++import qualified Text.Blaze.Internal
++import qualified Text.Hamlet
++import qualified Yesod.Core.Widget
++import qualified Text.Css
++import qualified Data.Monoid
++import qualified Data.Foldable
++import qualified Control.Monad
++
+ import qualified Blaze.ByteString.Builder.Html.Utf8 as B
+ import Blaze.ByteString.Builder (writeByteString, toLazyByteString)
+ import Blaze.ByteString.Builder.Internal.Write (fromWriteList)
+@@ -82,14 +86,12 @@ import Data.Text (Text, unpack, pack)
+ import qualified Data.Text.Read
+
+ import qualified Data.Map as Map
+-import Yesod.Persist (selectList, runDB, Filter, SelectOpt, Key, YesodPersist, PersistEntity, PersistQuery, YesodDB)
+ import Control.Arrow ((&&&))
+
+ import Control.Applicative ((<$>), (<|>))
+
+ import Data.Attoparsec.Text (Parser, char, string, digit, skipSpace, endOfInput, parseOnly)
+
+-import Yesod.Persist.Core
+
+ defaultFormMessage :: FormMessage -> Text
+ defaultFormMessage = englishFormMessage
+@@ -102,10 +104,24 @@ intField = Field
+ Right (a, "") -> Right a
+ _ -> Left $ MsgInvalidInteger s
+
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="number" :isReq:required="" value="#{showVal val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arOn
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"number\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+ where
+@@ -119,10 +135,24 @@ doubleField = Field
+ Right (a, "") -> Right a
+ _ -> Left $ MsgInvalidNumber s
+
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{showVal val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arOz
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+ where showVal = either id (pack . show)
+@@ -130,10 +160,24 @@ $newline never
+ dayField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Day
+ dayField = Field
+ { fieldParse = parseHelper $ parseDate . unpack
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="date" :isReq:required="" value="#{showVal val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arOJ
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"date\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+ where showVal = either id (pack . show)
+@@ -141,10 +185,23 @@ $newline never
+ timeField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay
+ timeField = Field
+ { fieldParse = parseHelper parseTime
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} :isReq:required="" value="#{showVal val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arOW
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+ where
+@@ -157,10 +214,18 @@ $newline never
+ htmlField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Html
+ htmlField = Field
+ { fieldParse = parseHelper $ Right . preEscapedText . sanitizeBalance
+- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
+-$newline never
+-<textarea id="#{theId}" name="#{name}" *{attrs}>#{showVal val}
+-|]
++ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_arP6
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<textarea id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
++
+ , fieldEnctype = UrlEncoded
+ }
+ where showVal = either id (pack . renderHtml)
+@@ -169,8 +234,6 @@ $newline never
+ -- br-tags.
+ newtype Textarea = Textarea { unTextarea :: Text }
+ deriving (Show, Read, Eq, PersistField, Ord)
+-instance PersistFieldSql Textarea where
+- sqlType _ = SqlString
+ instance ToHtml Textarea where
+ toHtml =
+ unsafeByteString
+@@ -188,10 +251,18 @@ instance ToHtml Textarea where
+ textareaField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Textarea
+ textareaField = Field
+ { fieldParse = parseHelper $ Right . Textarea
+- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
+-$newline never
+-<textarea id="#{theId}" name="#{name}" *{attrs}>#{either id unTextarea val}
+-|]
++ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_arPf
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<textarea id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ id (toHtml (either id unTextarea val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -199,10 +270,19 @@ hiddenField :: (Monad m, PathPiece p, RenderMessage (HandlerSite m) FormMessage)
+ => Field m p
+ hiddenField = Field
+ { fieldParse = parseHelper $ maybe (Left MsgValueRequired) Right . fromPathPiece
+- , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|
+-$newline never
+-<input type="hidden" id="#{theId}" name="#{name}" *{attrs} value="#{either id toPathPiece val}">
+-|]
++ , fieldView = \theId name attrs val _isReq -> toWidget $ \ _render_arPo
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input type=\"hidden\" id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
++ id (toHtml (either id toPathPiece val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -210,20 +290,55 @@ textField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Tex
+ textField = Field
+ { fieldParse = parseHelper $ Right
+ , fieldView = \theId name attrs val isReq ->
+- [whamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required value="#{either id id val}">
+-|]
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
++ Text.Hamlet.condH
++ [(isReq,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (either id id val));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+ passwordField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text
+ passwordField = Field
+ { fieldParse = parseHelper $ Right
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="password" :isReq:required="" value="#{either id id val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arPF
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\" type=\"password\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (either id id val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -295,10 +410,24 @@ emailField = Field
+ case Email.canonicalizeEmail $ encodeUtf8 s of
+ Just e -> Right $ decodeUtf8With lenientDecode e
+ Nothing -> Left $ MsgInvalidEmail s
+- , fieldView = \theId name attrs val isReq -> toWidget [hamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="email" :isReq:required="" value="#{either id id val}">
+-|]
++ , fieldView = \theId name attrs val isReq -> toWidget $ \ _render_arQe
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"email\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (either id id val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -307,20 +436,78 @@ searchField :: Monad m => RenderMessage (HandlerSite m) FormMessage => AutoFocus
+ searchField autoFocus = Field
+ { fieldParse = parseHelper Right
+ , fieldView = \theId name attrs val isReq -> do
+- [whamlet|\
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="search" :isReq:required="" :autoFocus:autofocus="" value="#{either id id val}">
+-|]
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"search\"");
++ Text.Hamlet.condH
++ [(isReq,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ Text.Hamlet.condH
++ [(autoFocus,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " autofocus=\"\""))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (either id id val));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ when autoFocus $ do
+ -- we want this javascript to be placed immediately after the field
+- [whamlet|
+-$newline never
+-<script>if (!('autofocus' in document.createElement('input'))) {document.getElementById('#{theId}').focus();}
+-|]
+- toWidget [cassius|
+- ##{theId}
+- -webkit-appearance: textfield
+- |]
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<script>if (!('autofocus' in document.createElement('input'))) {document.getElementById('");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "').focus();}</script>") }
++
++ toWidget $ \ _render_arQv
++ -> (Text.Css.CssNoWhitespace
++ . (foldr ($) []))
++ [((++)
++ $ (map
++ Text.Css.TopBlock
++ (((Text.Css.Block
++ {Text.Css.blockSelector = Data.Monoid.mconcat
++ [(Text.Css.fromText
++ . Text.Css.pack)
++ "#",
++ toCss theId],
++ Text.Css.blockAttrs = (concat
++ $ ([Text.Css.Attr
++ (Data.Monoid.mconcat
++ [(Text.Css.fromText
++ . Text.Css.pack)
++ "-webkit-appearance"])
++ (Data.Monoid.mconcat
++ [(Text.Css.fromText
++ . Text.Css.pack)
++ "textfield"])]
++ :
++ (map
++ Text.Css.mixinAttrs
++ []))),
++ Text.Css.blockBlocks = (),
++ Text.Css.blockMixins = ()}
++ :)
++ . ((foldr (.) id [])
++ . (concatMap Text.Css.mixinBlocks [] ++)))
++ [])))]
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -331,7 +518,30 @@ urlField = Field
+ Nothing -> Left $ MsgInvalidUrl s
+ Just _ -> Right s
+ , fieldView = \theId name attrs val isReq ->
+- [whamlet|<input ##{theId} name=#{name} *{attrs} type=url :isReq:required value=#{either id id val}>|]
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"url\"");
++ Text.Hamlet.condH
++ [(isReq,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (either id id val));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -344,18 +554,56 @@ selectField :: (Eq a, RenderMessage site FormMessage)
+ => HandlerT site IO (OptionList a)
+ -> Field (HandlerT site IO) a
+ selectField = selectFieldHelper
+- (\theId name attrs inside -> [whamlet|
+-$newline never
+-<select ##{theId} name=#{name} *{attrs}>^{inside}
+-|]) -- outside
+- (\_theId _name isSel -> [whamlet|
+-$newline never
+-<option value=none :isSel:selected>_{MsgSelectNone}
+-|]) -- onOpt
+- (\_theId _name _attrs value isSel text -> [whamlet|
+-$newline never
+-<option value=#{value} :isSel:selected>#{text}
+-|]) -- inside
++ (\theId name attrs inside -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<select id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) inside;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</select>") })
++ -- outside
++ (\_theId _name isSel -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<option value=\"none\"");
++ Text.Hamlet.condH
++ [(isSel,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ ((Control.Monad.liftM (toHtml .) getMessageRender)
++ >>=
++ (\ urender_arQS
++ -> (Yesod.Core.Widget.asWidgetT . toWidget)
++ (urender_arQS MsgSelectNone)));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
++ -- onOpt
++ (\_theId _name _attrs value isSel text -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<option value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml value);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ Text.Hamlet.condH
++ [(isSel,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml text);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
++ -- inside
+
+ multiSelectFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg)
+ => [(msg, a)]
+@@ -378,11 +626,48 @@ multiSelectField ioptlist =
+ view theId name attrs val isReq = do
+ opts <- fmap olOptions $ handlerToWidget ioptlist
+ let selOpts = map (id &&& (optselected val)) opts
+- [whamlet|
+- <select ##{theId} name=#{name} :isReq:required multiple *{attrs}>
+- $forall (opt, optsel) <- selOpts
+- <option value=#{optionExternalValue opt} :optsel:selected>#{optionDisplay opt}
+- |]
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<select id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ Text.Hamlet.condH
++ [(isReq,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " multiple");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ Data.Foldable.mapM_
++ (\ (opt_arRl, optsel_arRm)
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<option value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (optionExternalValue opt_arRl));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ Text.Hamlet.condH
++ [(optsel_arRm,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " selected"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (optionDisplay opt_arRl));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</option>") })
++ selOpts;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</select>") }
++
+ where
+ optselected (Left _) _ = False
+ optselected (Right vals) opt = (optionInternalValue opt) `elem` vals
+@@ -392,67 +677,172 @@ radioFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg)
+ -> Field (HandlerT site IO) a
+ radioFieldList = radioField . optionsPairs
+
+-checkboxesFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg) => [(msg, a)]
+- -> Field (HandlerT site IO) [a]
+-checkboxesFieldList = checkboxesField . optionsPairs
+-
+-checkboxesField :: (Eq a, RenderMessage site FormMessage)
+- => HandlerT site IO (OptionList a)
+- -> Field (HandlerT site IO) [a]
+-checkboxesField ioptlist = (multiSelectField ioptlist)
+- { fieldView =
+- \theId name attrs val isReq -> do
+- opts <- fmap olOptions $ handlerToWidget ioptlist
+- let optselected (Left _) _ = False
+- optselected (Right vals) opt = (optionInternalValue opt) `elem` vals
+- [whamlet|
+- <span ##{theId}>
+- $forall opt <- opts
+- <label>
+- <input type=checkbox name=#{name} value=#{optionExternalValue opt} *{attrs} :optselected val opt:checked>
+- #{optionDisplay opt}
+- |]
+- }
+
+ radioField :: (Eq a, RenderMessage site FormMessage)
+ => HandlerT site IO (OptionList a)
+ -> Field (HandlerT site IO) a
+ radioField = selectFieldHelper
+- (\theId _name _attrs inside -> [whamlet|
+-$newline never
+-<div ##{theId}>^{inside}
+-|])
+- (\theId name isSel -> [whamlet|
+-$newline never
+-<label .radio for=#{theId}-none>
+- <div>
+- <input id=#{theId}-none type=radio name=#{name} value=none :isSel:checked>
+- _{MsgSelectNone}
+-|])
+- (\theId name attrs value isSel text -> [whamlet|
+-$newline never
+-<label .radio for=#{theId}-#{value}>
+- <div>
+- <input id=#{theId}-#{value} type=radio name=#{name} value=#{value} :isSel:checked *{attrs}>
+- \#{text}
+-|])
++ (\theId _name _attrs inside -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<div id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) inside;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
++
++ (\theId name isSel -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<label class=\"radio\" for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "-none\"><div><input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "-none\" type=\"radio\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"none\"");
++ Text.Hamlet.condH
++ [(isSel,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ ((Control.Monad.liftM (toHtml .) getMessageRender)
++ >>=
++ (\ urender_arRA
++ -> (Yesod.Core.Widget.asWidgetT . toWidget)
++ (urender_arRA MsgSelectNone)));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div></label>") })
++
++ (\theId name attrs value isSel text -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<label class=\"radio\" for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "-");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml value);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\"><div><input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "-");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml value);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\" type=\"radio\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml value);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ Text.Hamlet.condH
++ [(isSel,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml text);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div></label>") })
++
+
+ boolField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool
+ boolField = Field
+ { fieldParse = \e _ -> return $ boolParser e
+- , fieldView = \theId name attrs val isReq -> [whamlet|
+-$newline never
+- $if not isReq
+- <input id=#{theId}-none *{attrs} type=radio name=#{name} value=none checked>
+- <label for=#{theId}-none>_{MsgSelectNone}
++ , fieldView = \theId name attrs val isReq -> do { Text.Hamlet.condH
++ [(not isReq,
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "-none\" type=\"radio\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\" value=\"none\" checked");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "-none\">");
++ ((Control.Monad.liftM (toHtml .) getMessageRender)
++ >>=
++ (\ urender_arRX
++ -> (Yesod.Core.Widget.asWidgetT . toWidget)
++ (urender_arRX MsgSelectNone)));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</label>") })]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "-yes\" type=\"radio\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"yes\"");
++ Text.Hamlet.condH
++ [(showVal id val,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "-yes\">");
++ ((Control.Monad.liftM (toHtml .) getMessageRender)
++ >>=
++ (\ urender_arRY
++ -> (Yesod.Core.Widget.asWidgetT . toWidget)
++ (urender_arRY MsgBoolYes)));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "</label><input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "-no\" type=\"radio\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"no\"");
++ Text.Hamlet.condH
++ [(showVal not val,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "-no\">");
++ ((Control.Monad.liftM (toHtml .) getMessageRender)
++ >>=
++ (\ urender_arRZ
++ -> (Yesod.Core.Widget.asWidgetT . toWidget)
++ (urender_arRZ MsgBoolNo)));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</label>") }
+
+-
+-<input id=#{theId}-yes *{attrs} type=radio name=#{name} value=yes :showVal id val:checked>
+-<label for=#{theId}-yes>_{MsgBoolYes}
+-
+-<input id=#{theId}-no *{attrs} type=radio name=#{name} value=no :showVal not val:checked>
+-<label for=#{theId}-no>_{MsgBoolNo}
+-|]
+ , fieldEnctype = UrlEncoded
+ }
+ where
+@@ -478,10 +868,25 @@ $newline never
+ checkBoxField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool
+ checkBoxField = Field
+ { fieldParse = \e _ -> return $ checkBoxParser e
+- , fieldView = \theId name attrs val _ -> [whamlet|
+-$newline never
+-<input id=#{theId} *{attrs} type=checkbox name=#{name} value=yes :showVal id val:checked>
+-|]
++ , fieldView = \theId name attrs val _ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml theId);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\" type=\"checkbox\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"yes\"");
++ Text.Hamlet.condH
++ [(showVal id val,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " checked"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = UrlEncoded
+ }
+
+@@ -525,49 +930,7 @@ optionsPairs opts = do
+ optionsEnum :: (MonadHandler m, Show a, Enum a, Bounded a) => m (OptionList a)
+ optionsEnum = optionsPairs $ map (\x -> (pack $ show x, x)) [minBound..maxBound]
+
+-optionsPersist :: ( YesodPersist site, PersistEntity a
+- , PersistQuery (YesodDB site)
+- , PathPiece (Key a)
+- , PersistEntityBackend a ~ PersistMonadBackend (YesodDB site)
+- , RenderMessage site msg
+- )
+- => [Filter a]
+- -> [SelectOpt a]
+- -> (a -> msg)
+- -> HandlerT site IO (OptionList (Entity a))
+-optionsPersist filts ords toDisplay = fmap mkOptionList $ do
+- mr <- getMessageRender
+- pairs <- runDB $ selectList filts ords
+- return $ map (\(Entity key value) -> Option
+- { optionDisplay = mr (toDisplay value)
+- , optionInternalValue = Entity key value
+- , optionExternalValue = toPathPiece key
+- }) pairs
+-
+--- | An alternative to 'optionsPersist' which returns just the @Key@ instead of
+--- the entire @Entity@.
+---
+--- Since 1.3.2
+-optionsPersistKey
+- :: (YesodPersist site
+- , PersistEntity a
+- , PersistQuery (YesodPersistBackend site (HandlerT site IO))
+- , PathPiece (Key a)
+- , RenderMessage site msg
+- , PersistEntityBackend a ~ PersistMonadBackend (YesodDB site))
+- => [Filter a]
+- -> [SelectOpt a]
+- -> (a -> msg)
+- -> HandlerT site IO (OptionList (Key a))
+-
+-optionsPersistKey filts ords toDisplay = fmap mkOptionList $ do
+- mr <- getMessageRender
+- pairs <- runDB $ selectList filts ords
+- return $ map (\(Entity key value) -> Option
+- { optionDisplay = mr (toDisplay value)
+- , optionInternalValue = key
+- , optionExternalValue = toPathPiece key
+- }) pairs
++
+
+ selectFieldHelper
+ :: (Eq a, RenderMessage site FormMessage)
+@@ -611,9 +974,21 @@ fileField = Field
+ case files of
+ [] -> Right Nothing
+ file:_ -> Right $ Just file
+- , fieldView = \id' name attrs _ isReq -> toWidget [hamlet|
+- <input id=#{id'} name=#{name} *{attrs} type=file :isReq:required>
+- |]
++ , fieldView = \id' name attrs _ isReq -> toWidget $ \ _render_arSN
++ -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml id');
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"file\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required"))]
++ Nothing;
++ id ((Text.Hamlet.attrsToHtml . toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fieldEnctype = Multipart
+ }
+
+@@ -640,10 +1015,20 @@ fileAFormReq fs = AForm $ \(site, langs) menvs ints -> do
+ { fvLabel = toHtml $ renderMessage site langs $ fsLabel fs
+ , fvTooltip = fmap (toHtml . renderMessage site langs) $ fsTooltip fs
+ , fvId = id'
+- , fvInput = [whamlet|
+-$newline never
+-<input type=file name=#{name} ##{id'} *{fsAttrs fs}>
+-|]
++ , fvInput = do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input type=\"file\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml id');
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) (fsAttrs fs));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fvErrors = errs
+ , fvRequired = True
+ }
+@@ -672,10 +1057,20 @@ fileAFormOpt fs = AForm $ \(master, langs) menvs ints -> do
+ { fvLabel = toHtml $ renderMessage master langs $ fsLabel fs
+ , fvTooltip = fmap (toHtml . renderMessage master langs) $ fsTooltip fs
+ , fvId = id'
+- , fvInput = [whamlet|
+-$newline never
+-<input type=file name=#{name} ##{id'} *{fsAttrs fs}>
+-|]
++ , fvInput = do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input type=\"file\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml name);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" id=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml id');
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Hamlet.attrsToHtml . toAttributes) (fsAttrs fs));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ , fvErrors = errs
+ , fvRequired = False
+ }
+diff --git a/Yesod/Form/Functions.hs b/Yesod/Form/Functions.hs
+index 8a36710..c375ae0 100644
+--- a/Yesod/Form/Functions.hs
++++ b/Yesod/Form/Functions.hs
+@@ -59,6 +59,10 @@ import Data.Maybe (listToMaybe, fromMaybe)
+ import qualified Data.Map as Map
+ import qualified Data.Text.Encoding as TE
+ import Control.Arrow (first)
++import qualified Text.Blaze.Internal
++import qualified Yesod.Core.Widget
++import qualified Data.Foldable
++import qualified Text.Hamlet
+
+ -- | Get a unique identifier.
+ newFormIdent :: Monad m => MForm m Text
+@@ -210,7 +214,14 @@ postHelper form env = do
+ let token =
+ case reqToken req of
+ Nothing -> mempty
+- Just n -> [shamlet|<input type=hidden name=#{tokenKey} value=#{n}>|]
++ Just n -> do { id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input type=\"hidden\" name=\"");
++ id (toHtml tokenKey);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" value=\"");
++ id (toHtml n);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\">") }
++
+ m <- getYesod
+ langs <- languages
+ ((res, xml), enctype) <- runFormGeneric (form token) m langs env
+@@ -279,7 +290,12 @@ getHelper :: MonadHandler m
+ -> Maybe (Env, FileEnv)
+ -> m (a, Enctype)
+ getHelper form env = do
+- let fragment = [shamlet|<input type=hidden name=#{getKey}>|]
++ let fragment = do { id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input type=\"hidden\" name=\"");
++ id (toHtml getKey);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\">") }
++
+ langs <- languages
+ m <- getYesod
+ runFormGeneric (form fragment) m langs env
+@@ -293,19 +309,66 @@ renderTable, renderDivs, renderDivsNoLabels :: Monad m => FormRender m a
+ renderTable aform fragment = do
+ (res, views') <- aFormToForm aform
+ let views = views' []
+- let widget = [whamlet|
+-$newline never
+-\#{fragment}
+-$forall view <- views
+- <tr :fvRequired view:.required :not $ fvRequired view:.optional>
+- <td>
+- <label for=#{fvId view}>#{fvLabel view}
+- $maybe tt <- fvTooltip view
+- <div .tooltip>#{tt}
+- <td>^{fvInput view}
+- $maybe err <- fvErrors view
+- <td .errors>#{err}
+-|]
++ let widget = do { (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml fragment);
++ Data.Foldable.mapM_
++ (\ view_aagq
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<tr");
++ Text.Hamlet.condH
++ [(or [fvRequired view_aagq, not (fvRequired view_aagq)],
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " class=\"");
++ Text.Hamlet.condH
++ [(fvRequired view_aagq,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(not (fvRequired view_aagq),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "optional"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"") })]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "><td><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml (fvId view_aagq));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (fvLabel view_aagq));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</label>");
++ Text.Hamlet.maybeH
++ (fvTooltip view_aagq)
++ (\ tt_aagr
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<div class=\"tooltip\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml tt_aagr);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</td><td>");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (fvInput view_aagq);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</td>");
++ Text.Hamlet.maybeH
++ (fvErrors view_aagq)
++ (\ err_aags
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<td class=\"errors\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml err_aags);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</td>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</tr>") })
++ views }
++
+ return (res, widget)
+
+ -- | render a field inside a div
+@@ -318,19 +381,67 @@ renderDivsMaybeLabels :: Monad m => Bool -> FormRender m a
+ renderDivsMaybeLabels withLabels aform fragment = do
+ (res, views') <- aFormToForm aform
+ let views = views' []
+- let widget = [whamlet|
+-$newline never
+-\#{fragment}
+-$forall view <- views
+- <div :fvRequired view:.required :not $ fvRequired view:.optional>
+- $if withLabels
+- <label for=#{fvId view}>#{fvLabel view}
+- $maybe tt <- fvTooltip view
+- <div .tooltip>#{tt}
+- ^{fvInput view}
+- $maybe err <- fvErrors view
+- <div .errors>#{err}
+-|]
++ let widget = do { (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml fragment);
++ Data.Foldable.mapM_
++ (\ view_aagE
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<div");
++ Text.Hamlet.condH
++ [(or [fvRequired view_aagE, not (fvRequired view_aagE)],
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) " class=\"");
++ Text.Hamlet.condH
++ [(fvRequired view_aagE,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(not (fvRequired view_aagE),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "optional"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\"") })]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ Text.Hamlet.condH
++ [(withLabels,
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "<label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml (fvId view_aagE));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (fvLabel view_aagE));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</label>") })]
++ Nothing;
++ Text.Hamlet.maybeH
++ (fvTooltip view_aagE)
++ (\ tt_aagF
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<div class=\"tooltip\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml tt_aagF);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget) (fvInput view_aagE);
++ Text.Hamlet.maybeH
++ (fvErrors view_aagE)
++ (\ err_aagG
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<div class=\"errors\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml err_aagG);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div>") })
++ views }
++
+ return (res, widget)
+
+ -- | Render a form using Bootstrap-friendly shamlet syntax.
+@@ -354,19 +465,63 @@ renderBootstrap aform fragment = do
+ let views = views' []
+ has (Just _) = True
+ has Nothing = False
+- let widget = [whamlet|
+- $newline never
+- \#{fragment}
+- $forall view <- views
+- <div .control-group .clearfix :fvRequired view:.required :not $ fvRequired view:.optional :has $ fvErrors view:.error>
+- <label .control-label for=#{fvId view}>#{fvLabel view}
+- <div .controls .input>
+- ^{fvInput view}
+- $maybe tt <- fvTooltip view
+- <span .help-block>#{tt}
+- $maybe err <- fvErrors view
+- <span .help-block>#{err}
+- |]
++ let widget = do { (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml fragment);
++ Data.Foldable.mapM_
++ (\ view_aagR
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<div class=\"control-group clearfix ");
++ Text.Hamlet.condH
++ [(fvRequired view_aagR,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "required "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(not (fvRequired view_aagR),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "optional "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(has (fvErrors view_aagR),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "error"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "\"><label class=\"control-label\" for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml (fvId view_aagR));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (fvLabel view_aagR));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "</label><div class=\"controls input\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (fvInput view_aagR);
++ Text.Hamlet.maybeH
++ (fvTooltip view_aagR)
++ (\ tt_aagS
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<span class=\"help-block\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml tt_aagS);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</span>") })
++ Nothing;
++ Text.Hamlet.maybeH
++ (fvErrors view_aagR)
++ (\ err_aagT
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<span class=\"help-block\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml err_aagT);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</span>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . pack) "</div></div>") })
++ views }
++
+ return (res, widget)
+
+ check :: (Monad m, RenderMessage (HandlerSite m) msg)
+diff --git a/Yesod/Form/Jquery.hs b/Yesod/Form/Jquery.hs
+index 2c4ae25..4362188 100644
+--- a/Yesod/Form/Jquery.hs
++++ b/Yesod/Form/Jquery.hs
+@@ -12,6 +12,18 @@ module Yesod.Form.Jquery
+ , Default (..)
+ ) where
+
++import qualified Text.Blaze as Text.Blaze.Internal
++import qualified Text.Blaze.Internal
++import qualified Text.Hamlet
++import qualified Yesod.Core.Widget
++import qualified Text.Css
++import qualified Data.Monoid
++import qualified Data.Foldable
++import qualified Control.Monad
++import qualified Text.Julius
++import qualified Data.Text.Lazy.Builder
++import qualified Text.Shakespeare
++
+ import Yesod.Core
+ import Yesod.Form
+ import Data.Time (Day)
+@@ -60,27 +72,59 @@ jqueryDayField jds = Field
+ . readMay
+ . unpack
+ , fieldView = \theId name attrs val isReq -> do
+- toWidget [shamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="date" :isReq:required="" value="#{showVal val}">
+-|]
++ toWidget $ do { id
++ ((Text.Blaze.Internal.preEscapedText . pack) "<input id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"date\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ addScript' urlJqueryJs
+ addScript' urlJqueryUiJs
+ addStylesheet' urlJqueryUiCss
+- toWidget [julius|
+-$(function(){
+- var i = document.getElementById("#{rawJS theId}");
+- if (i.type != "date") {
+- $(i).datepicker({
+- dateFormat:'yy-mm-dd',
+- changeMonth:#{jsBool $ jdsChangeMonth jds},
+- changeYear:#{jsBool $ jdsChangeYear jds},
+- numberOfMonths:#{rawJS $ mos $ jdsNumberOfMonths jds},
+- yearRange:#{toJSON $ jdsYearRange jds}
+- });
+- }
+-});
+-|]
++ toWidget $ Text.Julius.asJavascriptUrl
++ (\ _render_a1lYC
++ -> mconcat
++ [Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\n$(function(){\n var i = document.getElementById(\""),
++ Text.Julius.toJavascript (rawJS theId),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\");\n if (i.type != \"date\") {\n $(i).datepicker({\n dateFormat:'yy-mm-dd',\n changeMonth:"),
++ Text.Julius.toJavascript (jsBool (jdsChangeMonth jds)),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ ",\n changeYear:"),
++ Text.Julius.toJavascript (jsBool (jdsChangeYear jds)),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ ",\n numberOfMonths:"),
++ Text.Julius.toJavascript (rawJS (mos (jdsNumberOfMonths jds))),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ ",\n yearRange:"),
++ Text.Julius.toJavascript (toJSON (jdsYearRange jds)),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\n });\n }\n});")])
++
+ , fieldEnctype = UrlEncoded
+ }
+ where
+@@ -101,16 +145,47 @@ jqueryAutocompleteField :: (RenderMessage site FormMessage, YesodJquery site)
+ jqueryAutocompleteField src = Field
+ { fieldParse = parseHelper $ Right
+ , fieldView = \theId name attrs val isReq -> do
+- toWidget [shamlet|
+-$newline never
+-<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{either id id val}" .autocomplete>
+-|]
++ toWidget $ do { id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<input class=\"autocomplete\" id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id
++ ((Text.Blaze.Internal.preEscapedText . pack) "\" type=\"text\"");
++ Text.Hamlet.condH
++ [(isReq,
++ id ((Text.Blaze.Internal.preEscapedText . pack) " required=\"\""))]
++ Nothing;
++ id ((Text.Blaze.Internal.preEscapedText . pack) " value=\"");
++ id (toHtml (either id id val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">") }
++
+ addScript' urlJqueryJs
+ addScript' urlJqueryUiJs
+ addStylesheet' urlJqueryUiCss
+- toWidget [julius|
+-$(function(){$("##{rawJS theId}").autocomplete({source:"@{src}",minLength:2})});
+-|]
++ toWidget $ Text.Julius.asJavascriptUrl
++ (\ _render_a1lYP
++ -> mconcat
++ [Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\n$(function(){$(\"#"),
++ Text.Julius.toJavascript (rawJS theId),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\").autocomplete({source:\""),
++ Text.Julius.Javascript
++ (Data.Text.Lazy.Builder.fromText
++ (_render_a1lYP src [])),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\",minLength:2})});")])
++
+ , fieldEnctype = UrlEncoded
+ }
+
+diff --git a/Yesod/Form/MassInput.hs b/Yesod/Form/MassInput.hs
+index 332eb66..5015e7b 100644
+--- a/Yesod/Form/MassInput.hs
++++ b/Yesod/Form/MassInput.hs
+@@ -9,6 +9,16 @@ module Yesod.Form.MassInput
+ , massTable
+ ) where
+
++import qualified Data.Text
++import qualified Text.Blaze as Text.Blaze.Internal
++import qualified Text.Blaze.Internal
++import qualified Text.Hamlet
++import qualified Yesod.Core.Widget
++import qualified Text.Css
++import qualified Data.Monoid
++import qualified Data.Foldable
++import qualified Control.Monad
++
+ import Yesod.Form.Types
+ import Yesod.Form.Functions
+ import Yesod.Form.Fields (boolField)
+@@ -70,16 +80,28 @@ inputList label fixXml single mdef = formToAForm $ do
+ { fvLabel = label
+ , fvTooltip = Nothing
+ , fvId = theId
+- , fvInput = [whamlet|
+-$newline never
+-^{fixXml views}
+-<p>
+- $forall xml <- xmls
+- ^{xml}
+- <input .count type=hidden name=#{countName} value=#{count}>
+- <input type=checkbox name=#{addName}>
+- Add another row
+-|]
++ , fvInput = do { (Yesod.Core.Widget.asWidgetT . toWidget) (fixXml views);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<p>");
++ Data.Foldable.mapM_
++ (\ xml_aUS3 -> (Yesod.Core.Widget.asWidgetT . toWidget) xml_aUS3)
++ xmls;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<input class=\"count\" type=\"hidden\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml countName);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\" value=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml count);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\"><input type=\"checkbox\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml addName);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\">Add another row</p>") }
++
+ , fvErrors = Nothing
+ , fvRequired = False
+ }])
+@@ -92,10 +114,14 @@ withDelete af = do
+ deleteName <- newFormIdent
+ (menv, _, _) <- ask
+ res <- case menv >>= Map.lookup deleteName . fst of
+- Just ("yes":_) -> return $ Left [whamlet|
+-$newline never
+-<input type=hidden name=#{deleteName} value=yes>
+-|]
++ Just ("yes":_) -> return $ Left $ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<input type=\"hidden\" name=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml deleteName);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\" value=\"yes\">") }
++
+ _ -> do
+ (_, xml2) <- aFormToForm $ areq boolField FieldSettings
+ { fsLabel = SomeMessage MsgDelete
+@@ -121,32 +147,155 @@ fixme eithers =
+ massDivs, massTable
+ :: [[FieldView site]]
+ -> WidgetT site IO ()
+-massDivs viewss = [whamlet|
+-$newline never
+-$forall views <- viewss
+- <fieldset>
+- $forall view <- views
+- <div :fvRequired view:.required :not $ fvRequired view:.optional>
+- <label for=#{fvId view}>#{fvLabel view}
+- $maybe tt <- fvTooltip view
+- <div .tooltip>#{tt}
+- ^{fvInput view}
+- $maybe err <- fvErrors view
+- <div .errors>#{err}
+-|]
++massDivs viewss = Data.Foldable.mapM_
++ (\ views_aUSm
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<fieldset>");
++ Data.Foldable.mapM_
++ (\ view_aUSn
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<div");
++ Text.Hamlet.condH
++ [(or [fvRequired view_aUSn, not (fvRequired view_aUSn)],
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ " class=\"");
++ Text.Hamlet.condH
++ [(fvRequired view_aUSn,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "required "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(not (fvRequired view_aUSn),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "optional"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\"") })]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml (fvId view_aUSn));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (fvLabel view_aUSn));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</label>");
++ Text.Hamlet.maybeH
++ (fvTooltip view_aUSn)
++ (\ tt_aUSo
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<div class=\"tooltip\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml tt_aUSo);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget) (fvInput view_aUSn);
++ Text.Hamlet.maybeH
++ (fvErrors view_aUSn)
++ (\ err_aUSp
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<div class=\"errors\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml err_aUSp);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</div>") })
++ views_aUSm;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</fieldset>") })
++ viewss
++
++
++massTable viewss = Data.Foldable.mapM_
++ (\ views_aUSu
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<fieldset><table>");
++ Data.Foldable.mapM_
++ (\ view_aUSv
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "<tr");
++ Text.Hamlet.condH
++ [(or [fvRequired view_aUSv, not (fvRequired view_aUSv)],
++ do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ " class=\"");
++ Text.Hamlet.condH
++ [(fvRequired view_aUSv,
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "required "))]
++ Nothing;
++ Text.Hamlet.condH
++ [(not (fvRequired view_aUSv),
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "optional"))]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "\"") })]
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "><td><label for=\"");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (toHtml (fvId view_aUSv));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml (fvLabel view_aUSv));
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</label>");
++ Text.Hamlet.maybeH
++ (fvTooltip view_aUSv)
++ (\ tt_aUSw
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<div class=\"tooltip\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml tt_aUSw);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</div>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</td><td>");
++ (Yesod.Core.Widget.asWidgetT . toWidget) (fvInput view_aUSv);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</td>");
++ Text.Hamlet.maybeH
++ (fvErrors view_aUSv)
++ (\ err_aUSx
++ -> do { (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "<td class=\"errors\">");
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ (toHtml err_aUSx);
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</td>") })
++ Nothing;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "</tr>") })
++ views_aUSu;
++ (Yesod.Core.Widget.asWidgetT . toWidget)
++ ((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
++ "</table></fieldset>") })
++ viewss
+
+-massTable viewss = [whamlet|
+-$newline never
+-$forall views <- viewss
+- <fieldset>
+- <table>
+- $forall view <- views
+- <tr :fvRequired view:.required :not $ fvRequired view:.optional>
+- <td>
+- <label for=#{fvId view}>#{fvLabel view}
+- $maybe tt <- fvTooltip view
+- <div .tooltip>#{tt}
+- <td>^{fvInput view}
+- $maybe err <- fvErrors view
+- <td .errors>#{err}
+-|]
+diff --git a/Yesod/Form/Nic.hs b/Yesod/Form/Nic.hs
+index 2862678..7b49b1a 100644
+--- a/Yesod/Form/Nic.hs
++++ b/Yesod/Form/Nic.hs
+@@ -9,6 +9,19 @@ module Yesod.Form.Nic
+ , nicHtmlField
+ ) where
+
++import qualified Text.Blaze as Text.Blaze.Internal
++import qualified Text.Blaze.Internal
++import qualified Text.Hamlet
++import qualified Yesod.Core.Widget
++import qualified Text.Css
++import qualified Data.Monoid
++import qualified Data.Foldable
++import qualified Control.Monad
++import qualified Text.Julius
++import qualified Data.Text.Lazy.Builder
++import qualified Text.Shakespeare
++
++
+ import Yesod.Core
+ import Yesod.Form
+ import Text.HTML.SanitizeXSS (sanitizeBalance)
+@@ -27,20 +40,48 @@ nicHtmlField :: YesodNic site => Field (HandlerT site IO) Html
+ nicHtmlField = Field
+ { fieldParse = \e _ -> return . Right . fmap (preEscapedToMarkup . sanitizeBalance) . listToMaybe $ e
+ , fieldView = \theId name attrs val _isReq -> do
+- toWidget [shamlet|
+-$newline never
+- <textarea id="#{theId}" *{attrs} name="#{name}" .html>#{showVal val}
+-|]
++ toWidget $ do { id
++ ((Text.Blaze.Internal.preEscapedText . pack)
++ "<textarea class=\"html\" id=\"");
++ id (toHtml theId);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\" name=\"");
++ id (toHtml name);
++ id ((Text.Blaze.Internal.preEscapedText . pack) "\"");
++ id ((Text.Hamlet.attrsToHtml . Text.Hamlet.toAttributes) attrs);
++ id ((Text.Blaze.Internal.preEscapedText . pack) ">");
++ id (toHtml (showVal val));
++ id ((Text.Blaze.Internal.preEscapedText . pack) "</textarea>") }
++
+ addScript' urlNicEdit
+ master <- getYesod
+ toWidget $
+ case jsLoader master of
+- BottomOfHeadBlocking -> [julius|
+-bkLib.onDomLoaded(function(){new nicEditor({fullPanel:true}).panelInstance("#{rawJS theId}")});
+-|]
+- _ -> [julius|
+-(function(){new nicEditor({fullPanel:true}).panelInstance("#{rawJS theId}")})();
+-|]
++ BottomOfHeadBlocking -> Text.Julius.asJavascriptUrl
++ (\ _render_a1qhO
++ -> Data.Monoid.mconcat
++ [Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\nbkLib.onDomLoaded(function(){new nicEditor({true}).panelInstance(\""),
++ Text.Julius.toJavascript (rawJS theId),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\")});")])
++
++ _ -> Text.Julius.asJavascriptUrl
++ (\ _render_a1qhS
++ -> Data.Monoid.mconcat
++ [Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\n(function(){new nicEditor({true}).panelInstance(\""),
++ Text.Julius.toJavascript (rawJS theId),
++ Text.Julius.Javascript
++ ((Data.Text.Lazy.Builder.fromText
++ . Text.Shakespeare.pack')
++ "\")})();")])
++
+ , fieldEnctype = UrlEncoded
+ }
+ where
+diff --git a/yesod-form.cabal b/yesod-form.cabal
+index 39fa680..88ed066 100644
+--- a/yesod-form.cabal
++++ b/yesod-form.cabal
+@@ -19,6 +19,7 @@ library
+ , time >= 1.1.4
+ , hamlet >= 1.1 && < 1.2
+ , shakespeare-css >= 1.0 && < 1.1
++ , shakespeare
+ , shakespeare-js >= 1.0.2 && < 1.3
+ , persistent >= 1.2 && < 1.3
+ , template-haskell
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod-persistent_1.1.0.1_0001-avoid-TH.patch b/standalone/android/haskell-patches/yesod-persistent_1.1.0.1_0001-avoid-TH.patch
deleted file mode 100644
index 6a28b3fd1..000000000
--- a/standalone/android/haskell-patches/yesod-persistent_1.1.0.1_0001-avoid-TH.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 62cc9e3f70d8cea848d56efa198a68527fd07267 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:40:19 -0400
-Subject: [PATCH] avoid TH
-
----
- Yesod/Persist.hs | 2 --
- yesod-persistent.cabal | 1 -
- 2 files changed, 3 deletions(-)
-
-diff --git a/Yesod/Persist.hs b/Yesod/Persist.hs
-index 0646152..5130497 100644
---- a/Yesod/Persist.hs
-+++ b/Yesod/Persist.hs
-@@ -7,11 +7,9 @@ module Yesod.Persist
- , get404
- , getBy404
- , module Database.Persist
-- , module Database.Persist.TH
- ) where
-
- import Database.Persist
--import Database.Persist.TH
- import Control.Monad.Trans.Class (MonadTrans)
-
- import Yesod.Handler
-diff --git a/yesod-persistent.cabal b/yesod-persistent.cabal
-index 111c1b9..07f6e17 100644
---- a/yesod-persistent.cabal
-+++ b/yesod-persistent.cabal
-@@ -16,7 +16,6 @@ library
- build-depends: base >= 4 && < 5
- , yesod-core >= 1.1 && < 1.2
- , persistent >= 1.0 && < 1.2
-- , persistent-template >= 1.0 && < 1.2
- , transformers >= 0.2.2 && < 0.4
- exposed-modules: Yesod.Persist
- ghc-options: -Wall
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/yesod-persistent_do-not-really-build.patch b/standalone/android/haskell-patches/yesod-persistent_do-not-really-build.patch
new file mode 100644
index 000000000..ecccf75ac
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod-persistent_do-not-really-build.patch
@@ -0,0 +1,26 @@
+From 03819615edb1c5f7414768dae84234d6791bd758 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 04:11:46 +0000
+Subject: [PATCH] do not really build
+
+---
+ yesod-persistent.cabal | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/yesod-persistent.cabal b/yesod-persistent.cabal
+index 98c2146..11960cf 100644
+--- a/yesod-persistent.cabal
++++ b/yesod-persistent.cabal
+@@ -23,8 +23,7 @@ library
+ , lifted-base
+ , pool-conduit
+ , resourcet
+- exposed-modules: Yesod.Persist
+- Yesod.Persist.Core
++ exposed-modules:
+ ghc-options: -Wall
+
+ test-suite test
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod-routes_1.1.2_0001-remove-TH-and-export-module-used-by-TH-splices.patch b/standalone/android/haskell-patches/yesod-routes_1.1.2_0001-remove-TH-and-export-module-used-by-TH-splices.patch
deleted file mode 100644
index 33bcff447..000000000
--- a/standalone/android/haskell-patches/yesod-routes_1.1.2_0001-remove-TH-and-export-module-used-by-TH-splices.patch
+++ /dev/null
@@ -1,674 +0,0 @@
-From 06176b0f3dbbe559490f0971e0db205287793286 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 21:01:12 -0400
-Subject: [PATCH] remove TH and export module used by TH splices
-
----
- Yesod/Routes/Overlap.hs | 74 ----------
- Yesod/Routes/Parse.hs | 115 ---------------
- Yesod/Routes/TH.hs | 12 --
- Yesod/Routes/TH/Dispatch.hs | 344 --------------------------------------------
- Yesod/Routes/TH/Types.hs | 16 ---
- yesod-routes.cabal | 21 ---
- 6 files changed, 582 deletions(-)
- delete mode 100644 Yesod/Routes/Overlap.hs
- delete mode 100644 Yesod/Routes/Parse.hs
- delete mode 100644 Yesod/Routes/TH.hs
- delete mode 100644 Yesod/Routes/TH/Dispatch.hs
-
-diff --git a/Yesod/Routes/Overlap.hs b/Yesod/Routes/Overlap.hs
-deleted file mode 100644
-index ae45a02..0000000
---- a/Yesod/Routes/Overlap.hs
-+++ /dev/null
-@@ -1,74 +0,0 @@
---- | Check for overlapping routes.
--module Yesod.Routes.Overlap
-- ( findOverlaps
-- , findOverlapNames
-- , Overlap (..)
-- ) where
--
--import Yesod.Routes.TH.Types
--import Data.List (intercalate)
--
--data Overlap t = Overlap
-- { overlapParents :: [String] -> [String] -- ^ parent resource trees
-- , overlap1 :: ResourceTree t
-- , overlap2 :: ResourceTree t
-- }
--
--findOverlaps :: ([String] -> [String]) -> [ResourceTree t] -> [Overlap t]
--findOverlaps _ [] = []
--findOverlaps front (x:xs) = concatMap (findOverlap front x) xs ++ findOverlaps front xs
--
--findOverlap :: ([String] -> [String]) -> ResourceTree t -> ResourceTree t -> [Overlap t]
--findOverlap front x y =
-- here rest
-- where
-- here
-- | overlaps (resourceTreePieces x) (resourceTreePieces y) (hasSuffix x) (hasSuffix y) = (Overlap front x y:)
-- | otherwise = id
-- rest =
-- case x of
-- ResourceParent name _ children -> findOverlaps (front . (name:)) children
-- ResourceLeaf{} -> []
--
--hasSuffix :: ResourceTree t -> Bool
--hasSuffix (ResourceLeaf r) =
-- case resourceDispatch r of
-- Subsite{} -> True
-- Methods Just{} _ -> True
-- Methods Nothing _ -> False
--hasSuffix ResourceParent{} = True
--
--overlaps :: [(CheckOverlap, Piece t)] -> [(CheckOverlap, Piece t)] -> Bool -> Bool -> Bool
--
---- No pieces on either side, will overlap regardless of suffix
--overlaps [] [] _ _ = True
--
---- No pieces on the left, will overlap if the left side has a suffix
--overlaps [] _ suffixX _ = suffixX
--
---- Ditto for the right
--overlaps _ [] _ suffixY = suffixY
--
---- As soon as we ignore a single piece (via CheckOverlap == False), we say that
---- the routes don't overlap at all. In other words, disabling overlap checking
---- on a single piece disables it on the whole route.
--overlaps ((False, _):_) _ _ _ = False
--overlaps _ ((False, _):_) _ _ = False
--
---- Compare the actual pieces
--overlaps ((True, pieceX):xs) ((True, pieceY):ys) suffixX suffixY =
-- piecesOverlap pieceX pieceY && overlaps xs ys suffixX suffixY
--
--piecesOverlap :: Piece t -> Piece t -> Bool
---- Statics only match if they equal. Dynamics match with anything
--piecesOverlap (Static x) (Static y) = x == y
--piecesOverlap _ _ = True
--
--findOverlapNames :: [ResourceTree t] -> [(String, String)]
--findOverlapNames =
-- map go . findOverlaps id
-- where
-- go (Overlap front x y) =
-- (go' $ resourceTreeName x, go' $ resourceTreeName y)
-- where
-- go' = intercalate "/" . front . return
-diff --git a/Yesod/Routes/Parse.hs b/Yesod/Routes/Parse.hs
-deleted file mode 100644
-index fc16eef..0000000
---- a/Yesod/Routes/Parse.hs
-+++ /dev/null
-@@ -1,115 +0,0 @@
--{-# LANGUAGE TemplateHaskell #-}
--{-# LANGUAGE DeriveDataTypeable #-}
--{-# OPTIONS_GHC -fno-warn-missing-fields #-} -- QuasiQuoter
--module Yesod.Routes.Parse
-- ( parseRoutes
-- , parseRoutesFile
-- , parseRoutesNoCheck
-- , parseRoutesFileNoCheck
-- , parseType
-- ) where
--
--import Language.Haskell.TH.Syntax
--import Data.Char (isUpper)
--import Language.Haskell.TH.Quote
--import qualified System.IO as SIO
--import Yesod.Routes.TH
--import Yesod.Routes.Overlap (findOverlapNames)
--
---- | A quasi-quoter to parse a string into a list of 'Resource's. Checks for
---- overlapping routes, failing if present; use 'parseRoutesNoCheck' to skip the
---- checking. See documentation site for details on syntax.
--parseRoutes :: QuasiQuoter
--parseRoutes = QuasiQuoter { quoteExp = x }
-- where
-- x s = do
-- let res = resourcesFromString s
-- case findOverlapNames res of
-- [] -> lift res
-- z -> error $ "Overlapping routes: " ++ unlines (map show z)
--
--parseRoutesFile :: FilePath -> Q Exp
--parseRoutesFile = parseRoutesFileWith parseRoutes
--
--parseRoutesFileNoCheck :: FilePath -> Q Exp
--parseRoutesFileNoCheck = parseRoutesFileWith parseRoutesNoCheck
--
--parseRoutesFileWith :: QuasiQuoter -> FilePath -> Q Exp
--parseRoutesFileWith qq fp = do
-- s <- qRunIO $ readUtf8File fp
-- quoteExp qq s
--
--readUtf8File :: FilePath -> IO String
--readUtf8File fp = do
-- h <- SIO.openFile fp SIO.ReadMode
-- SIO.hSetEncoding h SIO.utf8_bom
-- SIO.hGetContents h
--
---- | Same as 'parseRoutes', but performs no overlap checking.
--parseRoutesNoCheck :: QuasiQuoter
--parseRoutesNoCheck = QuasiQuoter
-- { quoteExp = lift . resourcesFromString
-- }
--
---- | Convert a multi-line string to a set of resources. See documentation for
---- the format of this string. This is a partial function which calls 'error' on
---- invalid input.
--resourcesFromString :: String -> [ResourceTree String]
--resourcesFromString =
-- fst . parse 0 . lines
-- where
-- parse _ [] = ([], [])
-- parse indent (thisLine:otherLines)
-- | length spaces < indent = ([], thisLine : otherLines)
-- | otherwise = (this others, remainder)
-- where
-- spaces = takeWhile (== ' ') thisLine
-- (others, remainder) = parse indent otherLines'
-- (this, otherLines') =
-- case takeWhile (/= "--") $ words thisLine of
-- [pattern, constr] | last constr == ':' ->
-- let (children, otherLines'') = parse (length spaces + 1) otherLines
-- (pieces, Nothing) = piecesFromString $ drop1Slash pattern
-- in ((ResourceParent (init constr) pieces children :), otherLines'')
-- (pattern:constr:rest) ->
-- let (pieces, mmulti) = piecesFromString $ drop1Slash pattern
-- disp = dispatchFromString rest mmulti
-- in ((ResourceLeaf (Resource constr pieces disp):), otherLines)
-- [] -> (id, otherLines)
-- _ -> error $ "Invalid resource line: " ++ thisLine
--
--dispatchFromString :: [String] -> Maybe String -> Dispatch String
--dispatchFromString rest mmulti
-- | null rest = Methods mmulti []
-- | all (all isUpper) rest = Methods mmulti rest
--dispatchFromString [subTyp, subFun] Nothing =
-- Subsite subTyp subFun
--dispatchFromString [_, _] Just{} =
-- error "Subsites cannot have a multipiece"
--dispatchFromString rest _ = error $ "Invalid list of methods: " ++ show rest
--
--drop1Slash :: String -> String
--drop1Slash ('/':x) = x
--drop1Slash x = x
--
--piecesFromString :: String -> ([(CheckOverlap, Piece String)], Maybe String)
--piecesFromString "" = ([], Nothing)
--piecesFromString x =
-- case (this, rest) of
-- (Left typ, ([], Nothing)) -> ([], Just typ)
-- (Left _, _) -> error "Multipiece must be last piece"
-- (Right piece, (pieces, mtyp)) -> (piece:pieces, mtyp)
-- where
-- (y, z) = break (== '/') x
-- this = pieceFromString y
-- rest = piecesFromString $ drop 1 z
--
--parseType :: String -> Type
--parseType = ConT . mkName -- FIXME handle more complicated stuff
--
--pieceFromString :: String -> Either String (CheckOverlap, Piece String)
--pieceFromString ('#':'!':x) = Right $ (False, Dynamic x)
--pieceFromString ('#':x) = Right $ (True, Dynamic x)
--pieceFromString ('*':x) = Left x
--pieceFromString ('!':x) = Right $ (False, Static x)
--pieceFromString x = Right $ (True, Static x)
-diff --git a/Yesod/Routes/TH.hs b/Yesod/Routes/TH.hs
-deleted file mode 100644
-index 41045b3..0000000
---- a/Yesod/Routes/TH.hs
-+++ /dev/null
-@@ -1,12 +0,0 @@
--{-# LANGUAGE TemplateHaskell #-}
--module Yesod.Routes.TH
-- ( module Yesod.Routes.TH.Types
-- -- * Functions
-- , module Yesod.Routes.TH.RenderRoute
-- -- ** Dispatch
-- , module Yesod.Routes.TH.Dispatch
-- ) where
--
--import Yesod.Routes.TH.Types
--import Yesod.Routes.TH.RenderRoute
--import Yesod.Routes.TH.Dispatch
-diff --git a/Yesod/Routes/TH/Dispatch.hs b/Yesod/Routes/TH/Dispatch.hs
-deleted file mode 100644
-index a52f69a..0000000
---- a/Yesod/Routes/TH/Dispatch.hs
-+++ /dev/null
-@@ -1,344 +0,0 @@
--{-# LANGUAGE TemplateHaskell #-}
--module Yesod.Routes.TH.Dispatch
-- ( -- ** Dispatch
-- mkDispatchClause
-- ) where
--
--import Prelude hiding (exp)
--import Yesod.Routes.TH.Types
--import Language.Haskell.TH.Syntax
--import Data.Maybe (catMaybes)
--import Control.Monad (forM, replicateM)
--import Data.Text (pack)
--import qualified Yesod.Routes.Dispatch as D
--import qualified Data.Map as Map
--import Data.Char (toLower)
--import Web.PathPieces (PathPiece (..), PathMultiPiece (..))
--import Control.Applicative ((<$>))
--import Data.List (foldl')
--
--data FlatResource a = FlatResource [(String, [(CheckOverlap, Piece a)])] String [(CheckOverlap, Piece a)] (Dispatch a)
--
--flatten :: [ResourceTree a] -> [FlatResource a]
--flatten =
-- concatMap (go id)
-- where
-- go front (ResourceLeaf (Resource a b c)) = [FlatResource (front []) a b c]
-- go front (ResourceParent name pieces children) =
-- concatMap (go (front . ((name, pieces):))) children
--
---- |
----
---- This function will generate a single clause that will address all
---- your routing needs. It takes four arguments. The fourth (a list of
---- 'Resource's) is self-explanatory. We\'ll discuss the first
---- three. But first, let\'s cover the terminology.
----
---- Dispatching involves a master type and a sub type. When you dispatch to the
---- top level type, master and sub are the same. Each time to dispatch to
---- another subsite, the sub changes. This requires two changes:
----
---- * Getting the new sub value. This is handled via 'subsiteFunc'.
----
---- * Figure out a way to convert sub routes to the original master route. To
---- address this, we keep a toMaster function, and each time we dispatch to a
---- new subsite, we compose it with the constructor for that subsite.
----
---- Dispatching acts on two different components: the request method and a list
---- of path pieces. If we cannot match the path pieces, we need to return a 404
---- response. If the path pieces match, but the method is not supported, we need
---- to return a 405 response.
----
---- The final result of dispatch is going to be an application type. A simple
---- example would be the WAI Application type. However, our handler functions
---- will need more input: the master/subsite, the toMaster function, and the
---- type-safe route. Therefore, we need to have another type, the handler type,
---- and a function that turns a handler into an application, i.e.
----
---- > runHandler :: handler sub master -> master -> sub -> Route sub -> (Route sub -> Route master) -> app
----
---- This is the first argument to our function. Note that this will almost
---- certainly need to be a method of a typeclass, since it will want to behave
---- differently based on the subsite.
----
---- Note that the 404 response passed in is an application, while the 405
---- response is a handler, since the former can\'t be passed the type-safe
---- route.
----
---- In the case of a subsite, we don\'t directly deal with a handler function.
---- Instead, we redispatch to the subsite, passing on the updated sub value and
---- toMaster function, as well as any remaining, unparsed path pieces. This
---- function looks like:
----
---- > dispatcher :: master -> sub -> (Route sub -> Route master) -> app -> handler sub master -> Text -> [Text] -> app
----
---- Where the parameters mean master, sub, toMaster, 404 response, 405 response,
---- request method and path pieces. This is the second argument of our function.
----
---- Finally, we need a way to decide which of the possible formats
---- should the handler send the data out. Think of each URL holding an
---- abstract object which has multiple representation (JSON, plain HTML
---- etc). Each client might have a preference on which format it wants
---- the abstract object in. For example, a javascript making a request
---- (on behalf of a browser) might prefer a JSON object over a plain
---- HTML file where as a user browsing with javascript disabled would
---- want the page in HTML. The third argument is a function that
---- converts the abstract object to the desired representation
---- depending on the preferences sent by the client.
----
---- The typical values for the first three arguments are,
---- @'yesodRunner'@ for the first, @'yesodDispatch'@ for the second and
---- @fmap 'chooseRep'@.
--
--mkDispatchClause :: Q Exp -- ^ runHandler function
-- -> Q Exp -- ^ dispatcher function
-- -> Q Exp -- ^ fixHandler function
-- -> [ResourceTree a]
-- -> Q Clause
--mkDispatchClause runHandler dispatcher fixHandler ress' = do
-- -- Allocate the names to be used. Start off with the names passed to the
-- -- function itself (with a 0 suffix).
-- --
-- -- We don't reuse names so as to avoid shadowing names (triggers warnings
-- -- with -Wall). Additionally, we want to ensure that none of the code
-- -- passed to toDispatch uses variables from the closure to prevent the
-- -- dispatch data structure from being rebuilt on each run.
-- master0 <- newName "master0"
-- sub0 <- newName "sub0"
-- toMaster0 <- newName "toMaster0"
-- app4040 <- newName "app4040"
-- handler4050 <- newName "handler4050"
-- method0 <- newName "method0"
-- pieces0 <- newName "pieces0"
--
-- -- Name of the dispatch function
-- dispatch <- newName "dispatch"
--
-- -- Dispatch function applied to the pieces
-- let dispatched = VarE dispatch `AppE` VarE pieces0
--
-- -- The 'D.Route's used in the dispatch function
-- routes <- mapM (buildRoute runHandler dispatcher fixHandler) ress
--
-- -- The dispatch function itself
-- toDispatch <- [|D.toDispatch|]
-- let dispatchFun = FunD dispatch [Clause [] (NormalB $ toDispatch `AppE` ListE routes) []]
--
-- -- The input to the clause.
-- let pats = map VarP [master0, sub0, toMaster0, app4040, handler4050, method0, pieces0]
--
-- -- For each resource that dispatches based on methods, build up a map for handling the dispatching.
-- methodMaps <- catMaybes <$> mapM (buildMethodMap fixHandler) ress
--
-- u <- [|case $(return dispatched) of
-- Just f -> f $(return $ VarE master0)
-- $(return $ VarE sub0)
-- $(return $ VarE toMaster0)
-- $(return $ VarE app4040)
-- $(return $ VarE handler4050)
-- $(return $ VarE method0)
-- Nothing -> $(return $ VarE app4040)
-- |]
-- return $ Clause pats (NormalB u) $ dispatchFun : methodMaps
-- where
-- ress = flatten ress'
--
---- | Determine the name of the method map for a given resource name.
--methodMapName :: String -> Name
--methodMapName s = mkName $ "methods" ++ s
--
--buildMethodMap :: Q Exp -- ^ fixHandler
-- -> FlatResource a
-- -> Q (Maybe Dec)
--buildMethodMap _ (FlatResource _ _ _ (Methods _ [])) = return Nothing -- single handle function
--buildMethodMap fixHandler (FlatResource parents name pieces' (Methods mmulti methods)) = do
-- fromList <- [|Map.fromList|]
-- methods' <- mapM go methods
-- let exp = fromList `AppE` ListE methods'
-- let fun = FunD (methodMapName name) [Clause [] (NormalB exp) []]
-- return $ Just fun
-- where
-- pieces = concat $ map snd parents ++ [pieces']
-- go method = do
-- fh <- fixHandler
-- let func = VarE $ mkName $ map toLower method ++ name
-- pack' <- [|pack|]
-- let isDynamic Dynamic{} = True
-- isDynamic _ = False
-- let argCount = length (filter (isDynamic . snd) pieces) + maybe 0 (const 1) mmulti
-- xs <- replicateM argCount $ newName "arg"
-- let rhs = LamE (map VarP xs) $ fh `AppE` (foldl' AppE func $ map VarE xs)
-- return $ TupE [pack' `AppE` LitE (StringL method), rhs]
--buildMethodMap _ (FlatResource _ _ _ Subsite{}) = return Nothing
--
---- | Build a single 'D.Route' expression.
--buildRoute :: Q Exp -> Q Exp -> Q Exp -> FlatResource a -> Q Exp
--buildRoute runHandler dispatcher fixHandler (FlatResource parents name resPieces resDisp) = do
-- -- First two arguments to D.Route
-- routePieces <- ListE <$> mapM (convertPiece . snd) allPieces
-- isMulti <-
-- case resDisp of
-- Methods Nothing _ -> [|False|]
-- _ -> [|True|]
--
-- [|D.Route $(return routePieces) $(return isMulti) $(routeArg3 runHandler dispatcher fixHandler parents name (map snd allPieces) resDisp)|]
-- where
-- allPieces = concat $ map snd parents ++ [resPieces]
--
--routeArg3 :: Q Exp -- ^ runHandler
-- -> Q Exp -- ^ dispatcher
-- -> Q Exp -- ^ fixHandler
-- -> [(String, [(CheckOverlap, Piece a)])]
-- -> String -- ^ name of resource
-- -> [Piece a]
-- -> Dispatch a
-- -> Q Exp
--routeArg3 runHandler dispatcher fixHandler parents name resPieces resDisp = do
-- pieces <- newName "pieces"
--
-- -- Allocate input piece variables (xs) and variables that have been
-- -- converted via fromPathPiece (ys)
-- xs <- forM resPieces $ \piece ->
-- case piece of
-- Static _ -> return Nothing
-- Dynamic _ -> Just <$> newName "x"
--
-- -- Note: the zipping with Ints is just a workaround for (apparently) a bug
-- -- in GHC where the identifiers are considered to be overlapping. Using
-- -- newName should avoid the problem, but it doesn't.
-- ys <- forM (zip (catMaybes xs) [1..]) $ \(x, i) -> do
-- y <- newName $ "y" ++ show (i :: Int)
-- return (x, y)
--
-- -- In case we have multi pieces at the end
-- xrest <- newName "xrest"
-- yrest <- newName "yrest"
--
-- -- Determine the pattern for matching the pieces
-- pat <-
-- case resDisp of
-- Methods Nothing _ -> return $ ListP $ map (maybe WildP VarP) xs
-- _ -> do
-- let cons = mkName ":"
-- return $ foldr (\a b -> ConP cons [maybe WildP VarP a, b]) (VarP xrest) xs
--
-- -- Convert the xs
-- fromPathPiece' <- [|fromPathPiece|]
-- xstmts <- forM ys $ \(x, y) -> return $ BindS (VarP y) (fromPathPiece' `AppE` VarE x)
--
-- -- Convert the xrest if appropriate
-- (reststmts, yrest') <-
-- case resDisp of
-- Methods (Just _) _ -> do
-- fromPathMultiPiece' <- [|fromPathMultiPiece|]
-- return ([BindS (VarP yrest) (fromPathMultiPiece' `AppE` VarE xrest)], [yrest])
-- _ -> return ([], [])
--
-- -- The final expression that actually uses the values we've computed
-- caller <- buildCaller runHandler dispatcher fixHandler xrest parents name resDisp $ map snd ys ++ yrest'
--
-- -- Put together all the statements
-- just <- [|Just|]
-- let stmts = concat
-- [ xstmts
-- , reststmts
-- , [NoBindS $ just `AppE` caller]
-- ]
--
-- errorMsg <- [|error "Invariant violated"|]
-- let matches =
-- [ Match pat (NormalB $ DoE stmts) []
-- , Match WildP (NormalB errorMsg) []
-- ]
--
-- return $ LamE [VarP pieces] $ CaseE (VarE pieces) matches
--
---- | The final expression in the individual Route definitions.
--buildCaller :: Q Exp -- ^ runHandler
-- -> Q Exp -- ^ dispatcher
-- -> Q Exp -- ^ fixHandler
-- -> Name -- ^ xrest
-- -> [(String, [(CheckOverlap, Piece a)])]
-- -> String -- ^ name of resource
-- -> Dispatch a
-- -> [Name] -- ^ ys
-- -> Q Exp
--buildCaller runHandler dispatcher fixHandler xrest parents name resDisp ys = do
-- master <- newName "master"
-- sub <- newName "sub"
-- toMaster <- newName "toMaster"
-- app404 <- newName "_app404"
-- handler405 <- newName "_handler405"
-- method <- newName "_method"
--
-- let pat = map VarP [master, sub, toMaster, app404, handler405, method]
--
-- -- Create the route
-- let route = routeFromDynamics parents name ys
--
-- exp <-
-- case resDisp of
-- Methods _ ms -> do
-- handler <- newName "handler"
--
-- -- Run the whole thing
-- runner <- [|$(runHandler)
-- $(return $ VarE handler)
-- $(return $ VarE master)
-- $(return $ VarE sub)
-- (Just $(return route))
-- $(return $ VarE toMaster)|]
--
-- let myLet handlerExp =
-- LetE [FunD handler [Clause [] (NormalB handlerExp) []]] runner
--
-- if null ms
-- then do
-- -- Just a single handler
-- fh <- fixHandler
-- let he = fh `AppE` foldl' (\a b -> a `AppE` VarE b) (VarE $ mkName $ "handle" ++ name) ys
-- return $ myLet he
-- else do
-- -- Individual methods
-- mf <- [|Map.lookup $(return $ VarE method) $(return $ VarE $ methodMapName name)|]
-- f <- newName "f"
-- let apply = foldl' (\a b -> a `AppE` VarE b) (VarE f) ys
-- let body405 =
-- VarE handler405
-- `AppE` route
-- return $ CaseE mf
-- [ Match (ConP 'Just [VarP f]) (NormalB $ myLet apply) []
-- , Match (ConP 'Nothing []) (NormalB body405) []
-- ]
--
-- Subsite _ getSub -> do
-- let sub2 = foldl' (\a b -> a `AppE` VarE b) (VarE (mkName getSub) `AppE` VarE sub) ys
-- [|$(dispatcher)
-- $(return $ VarE master)
-- $(return sub2)
-- ($(return $ VarE toMaster) . $(return route))
-- $(return $ VarE app404)
-- ($(return $ VarE handler405) . $(return route))
-- $(return $ VarE method)
-- $(return $ VarE xrest)
-- |]
--
-- return $ LamE pat exp
--
---- | Convert a 'Piece' to a 'D.Piece'
--convertPiece :: Piece a -> Q Exp
--convertPiece (Static s) = [|D.Static (pack $(lift s))|]
--convertPiece (Dynamic _) = [|D.Dynamic|]
--
--routeFromDynamics :: [(String, [(CheckOverlap, Piece a)])] -- ^ parents
-- -> String -- ^ constructor name
-- -> [Name]
-- -> Exp
--routeFromDynamics [] name ys = foldl' (\a b -> a `AppE` VarE b) (ConE $ mkName name) ys
--routeFromDynamics ((parent, pieces):rest) name ys =
-- foldl' (\a b -> a `AppE` b) (ConE $ mkName parent) here
-- where
-- (here', ys') = splitAt (length $ filter (isDynamic . snd) pieces) ys
-- isDynamic Dynamic{} = True
-- isDynamic _ = False
-- here = map VarE here' ++ [routeFromDynamics rest name ys']
-diff --git a/Yesod/Routes/TH/Types.hs b/Yesod/Routes/TH/Types.hs
-index 52cd446..18208d3 100644
---- a/Yesod/Routes/TH/Types.hs
-+++ b/Yesod/Routes/TH/Types.hs
-@@ -29,10 +29,6 @@ instance Functor ResourceTree where
- fmap f (ResourceLeaf r) = ResourceLeaf (fmap f r)
- fmap f (ResourceParent a b c) = ResourceParent a (map (second $ fmap f) b) $ map (fmap f) c
-
--instance Lift t => Lift (ResourceTree t) where
-- lift (ResourceLeaf r) = [|ResourceLeaf $(lift r)|]
-- lift (ResourceParent a b c) = [|ResourceParent $(lift a) $(lift b) $(lift c)|]
--
- data Resource typ = Resource
- { resourceName :: String
- , resourcePieces :: [(CheckOverlap, Piece typ)]
-@@ -45,9 +41,6 @@ type CheckOverlap = Bool
- instance Functor Resource where
- fmap f (Resource a b c) = Resource a (map (second $ fmap f) b) (fmap f c)
-
--instance Lift t => Lift (Resource t) where
-- lift (Resource a b c) = [|Resource $(lift a) $(lift b) $(lift c)|]
--
- data Piece typ = Static String | Dynamic typ
- deriving Show
-
-@@ -55,10 +48,6 @@ instance Functor Piece where
- fmap _ (Static s) = (Static s)
- fmap f (Dynamic t) = Dynamic (f t)
-
--instance Lift t => Lift (Piece t) where
-- lift (Static s) = [|Static $(lift s)|]
-- lift (Dynamic t) = [|Dynamic $(lift t)|]
--
- data Dispatch typ =
- Methods
- { methodsMulti :: Maybe typ -- ^ type of the multi piece at the end
-@@ -74,11 +63,6 @@ instance Functor Dispatch where
- fmap f (Methods a b) = Methods (fmap f a) b
- fmap f (Subsite a b) = Subsite (f a) b
-
--instance Lift t => Lift (Dispatch t) where
-- lift (Methods Nothing b) = [|Methods Nothing $(lift b)|]
-- lift (Methods (Just t) b) = [|Methods (Just $(lift t)) $(lift b)|]
-- lift (Subsite t b) = [|Subsite $(lift t) $(lift b)|]
--
- resourceMulti :: Resource typ -> Maybe typ
- resourceMulti Resource { resourceDispatch = Methods (Just t) _ } = Just t
- resourceMulti _ = Nothing
-diff --git a/yesod-routes.cabal b/yesod-routes.cabal
-index eb367b3..dc6a12c 100644
---- a/yesod-routes.cabal
-+++ b/yesod-routes.cabal
-@@ -23,31 +23,10 @@ library
- , path-pieces >= 0.1 && < 0.2
-
- exposed-modules: Yesod.Routes.Dispatch
-- Yesod.Routes.TH
- Yesod.Routes.Class
-- Yesod.Routes.Parse
-- Yesod.Routes.Overlap
-- other-modules: Yesod.Routes.TH.Dispatch
-- Yesod.Routes.TH.RenderRoute
- Yesod.Routes.TH.Types
- ghc-options: -Wall
-
--test-suite runtests
-- type: exitcode-stdio-1.0
-- main-is: main.hs
-- hs-source-dirs: test
-- other-modules: Hierarchy
--
-- build-depends: base >= 4.3 && < 5
-- , yesod-routes
-- , text >= 0.5 && < 0.12
-- , HUnit >= 1.2 && < 1.3
-- , hspec >= 1.3
-- , containers
-- , template-haskell
-- , path-pieces
-- ghc-options: -Wall
--
- source-repository head
- type: git
- location: https://github.com/yesodweb/yesod
---
-1.8.2.rc3
-
diff --git a/standalone/android/haskell-patches/yesod-routes_export-module-referenced-by-TH-splices.patch b/standalone/android/haskell-patches/yesod-routes_export-module-referenced-by-TH-splices.patch
new file mode 100644
index 000000000..e20e3c7f1
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod-routes_export-module-referenced-by-TH-splices.patch
@@ -0,0 +1,29 @@
+From f6bfe8e01d8fe6d129ad3819070aa17934094a0a Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 06:24:09 +0000
+Subject: [PATCH] export module referenced by TH splices
+
+---
+ yesod-routes.cabal | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/yesod-routes.cabal b/yesod-routes.cabal
+index 0b245f2..a97582a 100644
+--- a/yesod-routes.cabal
++++ b/yesod-routes.cabal
+@@ -27,11 +27,11 @@ library
+ Yesod.Routes.Class
+ Yesod.Routes.Parse
+ Yesod.Routes.Overlap
++ Yesod.Routes.TH.Types
+ other-modules: Yesod.Routes.TH.Dispatch
+ Yesod.Routes.TH.RenderRoute
+ Yesod.Routes.TH.ParseRoute
+ Yesod.Routes.TH.RouteAttrs
+- Yesod.Routes.TH.Types
+ ghc-options: -Wall
+
+ test-suite runtests
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod-static_1.1.2-remove-TH.patch b/standalone/android/haskell-patches/yesod-static_1.1.2-remove-TH.patch
deleted file mode 100644
index b0446111b..000000000
--- a/standalone/android/haskell-patches/yesod-static_1.1.2-remove-TH.patch
+++ /dev/null
@@ -1,174 +0,0 @@
-From 476414b04064bb66fc25ba9ca426c309fe5c156e Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Mon, 15 Apr 2013 12:48:13 -0400
-Subject: [PATCH] remove TH
-
----
- Yesod/Static.hs | 121 ----------------------------------------------
- dist/package.conf.inplace | 3 +-
- 2 files changed, 2 insertions(+), 122 deletions(-)
-
-diff --git a/Yesod/Static.hs b/Yesod/Static.hs
-index e8ca09f..193b1f0 100644
---- a/Yesod/Static.hs
-+++ b/Yesod/Static.hs
-@@ -1,5 +1,3 @@
--{-# LANGUAGE QuasiQuotes #-}
--{-# LANGUAGE TemplateHaskell #-}
- {-# LANGUAGE TypeFamilies #-}
- {-# LANGUAGE CPP #-}
- {-# LANGUAGE FlexibleInstances #-}
-@@ -34,11 +32,6 @@ module Yesod.Static
- -- * Smart constructor
- , static
- , staticDevel
-- , embed
-- -- * Template Haskell helpers
-- , staticFiles
-- , staticFilesList
-- , publicFiles
- -- * Hashing
- , base64md5
- #ifdef TEST_EXPORT
-@@ -50,7 +43,6 @@ import Prelude hiding (FilePath)
- import qualified Prelude
- import System.Directory
- import Control.Monad
--import Data.FileEmbed (embedDir)
-
- import Yesod.Core hiding (lift)
-
-@@ -111,18 +103,6 @@ staticDevel dir = do
- hashLookup <- cachedETagLookupDevel dir
- return $ Static $ webAppSettingsWithLookup (F.decodeString dir) hashLookup
-
---- | Produce a 'Static' based on embedding all of the static
---- files' contents in the executable at compile time.
---- Nota Bene: if you replace the scaffolded 'static' call in Settings/StaticFiles.hs
---- you will need to change the scaffolded addStaticContent. Otherwise, some of your
---- assets will be 404'ed. This is because by default yesod will generate compile those
---- assets to @static/tmp@ which for 'static' is fine since they are served out of the
---- directory itself. With embedded static, that will not work.
---- You can easily change @addStaticContent@ to @\_ _ _ -> return Nothing@ as a workaround.
---- This will cause yesod to embed those assets into the generated HTML file itself.
--embed :: Prelude.FilePath -> Q Exp
--embed fp = [|Static (embeddedSettings $(embedDir fp))|]
--
- instance RenderRoute Static where
- -- | A route on the static subsite (see also 'staticFiles').
- --
-@@ -167,59 +147,6 @@ getFileListPieces = flip go id
- dirs' <- mapM (\f -> go (fullPath f) (front . (:) f)) dirs
- return $ concat $ files' : dirs'
-
---- | Template Haskell function that automatically creates routes
---- for all of your static files.
----
---- For example, if you used
----
---- > staticFiles "static/"
----
---- and you had files @\"static\/style.css\"@ and
---- @\"static\/js\/script.js\"@, then the following top-level
---- definitions would be created:
----
---- > style_css = StaticRoute ["style.css"] []
---- > js_script_js = StaticRoute ["js/script.js"] []
----
---- Note that dots (@.@), dashes (@-@) and slashes (@\/@) are
---- replaced by underscores (@\_@) to create valid Haskell
---- identifiers.
--staticFiles :: Prelude.FilePath -> Q [Dec]
--staticFiles dir = mkStaticFiles dir
--
---- | Same as 'staticFiles', but takes an explicit list of files
---- to create identifiers for. The files path given are relative
---- to the static folder. For example, to create routes for the
---- files @\"static\/js\/jquery.js\"@ and
---- @\"static\/css\/normalize.css\"@, you would use:
----
---- > staticFilesList \"static\" [\"js\/jquery.js\", \"css\/normalize.css\"]
----
---- This can be useful when you have a very large number of static
---- files, but only need to refer to a few of them from Haskell.
--staticFilesList :: Prelude.FilePath -> [Prelude.FilePath] -> Q [Dec]
--staticFilesList dir fs =
-- mkStaticFilesList dir (map split fs) "StaticRoute" True
-- where
-- split :: Prelude.FilePath -> [String]
-- split [] = []
-- split x =
-- let (a, b) = break (== '/') x
-- in a : split (drop 1 b)
--
---- | Same as 'staticFiles', but doesn't append an ETag to the
---- query string.
----
---- Using 'publicFiles' will speed up the compilation, since there
---- won't be any need for hashing files during compile-time.
---- However, since the ETag ceases to be part of the URL, the
---- 'Static' subsite won't be able to set the expire date too far
---- on the future. Browsers still will be able to cache the
---- contents, however they'll need send a request to the server to
---- see if their copy is up-to-date.
--publicFiles :: Prelude.FilePath -> Q [Dec]
--publicFiles dir = mkStaticFiles' dir "StaticRoute" False
--
-
- mkHashMap :: Prelude.FilePath -> IO (M.Map F.FilePath S8.ByteString)
- mkHashMap dir = do
-@@ -262,54 +189,6 @@ cachedETagLookup dir = do
- etags <- mkHashMap dir
- return $ (\f -> return $ M.lookup f etags)
-
--mkStaticFiles :: Prelude.FilePath -> Q [Dec]
--mkStaticFiles fp = mkStaticFiles' fp "StaticRoute" True
--
--mkStaticFiles' :: Prelude.FilePath -- ^ static directory
-- -> String -- ^ route constructor "StaticRoute"
-- -> Bool -- ^ append checksum query parameter
-- -> Q [Dec]
--mkStaticFiles' fp routeConName makeHash = do
-- fs <- qRunIO $ getFileListPieces fp
-- mkStaticFilesList fp fs routeConName makeHash
--
--mkStaticFilesList
-- :: Prelude.FilePath -- ^ static directory
-- -> [[String]] -- ^ list of files to create identifiers for
-- -> String -- ^ route constructor "StaticRoute"
-- -> Bool -- ^ append checksum query parameter
-- -> Q [Dec]
--mkStaticFilesList fp fs routeConName makeHash = do
-- concat `fmap` mapM mkRoute fs
-- where
-- replace' c
-- | 'A' <= c && c <= 'Z' = c
-- | 'a' <= c && c <= 'z' = c
-- | '0' <= c && c <= '9' = c
-- | otherwise = '_'
-- mkRoute f = do
-- let name' = intercalate "_" $ map (map replace') f
-- routeName = mkName $
-- case () of
-- ()
-- | null name' -> error "null-named file"
-- | isDigit (head name') -> '_' : name'
-- | isLower (head name') -> name'
-- | otherwise -> '_' : name'
-- f' <- [|map pack $(lift f)|]
-- let route = mkName routeConName
-- pack' <- [|pack|]
-- qs <- if makeHash
-- then do hash <- qRunIO $ base64md5File $ pathFromRawPieces fp f
-- [|[(pack "etag", pack $(lift hash))]|]
-- else return $ ListE []
-- return
-- [ SigD routeName $ ConT route
-- , FunD routeName
-- [ Clause [] (NormalB $ (ConE route) `AppE` f' `AppE` qs) []
-- ]
-- ]
--
- base64md5File :: Prelude.FilePath -> IO String
- base64md5File = fmap (base64 . encode) . hashFile
- where encode d = Data.Serialize.encode (d :: MD5)
diff --git a/standalone/android/haskell-patches/yesod_001_hacked-up-for-Android.patch b/standalone/android/haskell-patches/yesod_001_hacked-up-for-Android.patch
new file mode 100644
index 000000000..23ba50d33
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod_001_hacked-up-for-Android.patch
@@ -0,0 +1,74 @@
+From 8bf7c428a42b984f63f435bb34f22743202ae449 Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 05:24:19 +0000
+Subject: [PATCH] hacked up for Android
+
+---
+ Yesod.hs | 2 --
+ Yesod/Default/Util.hs | 17 -----------------
+ 2 files changed, 19 deletions(-)
+
+diff --git a/Yesod.hs b/Yesod.hs
+index b367144..3050bf5 100644
+--- a/Yesod.hs
++++ b/Yesod.hs
+@@ -5,9 +5,7 @@ module Yesod
+ ( -- * Re-exports from yesod-core
+ module Yesod.Core
+ , module Yesod.Form
+- , module Yesod.Persist
+ ) where
+
+ import Yesod.Core
+ import Yesod.Form
+-import Yesod.Persist
+diff --git a/Yesod/Default/Util.hs b/Yesod/Default/Util.hs
+index a10358e..c5a4e58 100644
+--- a/Yesod/Default/Util.hs
++++ b/Yesod/Default/Util.hs
+@@ -8,7 +8,6 @@ module Yesod.Default.Util
+ , widgetFileNoReload
+ , widgetFileReload
+ , TemplateLanguage (..)
+- , defaultTemplateLanguages
+ , WidgetFileSettings
+ , wfsLanguages
+ , wfsHamletSettings
+@@ -20,9 +19,6 @@ import Yesod.Core -- purposely using complete import so that Haddock will see ad
+ import Control.Monad (when, unless)
+ import System.Directory (doesFileExist, createDirectoryIfMissing)
+ import Language.Haskell.TH.Syntax
+-import Text.Lucius (luciusFile, luciusFileReload)
+-import Text.Julius (juliusFile, juliusFileReload)
+-import Text.Cassius (cassiusFile, cassiusFileReload)
+ import Text.Hamlet (HamletSettings, defaultHamletSettings)
+ import Data.Maybe (catMaybes)
+ import Data.Default (Default (def))
+@@ -69,24 +65,11 @@ data TemplateLanguage = TemplateLanguage
+ , tlReload :: FilePath -> Q Exp
+ }
+
+-defaultTemplateLanguages :: HamletSettings -> [TemplateLanguage]
+-defaultTemplateLanguages hset =
+- [ TemplateLanguage False "hamlet" whamletFile' whamletFile'
+- , TemplateLanguage True "cassius" cassiusFile cassiusFileReload
+- , TemplateLanguage True "julius" juliusFile juliusFileReload
+- , TemplateLanguage True "lucius" luciusFile luciusFileReload
+- ]
+- where
+- whamletFile' = whamletFileWithSettings hset
+-
+ data WidgetFileSettings = WidgetFileSettings
+ { wfsLanguages :: HamletSettings -> [TemplateLanguage]
+ , wfsHamletSettings :: HamletSettings
+ }
+
+-instance Default WidgetFileSettings where
+- def = WidgetFileSettings defaultTemplateLanguages defaultHamletSettings
+-
+ widgetFileNoReload :: WidgetFileSettings -> FilePath -> Q Exp
+ widgetFileNoReload wfs x = combine "widgetFileNoReload" x False $ wfsLanguages wfs $ wfsHamletSettings wfs
+
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod_002_hack-around-missing-symbols.patch b/standalone/android/haskell-patches/yesod_002_hack-around-missing-symbols.patch
new file mode 100644
index 000000000..eaad739e5
--- /dev/null
+++ b/standalone/android/haskell-patches/yesod_002_hack-around-missing-symbols.patch
@@ -0,0 +1,41 @@
+From 7e815b11f242d6836f9615439e32f9937bf2feaf Mon Sep 17 00:00:00 2001
+From: foo <foo@bar>
+Date: Sun, 22 Sep 2013 13:59:34 +0000
+Subject: [PATCH] hack around missing symbols
+
+---
+ Yesod.hs | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/Yesod.hs b/Yesod.hs
+index 3050bf5..fbe309c 100644
+--- a/Yesod.hs
++++ b/Yesod.hs
+@@ -5,7 +5,24 @@ module Yesod
+ ( -- * Re-exports from yesod-core
+ module Yesod.Core
+ , module Yesod.Form
++ , insertBy
++ , replace
++ , deleteBy
++ , delete
++ , insert
++ , Key
+ ) where
+
+ import Yesod.Core
+ import Yesod.Form
++
++-- These symbols are usually imported from persistent,
++-- But it is not built on Android. Still export them
++-- just so that hiding them will work.
++data Key = DummyKey
++insertBy = undefined
++replace = undefined
++deleteBy = undefined
++delete = undefined
++insert = undefined
++
+--
+1.7.10.4
+
diff --git a/standalone/android/haskell-patches/yesod_1.1.8_0001-hacked-up-to-build-on-Android.patch b/standalone/android/haskell-patches/yesod_1.1.8_0001-hacked-up-to-build-on-Android.patch
deleted file mode 100644
index 5a042dc41..000000000
--- a/standalone/android/haskell-patches/yesod_1.1.8_0001-hacked-up-to-build-on-Android.patch
+++ /dev/null
@@ -1,157 +0,0 @@
-From 37abd5d34e18d11ff2961f672cf4491471029684 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Thu, 28 Feb 2013 23:39:18 -0400
-Subject: [PATCH] hacked up to build on Android
-
-removing stuff I don't need and stuff removed from other modules
----
- Yesod.hs | 7 ------
- yesod.cabal | 77 -----------------------------------------------------------
- 2 files changed, 84 deletions(-)
-
-diff --git a/Yesod.hs b/Yesod.hs
-index ef9623d..255ab56 100644
---- a/Yesod.hs
-+++ b/Yesod.hs
-@@ -6,7 +6,6 @@ module Yesod
- module Yesod.Core
- , module Yesod.Form
- , module Yesod.Json
-- , module Yesod.Persist
- -- * Running your application
- , warp
- , warpDebug
-@@ -21,19 +20,14 @@ module Yesod
- , readIntegral
- -- * Hamlet library
- -- ** Hamlet
-- , hamlet
-- , xhamlet
- , HtmlUrl
- , Html
- , toHtml
- -- ** Julius
-- , julius
- , JavascriptUrl
- , renderJavascriptUrl
- , toJSON
- -- ** Cassius/Lucius
-- , cassius
-- , lucius
- , CssUrl
- , renderCssUrl
- ) where
-@@ -46,7 +40,6 @@ import Text.Julius
-
- import Yesod.Form
- import Yesod.Json
--import Yesod.Persist
- import Control.Monad.IO.Class (liftIO, MonadIO(..))
- import Control.Monad.Trans.Control (MonadBaseControl)
-
-diff --git a/yesod.cabal b/yesod.cabal
-index 741f19a..7566cfb 100644
---- a/yesod.cabal
-+++ b/yesod.cabal
-@@ -13,7 +13,6 @@ description:
- The Yesod documentation site <http://www.yesodweb.com/> has much more information, including on the supporting packages mentioned above.
- category: Web, Yesod
- stability: Stable
--cabal-version: >= 1.6
- build-type: Simple
- homepage: http://www.yesodweb.com/
-
-@@ -28,9 +27,7 @@ extra-source-files:
- library
- build-depends: base >= 4.3 && < 5
- , yesod-core >= 1.1.5 && < 1.2
-- , yesod-auth >= 1.1 && < 1.2
- , yesod-json >= 1.1 && < 1.2
-- , yesod-persistent >= 1.1 && < 1.2
- , yesod-form >= 1.1 && < 1.3
- , yesod-default >= 1.1.3 && < 1.2
- , monad-control >= 0.3 && < 0.4
-@@ -48,80 +45,6 @@ library
- exposed-modules: Yesod
- ghc-options: -Wall
-
--executable yesod-ghc-wrapper
-- main-is: ghcwrapper.hs
-- build-depends:
-- base >= 4 && < 5
-- , Cabal
--
--executable yesod-ld-wrapper
-- main-is: ghcwrapper.hs
-- cpp-options: -DLDCMD
-- build-depends:
-- base >= 4 && < 5
-- , Cabal
--executable yesod-ar-wrapper
-- main-is: ghcwrapper.hs
-- cpp-options: -DARCMD
-- build-depends:
-- base >= 4 && < 5
-- , Cabal
--
--executable yesod
-- if os(windows)
-- cpp-options: -DWINDOWS
-- build-depends: base >= 4.3 && < 5
-- , ghc >= 7.0.3 && < 7.8
-- , ghc-paths >= 0.1
-- , parsec >= 2.1 && < 4
-- , text >= 0.11
-- , shakespeare-text >= 1.0 && < 1.1
-- , shakespeare >= 1.0.2 && < 1.1
-- , shakespeare-js >= 1.0.2 && < 1.2
-- , shakespeare-css >= 1.0.2 && < 1.1
-- , bytestring >= 0.9.1.4
-- , time >= 1.1.4
-- , template-haskell
-- , directory >= 1.0
-- , Cabal
-- , unix-compat >= 0.2 && < 0.5
-- , containers >= 0.2
-- , attoparsec >= 0.10
-- , http-types >= 0.7
-- , blaze-builder >= 0.2.1.4 && < 0.4
-- , filepath >= 1.1
-- , process
-- , zlib >= 0.5 && < 0.6
-- , tar >= 0.4 && < 0.5
-- , system-filepath >= 0.4 && < 0.5
-- , system-fileio >= 0.3 && < 0.4
-- , unordered-containers
-- , yaml >= 0.8 && < 0.9
-- , optparse-applicative >= 0.4
-- , fsnotify >= 0.0 && < 0.1
-- , split >= 0.2 && < 0.3
-- , file-embed
-- , conduit >= 0.5 && < 0.6
-- , resourcet >= 0.3 && < 0.5
-- , base64-bytestring
-- , lifted-base
-- , http-reverse-proxy >= 0.1.1
-- , network
-- , http-conduit
-- , network-conduit
-- , project-template >= 0.1.1
--
-- ghc-options: -Wall -threaded
-- main-is: main.hs
-- other-modules: Scaffolding.Scaffolder
-- Devel
-- Build
-- GhcBuild
-- Keter
-- AddHandler
-- Paths_yesod
-- Options
--
- source-repository head
- type: git
- location: https://github.com/yesodweb/yesod
---
-1.7.10.4
-
diff --git a/standalone/android/haskell-patches/zlib_0.5.4.0_0001-hack-to-build-on-Android.patch b/standalone/android/haskell-patches/zlib_0.5.4.0_0001-hack-to-build-on-Android.patch
index 3b74bc26d..a899fb892 100644
--- a/standalone/android/haskell-patches/zlib_0.5.4.0_0001-hack-to-build-on-Android.patch
+++ b/standalone/android/haskell-patches/zlib_0.5.4.0_0001-hack-to-build-on-Android.patch
@@ -30,19 +30,6 @@ index fe851e6..c6168f4 100644
c_deflateInit2_ z a b c d e versionStr (#{const sizeof(z_stream)} :: CInt)
foreign import ccall unsafe "zlib.h deflateSetDictionary"
-diff --git a/zlib.cabal b/zlib.cabal
-index f2d1f5d..751bfab 100644
---- a/zlib.cabal
-+++ b/zlib.cabal
-@@ -36,7 +36,7 @@ library
- other-modules: Codec.Compression.Zlib.Stream
- extensions: CPP, ForeignFunctionInterface
- build-depends: base >= 3 && < 5,
-- bytestring >= 0.9 && < 0.12
-+ bytestring >= 0.10.3.0
- includes: zlib.h
- ghc-options: -Wall
- if !os(windows)
--
1.7.10.4
diff --git a/standalone/android/install-haskell-packages b/standalone/android/install-haskell-packages
index ef43d87c1..f0a4b9113 100755
--- a/standalone/android/install-haskell-packages
+++ b/standalone/android/install-haskell-packages
@@ -1,24 +1,23 @@
-#!/bin/sh
+#!/bin/bash
# Bootstraps from an empty cabal to all the necessary haskell packages
# being installed, with the necessary patches to work on Android.
#
-# Packages are installed at specific versions we have patches for. Newer
-# versions often break cross-compilation by adding TH, etc.
-#
-# Needs some extra C libraries to be installed inside the cross-compiler
-# lib directory: libgnutls libxml2
+# You should install ghc-android first.
#
-# When run with "native" as a parameter, the same versions are installed
-# in the host system. This is needed in order to use the EvilSplicer to
-# expand Template Haskell.
+# Note that the newest version of packages is installed.
+# It attempts to reuse patches for older versions, but
+# new versions of packages often break cross-compilation by adding TH,
+# etc
+#
+# Future work: Convert to using the method used here:
+# https://github.com/kaoskorobase/ghc-ios-cabal-scripts/
-# lib dir
set -e
-if [ "$1" ]; then
- mode="$1"
- shift 1
+if [ ! -d haskell-patches ]; then
+ cd standalone/android
fi
+
cabalopts="$@"
cabalinstall () {
@@ -28,36 +27,32 @@ cabalinstall () {
patched () {
pkg=$1
- version=$2
- if [ "$native" ]; then
- cabalinstall --force-reinstalls $pkg-$version
- else
- shift 2
- cabal unpack $pkg-$version
- cd $pkg-$version
- for patch in ../../haskell-patches/${pkg}_*; do
- echo applying $patch
- patch -p1 < $patch
- done
- cabalinstall "$@"
- cd ..
- fi
-}
-
-unpatched () {
+ shift 1
+ cabal unpack $pkg
+ cd $pkg*
+ git init
+ git config user.name dummy
+ git config user.email dummy@example.com
+ git add .
+ git commit -m "pre-patched state of $pkg"
+ for patch in ../../haskell-patches/${pkg}_*; do
+ echo trying $patch
+ if ! patch -p1 < $patch; then
+ echo "failed to apply $patch"
+ echo "please resolve this, replace the patch with a new version, and exit the subshell to continue"
+ $SHELL
+ fi
+ done
cabalinstall "$@"
+ rm -rf $pkg*
+ cd ..
}
-onlycross () {
- if [ ! "$native" ]; then
- eval "$@"
- fi
-}
-
-onlynative () {
- if [ "$native" ]; then
- eval "$@"
- fi
+installgitannexdeps () {
+ pushd ../..
+ echo cabal install --only-dependencies "$@"
+ cabal install --only-dependencies "$@"
+ popd
}
install_pkgs () {
@@ -65,145 +60,61 @@ install_pkgs () {
mkdir tmp
cd tmp
- onlycross unpatched bytestring-0.10.3.0 text-0.11.3.1 parsec-3.1.3
- patched network 2.4.1.0
- unpatched cereal-0.3.5.2
- patched socks 0.4.2
- unpatched hslogger-1.2.1
- patched MissingH 1.2.0.0
- patched unix-time 0.1.4
- patched async 2.0.1.4
- patched zlib 0.5.4.0
- patched primitive 0.5.0.1
- patched vector 0.10.0.1
- patched distributive 0.3
- unpatched hashable-1.1.2.5
- patched case-insensitive 0.4.0.1
- unpatched nats-0.1 semigroups-0.9 tagged-0.4.4 comonad-3.0.1.1 comonad-transformers-3.0.1
- patched profunctors 3.3
- patched split 0.2.1.2
- unpatched monads-tf-0.1.0.1
- onlycross patched gnutls 0.1.4
- unpatched attoparsec-0.10.4.0 blaze-builder-0.3.1.1
- patched syb 0.3.7
- patched aeson 0.6.1.0
- patched lifted-base 0.2.0.2
- patched resourcet 0.4.4
- patched monad-control 0.3.1.4
- unpatched conduit-0.5.6
- patched monad-logger 0.2.3.2
- unpatched reflection-1.1.7 bifunctors-3.2 semigroupoids-3.0.2
- unpatched bifunctors-3.2 comonads-fd-3.0.1 groupoids-3.0.1.1
- unpatched profunctor-extras-3.3
- patched lens 3.8.5
- unpatched xml-types-0.3.3
- patched libxml-sax 0.7.3
- patched network-conduit 0.6.2.2
- unpatched asn1-data-0.7.1 asn1-types-0.1.3 attoparsec-conduit-0.5.0.3
- unpatched blaze-builder-conduit-0.5.0.3 blaze-markup-0.5.1.5 blaze-html-0.5.1.3
- patched cipher-aes 0.1.7
- unpatched crypto-api-0.10.2
- unpatched cprng-aes-0.3.4
- unpatched http-types-0.8.0 mime-types-0.1.0.3
- patched certificate 1.3.7
- unpatched system-fileio-0.3.11 tls-1.1.2
- unpatched utf8-string-0.3.7
- unpatched publicsuffixlist-0.1
- unpatched xml-conduit-1.0.3.3
- unpatched zlib-bindings-0.1.1.3 zlib-conduit-0.5.0.3
- patched shakespeare 1.0.3
- patched hamlet 1.1.6.1
- patched xml-hamlet 0.4.0.3
- unpatched certificate-1.3.7
- unpatched dataenc-0.12 hxt-charproperties-9.1.1 \
- hxt-regex-xmlschema-9.1.0 hxt-unicode-9.0.2 hxt-9.3.1.1
- unpatched -f-templateHaskell QuickCheck-2.5.1.1
- unpatched Crypto-4.2.5.1
- patched HTTP 4000.2.8
- patched hS3 0.5.7
- patched file-embed 0.0.4.7
- patched gsasl 0.3.5 \
- --ghc-options=-I$HOME/.ghc/android-14/arm-linux-androideabi-4.7/arm-linux-androideabi/sysroot/usr/include/ \
- --ld-options="-L$HOME/.ghc/android-14/arm-linux-androideabi-4.7/arm-linux-androideabi/sysroot/usr/lib/"
- onlycross patched network-protocol-xmpp 0.4.4
- onlynative network-protocol-xmpp
- patched shakespeare-css 1.0.2
- patched shakespeare-i18n 1.0.0.2
- patched shakespeare-js 1.1.2
- patched persistent 1.1.5.1
- onlycross unpatched largeword-1.0.4 crypto-api-0.10.2 http-date-0.0.4 \
- cryptohash-0.8.3 vault-0.2.0.4 unix-compat-0.4.1.1 \
- crypto-conduit-0.4.3 wai-1.3.0.3
- patched wai-app-static 1.3.1
- onlycross patched wai-extra 1.3.2.1
- patched yesod-routes 1.1.2
- onlycross unpatched http-conduit-1.8.7.1
- onlycross patched DAV 0.3
- onlynative unpatched DAV
- patched yesod-core 1.1.8
- patched yesod-persistent 1.1.0.1
- patched yesod-form 1.2.1.1
- onlycross unpatched warp-1.3.7.2 yaml-0.8.2
- patched yesod-default 1.1.3.2
- patched yesod 1.1.8
- patched yesod-static 1.1.2
- unpatched ifelse-0.85
- unpatched SafeSemaphore-0.9.0
- if [ ! "$native" ]; then cabal install bloomfilter-1.2.6.10 --constraint 'bytestring >= 0.10.3.0'; fi
- onlynative unpatched bloomfilter-1.2.6.10
- unpatched edit-distance-0.2.1.2
- unpatched uuid-1.2.12
- unpatched json-0.7
- unpatched SHA-1.6.1
- onlycross unpatched data-endian-0.0.1
- unpatched hinotify-0.3.5
- patched iproute 1.2.11
- unpatched dns 0.3.6
-
- cd ..
- rm -rf tmp
-}
+ patched network
+ patched unix-time
+ patched lifted-base
+ patched zlib
+ patched process
+ patched MissingH
+ patched bloomfilter
+ patched SafeSemaphore
+ patched distributive
+ patched comonad
+ patched HTTP
+ patched MonadCatchIO-transformers
+ patched iproute
+ patched primitive
+ patched socks
+ patched entropy
+ patched vector
+ patched stm-chans
+ patched persistent
+ patched profunctors
+ patched skein
+ patched lens
+ patched persistent-template
+ patched wai-app-static
+ patched shakespeare
+ patched shakespeare-css
+ patched yesod-routes
+ patched yesod-core
+ patched yesod-persistent
+ patched yesod-form
+ patched crypto-numbers
+ patched yesod-auth
+ patched yesod
+ patched async
+ patched gnuidn
+ patched DAV
+ patched language-javascript
+ patched uuid
-native_install () {
- echo "Native install"
- native=1
- if [ ! -e $HOME/.cabal/packages/hackage.haskell.org ]; then
- cabal update
- fi
- install_pkgs
-}
+ cd ..
-cross_path () {
- PATH=$HOME/.ghc/android-14/arm-linux-androideabi-4.7/bin:$HOME/.ghc/android-14/arm-linux-androideabi-4.7/arm-linux-androideabi/bin:$PATH
+ installgitannexdeps -fAndroid -f-Pairing
}
-cross_install () {
- echo "Cross install"
- native=
- cross_path
- if [ ! -e $HOME/.ghc/android-14/arm-linux-androideabi-4.7/cabal/packages/hackage.haskell.org ]; then
- cabal update
- fi
- install_pkgs
-}
+echo
+echo
+echo native build
+echo
+cabal update
+installgitannexdeps
-case "$mode" in
- native)
- native_install
- ;;
- cross)
- cross_install
- ;;
- cleancross)
- # cross install, first removing all currently installed
- # packages except those part of ghc
- rm -f $(grep -l $HOME/.ghc/android-14/arm-linux-androideabi-4.7/.cabal/lib/ $HOME/.ghc/android-14/arm-linux-androideabi-4.7/lib/ghc-*/package.conf.d/*.conf)
- cross_path
- ghc-pkg recache
- cross_install
- ;;
- "")
- cross_install
- native_install
- ;;
-esac
+echo
+echo
+echo cross build
+echo
+PATH=$HOME/.ghc/$(cat abiversion)/bin:$HOME/.ghc/$(cat abiversion)/arm-linux-androideabi/bin:$PATH
+cabal update
+install_pkgs
diff --git a/standalone/android/term.patch b/standalone/android/term.patch
index b83c30e98..5f7d40335 100644
--- a/standalone/android/term.patch
+++ b/standalone/android/term.patch
@@ -501,8 +501,8 @@ index 8a3a4ac..824025d 100644
+
+ /* Reading from the fifo blocks until a url is written
+ * to it. */
-+ BufferedReader buf = new BufferedReader(new FileReader(webAppFifo));
+ while (true) {
++ BufferedReader buf = new BufferedReader(new FileReader(webAppFifo));
+ String s = buf.readLine();
+ try {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(s));
diff --git a/standalone/licences.gz b/standalone/licences.gz
index 1adb9eb4f..422f84225 100644
--- a/standalone/licences.gz
+++ b/standalone/licences.gz
Binary files differ
diff --git a/standalone/windows/build.sh b/standalone/windows/build.sh
index f62bc14a0..56aa58f31 100644
--- a/standalone/windows/build.sh
+++ b/standalone/windows/build.sh
@@ -26,13 +26,6 @@ rm -f git-annex-installer.exe
# for haskell libraries to link them with the cygwin library.
cabal update || true
-rm -rf MissingH-1.2.0.0
-cabal unpack MissingH
-cd MissingH-1.2.0.0
-withcyg patch -p1 <../standalone/windows/haskell-patches/MissingH_1.2.0.0-0001-hack-around-strange-build-problem-in-jenkins-autobui.patch
-cabal install || true
-cd ..
-
cabal install --only-dependencies -f"$FLAGS"
# Detect when the last build was an incremental build and failed,
diff --git a/standalone/windows/haskell-patches/MissingH_1.2.0.0-0001-hack-around-strange-build-problem-in-jenkins-autobui.patch b/standalone/windows/haskell-patches/MissingH_1.2.0.0-0001-hack-around-strange-build-problem-in-jenkins-autobui.patch
deleted file mode 100644
index be18ff23f..000000000
--- a/standalone/windows/haskell-patches/MissingH_1.2.0.0-0001-hack-around-strange-build-problem-in-jenkins-autobui.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 93876dea5befa576c1324e25dcf2135ae1705427 Mon Sep 17 00:00:00 2001
-From: Joey Hess <joey@kitenet.net>
-Date: Fri, 17 May 2013 13:04:56 -0400
-Subject: [PATCH] hack around strange build problem in jenkins autobuilder
-
-src\System\IO\WindowsCompat.hs:123:41:
- Couldn't match expected type `System.Time.ClockTime'
- with actual type `time-1.4:Data.Time.Clock.UTC.UTCTime'
- In the first argument of `clockTimeToEpoch', namely `modct'
- In the expression: clockTimeToEpoch modct
- In an equation for `epochtime': epochtime = clockTimeToEpoch modct
-
-But it works on Windows here..
----
- src/System/IO/WindowsCompat.hs | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
-
-diff --git a/src/System/IO/WindowsCompat.hs b/src/System/IO/WindowsCompat.hs
-index 473490d..0eea21b 100644
---- a/src/System/IO/WindowsCompat.hs
-+++ b/src/System/IO/WindowsCompat.hs
-@@ -120,8 +119,10 @@ getFileStatus fp =
- do isfile <- doesFileExist fp
- isdir <- doesDirectoryExist fp
- perms <- getPermissions fp
-+ {-
- modct <- getModificationTime fp
-- let epochtime = clockTimeToEpoch modct
-+ let epochtime = clockTimeToEpoch $ modct
-+ -}
- return $ FileStatusCompat {deviceID = -1,
- fileID = -1,
- fileMode = if isfile then regularFileMode
-@@ -131,8 +132,8 @@ getFileStatus fp =
- fileGroup = 0,
- specialDeviceID = -1,
- fileSize = 0, -- fixme: hFileSize?
-- accessTime = fromInteger epochtime,
-- modificationTime = fromInteger epochtime,
-- statusChangeTime = fromInteger epochtime
-+ accessTime = undefined, -- fromInteger epochtime,
-+ modificationTime = undefined, -- fromInteger epochtime,
-+ statusChangeTime = undefined -- fromInteger epochtime
- }
- #endif
---
-1.8.3.rc1
-