motion-yapper 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -1
  4. data/lib/yapper.rb +3 -3
  5. data/lib/yapper/db.rb +61 -4
  6. data/lib/yapper/document/persistence.rb +4 -0
  7. data/lib/yapper/document/selection.rb +13 -0
  8. data/lib/yapper/version.rb +1 -1
  9. data/motion-yapper.gemspec +1 -1
  10. data/spec/integration/search_spec.rb +111 -0
  11. data/vendor/Podfile.lock +11 -7
  12. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.bridgesupport +16 -2
  13. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.h +10 -7
  14. data/vendor/YapDatabaseRubyMotion/YapDatabaseRubyMotion.m +20 -2
  15. metadata +19 -297
  16. data/vendor/Pods/.build/libPods-CocoaLumberjack.a +0 -0
  17. data/vendor/Pods/.build/libPods-NSData+MD5Digest.a +0 -0
  18. data/vendor/Pods/.build/libPods-YapDatabase.a +0 -0
  19. data/vendor/Pods/.build/libPods.a +0 -0
  20. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDASLLogger.h +0 -41
  21. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDAbstractDatabaseLogger.h +0 -102
  22. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDContextFilterLogFormatter.h +0 -63
  23. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDDispatchQueueLogFormatter.h +0 -128
  24. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDFileLogger.h +0 -369
  25. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog+LOGV.h +0 -99
  26. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDLog.h +0 -634
  27. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDMultiFormatter.h +0 -30
  28. data/vendor/Pods/BuildHeaders/CocoaLumberjack/DDTTYLogger.h +0 -181
  29. data/vendor/Pods/BuildHeaders/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  30. data/vendor/Pods/BuildHeaders/YapDatabase/NSDictionary+YapDatabase.h +0 -8
  31. data/vendor/Pods/BuildHeaders/YapDatabase/YapCache.h +0 -91
  32. data/vendor/Pods/BuildHeaders/YapDatabase/YapCollectionKey.h +0 -23
  33. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabase.h +0 -547
  34. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnection.h +0 -449
  35. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseConnectionState.h +0 -29
  36. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseDefaults.h +0 -37
  37. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtension.h +0 -15
  38. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionConnection.h +0 -11
  39. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionPrivate.h +0 -444
  40. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseExtensionTransaction.h +0 -11
  41. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredView.h +0 -81
  42. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewConnection.h +0 -12
  43. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewPrivate.h +0 -17
  44. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTransaction.h +0 -39
  45. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFilteredViewTypes.h +0 -32
  46. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearch.h +0 -89
  47. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchConnection.h +0 -32
  48. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchPrivate.h +0 -77
  49. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  50. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseFullTextSearchTransaction.h +0 -68
  51. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseLogging.h +0 -158
  52. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseManager.h +0 -17
  53. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabasePrivate.h +0 -446
  54. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseQuery.h +0 -42
  55. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationship.h +0 -35
  56. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipConnection.h +0 -29
  57. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdge.h +0 -163
  58. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipEdgePrivate.h +0 -79
  59. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipNode.h +0 -99
  60. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipOptions.h +0 -59
  61. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipPrivate.h +0 -125
  62. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseRelationshipTransaction.h +0 -384
  63. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndex.h +0 -149
  64. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexConnection.h +0 -33
  65. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexPrivate.h +0 -83
  66. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetup.h +0 -33
  67. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexSetupPrivate.h +0 -18
  68. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +0 -58
  69. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseStatement.h +0 -13
  70. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseString.h +0 -121
  71. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseTransaction.h +0 -651
  72. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseView.h +0 -127
  73. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChange.h +0 -272
  74. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewChangePrivate.h +0 -94
  75. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewConnection.h +0 -116
  76. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappings.h +0 -842
  77. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewMappingsPrivate.h +0 -72
  78. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewOptions.h +0 -63
  79. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPage.h +0 -36
  80. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPageMetadata.h +0 -27
  81. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewPrivate.h +0 -170
  82. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptions.h +0 -330
  83. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewRangeOptionsPrivate.h +0 -17
  84. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTransaction.h +0 -498
  85. data/vendor/Pods/BuildHeaders/YapDatabase/YapDatabaseViewTypes.h +0 -99
  86. data/vendor/Pods/BuildHeaders/YapDatabase/YapMemoryTable.h +0 -74
  87. data/vendor/Pods/BuildHeaders/YapDatabase/YapNull.h +0 -17
  88. data/vendor/Pods/BuildHeaders/YapDatabase/YapSet.h +0 -41
  89. data/vendor/Pods/BuildHeaders/YapDatabase/YapTouch.h +0 -15
  90. data/vendor/Pods/CocoaLumberjack/LICENSE.txt +0 -18
  91. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.h +0 -41
  92. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDASLLogger.m +0 -100
  93. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.h +0 -102
  94. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDAbstractDatabaseLogger.m +0 -727
  95. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.h +0 -369
  96. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDFileLogger.m +0 -1539
  97. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog+LOGV.h +0 -99
  98. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.h +0 -634
  99. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDLog.m +0 -1208
  100. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.h +0 -181
  101. data/vendor/Pods/CocoaLumberjack/Lumberjack/DDTTYLogger.m +0 -1520
  102. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDContextFilterLogFormatter.h +0 -63
  103. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDContextFilterLogFormatter.m +0 -191
  104. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDDispatchQueueLogFormatter.h +0 -128
  105. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDDispatchQueueLogFormatter.m +0 -253
  106. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.h +0 -30
  107. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/DDMultiFormatter.m +0 -127
  108. data/vendor/Pods/CocoaLumberjack/Lumberjack/Extensions/README.txt +0 -7
  109. data/vendor/Pods/CocoaLumberjack/README.markdown +0 -74
  110. data/vendor/Pods/Headers/CocoaLumberjack/DDASLLogger.h +0 -41
  111. data/vendor/Pods/Headers/CocoaLumberjack/DDAbstractDatabaseLogger.h +0 -102
  112. data/vendor/Pods/Headers/CocoaLumberjack/DDContextFilterLogFormatter.h +0 -63
  113. data/vendor/Pods/Headers/CocoaLumberjack/DDDispatchQueueLogFormatter.h +0 -128
  114. data/vendor/Pods/Headers/CocoaLumberjack/DDFileLogger.h +0 -369
  115. data/vendor/Pods/Headers/CocoaLumberjack/DDLog+LOGV.h +0 -99
  116. data/vendor/Pods/Headers/CocoaLumberjack/DDLog.h +0 -634
  117. data/vendor/Pods/Headers/CocoaLumberjack/DDMultiFormatter.h +0 -30
  118. data/vendor/Pods/Headers/CocoaLumberjack/DDTTYLogger.h +0 -181
  119. data/vendor/Pods/Headers/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  120. data/vendor/Pods/Headers/YapDatabase/YapCollectionKey.h +0 -23
  121. data/vendor/Pods/Headers/YapDatabase/YapDatabase.h +0 -547
  122. data/vendor/Pods/Headers/YapDatabase/YapDatabaseConnection.h +0 -449
  123. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtension.h +0 -15
  124. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionConnection.h +0 -11
  125. data/vendor/Pods/Headers/YapDatabase/YapDatabaseExtensionTransaction.h +0 -11
  126. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredView.h +0 -81
  127. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewConnection.h +0 -12
  128. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTransaction.h +0 -39
  129. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFilteredViewTypes.h +0 -32
  130. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearch.h +0 -89
  131. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchConnection.h +0 -32
  132. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  133. data/vendor/Pods/Headers/YapDatabase/YapDatabaseFullTextSearchTransaction.h +0 -68
  134. data/vendor/Pods/Headers/YapDatabase/YapDatabaseQuery.h +0 -42
  135. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationship.h +0 -35
  136. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipConnection.h +0 -29
  137. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipEdge.h +0 -163
  138. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipNode.h +0 -99
  139. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipOptions.h +0 -59
  140. data/vendor/Pods/Headers/YapDatabase/YapDatabaseRelationshipTransaction.h +0 -384
  141. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndex.h +0 -149
  142. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexConnection.h +0 -33
  143. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexSetup.h +0 -33
  144. data/vendor/Pods/Headers/YapDatabase/YapDatabaseSecondaryIndexTransaction.h +0 -58
  145. data/vendor/Pods/Headers/YapDatabase/YapDatabaseTransaction.h +0 -651
  146. data/vendor/Pods/Headers/YapDatabase/YapDatabaseView.h +0 -127
  147. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewChange.h +0 -272
  148. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewConnection.h +0 -116
  149. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewMappings.h +0 -842
  150. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewOptions.h +0 -63
  151. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewRangeOptions.h +0 -330
  152. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTransaction.h +0 -498
  153. data/vendor/Pods/Headers/YapDatabase/YapDatabaseViewTypes.h +0 -99
  154. data/vendor/Pods/Headers/YapDatabase/YapSet.h +0 -41
  155. data/vendor/Pods/Headers/____Pods-CocoaLumberjack-prefix.h +0 -7
  156. data/vendor/Pods/Headers/____Pods-NSData+MD5Digest-prefix.h +0 -5
  157. data/vendor/Pods/Headers/____Pods-YapDatabase-prefix.h +0 -5
  158. data/vendor/Pods/Headers/____Pods-environment.h +0 -38
  159. data/vendor/Pods/Manifest.lock +0 -22
  160. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.h +0 -18
  161. data/vendor/Pods/NSData+MD5Digest/NSData+MD5Digest/NSData+MD5Digest.m +0 -39
  162. data/vendor/Pods/NSData+MD5Digest/README.md +0 -11
  163. data/vendor/Pods/Pods-CocoaLumberjack-Private.xcconfig +0 -5
  164. data/vendor/Pods/Pods-CocoaLumberjack-dummy.m +0 -5
  165. data/vendor/Pods/Pods-CocoaLumberjack-prefix.pch +0 -7
  166. data/vendor/Pods/Pods-CocoaLumberjack.xcconfig +0 -0
  167. data/vendor/Pods/Pods-NSData+MD5Digest-Private.xcconfig +0 -5
  168. data/vendor/Pods/Pods-NSData+MD5Digest-dummy.m +0 -5
  169. data/vendor/Pods/Pods-NSData+MD5Digest-prefix.pch +0 -5
  170. data/vendor/Pods/Pods-NSData+MD5Digest.xcconfig +0 -0
  171. data/vendor/Pods/Pods-YapDatabase-Private.xcconfig +0 -5
  172. data/vendor/Pods/Pods-YapDatabase-dummy.m +0 -5
  173. data/vendor/Pods/Pods-YapDatabase-prefix.pch +0 -5
  174. data/vendor/Pods/Pods-YapDatabase.xcconfig +0 -1
  175. data/vendor/Pods/Pods-acknowledgements.markdown +0 -59
  176. data/vendor/Pods/Pods-acknowledgements.plist +0 -97
  177. data/vendor/Pods/Pods-dummy.m +0 -5
  178. data/vendor/Pods/Pods-environment.h +0 -38
  179. data/vendor/Pods/Pods-resources.sh +0 -68
  180. data/vendor/Pods/Pods.xcconfig +0 -5
  181. data/vendor/Pods/Pods.xcodeproj/project.pbxproj +0 -4807
  182. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-CocoaLumberjack.xcscheme +0 -59
  183. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-NSData+MD5Digest.xcscheme +0 -59
  184. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods-YapDatabase.xcscheme +0 -59
  185. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/Pods.xcscheme +0 -59
  186. data/vendor/Pods/Pods.xcodeproj/xcuserdata/kareemk.xcuserdatad/xcschemes/xcschememanagement.plist +0 -31
  187. data/vendor/Pods/YapDatabase/LICENSE.txt +0 -18
  188. data/vendor/Pods/YapDatabase/README.md +0 -32
  189. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/Internal/YapDatabaseFilteredViewPrivate.h +0 -17
  190. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.h +0 -81
  191. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredView.m +0 -159
  192. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.h +0 -12
  193. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewConnection.m +0 -41
  194. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.h +0 -39
  195. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTransaction.m +0 -1235
  196. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FilteredViews/YapDatabaseFilteredViewTypes.h +0 -32
  197. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/Internal/YapDatabaseFullTextSearchPrivate.h +0 -77
  198. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.h +0 -89
  199. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearch.m +0 -146
  200. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.h +0 -32
  201. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchConnection.m +0 -298
  202. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.h +0 -79
  203. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchSnippetOptions.m +0 -95
  204. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.h +0 -68
  205. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/FullTextSearch/YapDatabaseFullTextSearchTransaction.m +0 -1403
  206. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/Internal/YapDatabaseExtensionPrivate.h +0 -444
  207. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.h +0 -15
  208. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtension.m +0 -83
  209. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.h +0 -11
  210. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionConnection.m +0 -46
  211. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.h +0 -11
  212. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Protocol/YapDatabaseExtensionTransaction.m +0 -204
  213. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipEdgePrivate.h +0 -79
  214. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/Internal/YapDatabaseRelationshipPrivate.h +0 -125
  215. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.h +0 -35
  216. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationship.m +0 -129
  217. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.h +0 -29
  218. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipConnection.m +0 -802
  219. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.h +0 -163
  220. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipEdge.m +0 -408
  221. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipNode.h +0 -99
  222. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.h +0 -59
  223. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipOptions.m +0 -29
  224. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.h +0 -384
  225. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Relationships/YapDatabaseRelationshipTransaction.m +0 -5254
  226. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexPrivate.h +0 -83
  227. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/Internal/YapDatabaseSecondaryIndexSetupPrivate.h +0 -18
  228. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.h +0 -149
  229. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndex.m +0 -161
  230. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.h +0 -33
  231. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexConnection.m +0 -331
  232. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.h +0 -33
  233. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexSetup.m +0 -245
  234. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.h +0 -58
  235. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/SecondaryIndex/YapDatabaseSecondaryIndexTransaction.m +0 -1269
  236. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewChangePrivate.h +0 -94
  237. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewMappingsPrivate.h +0 -72
  238. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.h +0 -36
  239. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPage.mm +0 -296
  240. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.h +0 -27
  241. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPageMetadata.m +0 -28
  242. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h +0 -170
  243. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Internal/YapDatabaseViewRangeOptionsPrivate.h +0 -17
  244. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.h +0 -272
  245. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewChange.m +0 -2500
  246. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.h +0 -842
  247. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewMappings.m +0 -1714
  248. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.h +0 -330
  249. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/Utilities/YapDatabaseViewRangeOptions.m +0 -141
  250. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.h +0 -127
  251. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseView.m +0 -194
  252. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.h +0 -116
  253. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewConnection.m +0 -888
  254. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.h +0 -63
  255. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewOptions.m +0 -27
  256. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h +0 -498
  257. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m +0 -4986
  258. data/vendor/Pods/YapDatabase/YapDatabase/Extensions/Views/YapDatabaseViewTypes.h +0 -99
  259. data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.h +0 -8
  260. data/vendor/Pods/YapDatabase/YapDatabase/Internal/NSDictionary+YapDatabase.m +0 -19
  261. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.h +0 -91
  262. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapCache.m +0 -465
  263. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.h +0 -29
  264. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseConnectionState.m +0 -48
  265. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.h +0 -37
  266. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseDefaults.m +0 -83
  267. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.h +0 -158
  268. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseLogging.m +0 -73
  269. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.h +0 -17
  270. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseManager.m +0 -56
  271. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabasePrivate.h +0 -446
  272. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.h +0 -13
  273. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseStatement.m +0 -26
  274. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapDatabaseString.h +0 -121
  275. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.h +0 -74
  276. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapMemoryTable.m +0 -603
  277. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.h +0 -17
  278. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapNull.m +0 -35
  279. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.h +0 -15
  280. data/vendor/Pods/YapDatabase/YapDatabase/Internal/YapTouch.m +0 -31
  281. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.h +0 -23
  282. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapCollectionKey.m +0 -199
  283. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.h +0 -42
  284. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapDatabaseQuery.m +0 -96
  285. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.h +0 -41
  286. data/vendor/Pods/YapDatabase/YapDatabase/Utilities/YapSet.m +0 -82
  287. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.h +0 -547
  288. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabase.m +0 -2013
  289. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.h +0 -449
  290. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseConnection.m +0 -4046
  291. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.h +0 -651
  292. data/vendor/Pods/YapDatabase/YapDatabase/YapDatabaseTransaction.m +0 -5602
  293. data/vendor/Pods/build-iPhoneSimulator/Pods.bridgesupport +0 -3172
  294. data/vendor/Pods/build-iPhoneSimulator/libPods.a +0 -0
@@ -1,369 +0,0 @@
1
- #import <Foundation/Foundation.h>
2
- #import "DDLog.h"
3
-
4
- @class DDLogFileInfo;
5
-
6
- /**
7
- * Welcome to Cocoa Lumberjack!
8
- *
9
- * The project page has a wealth of documentation if you have any questions.
10
- * https://github.com/CocoaLumberjack/CocoaLumberjack
11
- *
12
- * If you're new to the project you may wish to read the "Getting Started" wiki.
13
- * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
14
- *
15
- *
16
- * This class provides a logger to write log statements to a file.
17
- **/
18
-
19
-
20
- // Default configuration and safety/sanity values.
21
- //
22
- // maximumFileSize -> DEFAULT_LOG_MAX_FILE_SIZE
23
- // rollingFrequency -> DEFAULT_LOG_ROLLING_FREQUENCY
24
- // maximumNumberOfLogFiles -> DEFAULT_LOG_MAX_NUM_LOG_FILES
25
- //
26
- // You should carefully consider the proper configuration values for your application.
27
-
28
- #define DEFAULT_LOG_MAX_FILE_SIZE (1024 * 1024) // 1 MB
29
- #define DEFAULT_LOG_ROLLING_FREQUENCY (60 * 60 * 24) // 24 Hours
30
- #define DEFAULT_LOG_MAX_NUM_LOG_FILES (5) // 5 Files
31
-
32
-
33
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34
- #pragma mark -
35
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36
-
37
- // The LogFileManager protocol is designed to allow you to control all aspects of your log files.
38
- //
39
- // The primary purpose of this is to allow you to do something with the log files after they have been rolled.
40
- // Perhaps you want to compress them to save disk space.
41
- // Perhaps you want to upload them to an FTP server.
42
- // Perhaps you want to run some analytics on the file.
43
- //
44
- // A default LogFileManager is, of course, provided.
45
- // The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property.
46
- //
47
- // This protocol provides various methods to fetch the list of log files.
48
- //
49
- // There are two variants: sorted and unsorted.
50
- // If sorting is not necessary, the unsorted variant is obviously faster.
51
- // The sorted variant will return an array sorted by when the log files were created,
52
- // with the most recently created log file at index 0, and the oldest log file at the end of the array.
53
- //
54
- // You can fetch only the log file paths (full path including name), log file names (name only),
55
- // or an array of DDLogFileInfo objects.
56
- // The DDLogFileInfo class is documented below, and provides a handy wrapper that
57
- // gives you easy access to various file attributes such as the creation date or the file size.
58
-
59
- @protocol DDLogFileManager <NSObject>
60
- @required
61
-
62
- // Public properties
63
-
64
- /**
65
- * The maximum number of archived log files to keep on disk.
66
- * For example, if this property is set to 3,
67
- * then the LogFileManager will only keep 3 archived log files (plus the current active log file) on disk.
68
- * Once the active log file is rolled/archived, then the oldest of the existing 3 rolled/archived log files is deleted.
69
- *
70
- * You may optionally disable deleting old/rolled/archived log files by setting this property to zero.
71
- **/
72
- @property (readwrite, assign) NSUInteger maximumNumberOfLogFiles;
73
-
74
- // Public methods
75
-
76
- - (NSString *)logsDirectory;
77
-
78
- - (NSArray *)unsortedLogFilePaths;
79
- - (NSArray *)unsortedLogFileNames;
80
- - (NSArray *)unsortedLogFileInfos;
81
-
82
- - (NSArray *)sortedLogFilePaths;
83
- - (NSArray *)sortedLogFileNames;
84
- - (NSArray *)sortedLogFileInfos;
85
-
86
- // Private methods (only to be used by DDFileLogger)
87
-
88
- - (NSString *)createNewLogFile;
89
-
90
- @optional
91
-
92
- // Notifications from DDFileLogger
93
-
94
- - (void)didArchiveLogFile:(NSString *)logFilePath;
95
- - (void)didRollAndArchiveLogFile:(NSString *)logFilePath;
96
-
97
- @end
98
-
99
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100
- #pragma mark -
101
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102
-
103
- /**
104
- * Default log file manager.
105
- *
106
- * All log files are placed inside the logsDirectory.
107
- * If a specific logsDirectory isn't specified, the default directory is used.
108
- * On Mac, this is in ~/Library/Logs/<Application Name>.
109
- * On iPhone, this is in ~/Library/Caches/Logs.
110
- *
111
- * Log files are named "<bundle identifier> <date> <time>.log"
112
- * Example: com.organization.myapp 2013-12-03 17-14.log
113
- *
114
- * Archived log files are automatically deleted according to the maximumNumberOfLogFiles property.
115
- **/
116
- @interface DDLogFileManagerDefault : NSObject <DDLogFileManager>
117
- {
118
- NSUInteger maximumNumberOfLogFiles;
119
- NSString *_logsDirectory;
120
- }
121
-
122
- - (id)init;
123
- - (instancetype)initWithLogsDirectory:(NSString *)logsDirectory;
124
-
125
- /*
126
- * Methods to override.
127
- *
128
- * Log files are named "<bundle identifier> <date> <time>.log"
129
- * Example: com.organization.myapp 2013-12-03 17-14.log
130
- *
131
- * If you wish to change default filename, you can override following two methods.
132
- * - newLogFileName method would be called on new logfile creation.
133
- * - isLogFile: method would be called to filter logfiles from all other files in logsDirectory.
134
- * You have to parse given filename and return YES if it is logFile.
135
- *
136
- * **NOTE**
137
- * newLogFileName returns filename. If appropriate file already exists, number would be added
138
- * to filename before extension. You have to handle this case in isLogFile: method.
139
- *
140
- * Example:
141
- * - newLogFileName returns "com.organization.myapp 2013-12-03.log",
142
- * file "com.organization.myapp 2013-12-03.log" would be created.
143
- * - after some time "com.organization.myapp 2013-12-03.log" is archived
144
- * - newLogFileName again returns "com.organization.myapp 2013-12-03.log",
145
- * file "com.organization.myapp 2013-12-03 2.log" would be created.
146
- * - after some time "com.organization.myapp 2013-12-03 1.log" is archived
147
- * - newLogFileName again returns "com.organization.myapp 2013-12-03.log",
148
- * file "com.organization.myapp 2013-12-03 3.log" would be created.
149
- **/
150
- - (NSString *)newLogFileName;
151
- - (BOOL)isLogFile:(NSString *)fileName;
152
-
153
- /* Inherited from DDLogFileManager protocol:
154
-
155
- @property (readwrite, assign) NSUInteger maximumNumberOfLogFiles;
156
-
157
- - (NSString *)logsDirectory;
158
-
159
- - (NSArray *)unsortedLogFilePaths;
160
- - (NSArray *)unsortedLogFileNames;
161
- - (NSArray *)unsortedLogFileInfos;
162
-
163
- - (NSArray *)sortedLogFilePaths;
164
- - (NSArray *)sortedLogFileNames;
165
- - (NSArray *)sortedLogFileInfos;
166
-
167
- */
168
-
169
- @end
170
-
171
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
172
- #pragma mark -
173
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
174
-
175
- /**
176
- * Most users will want file log messages to be prepended with the date and time.
177
- * Rather than forcing the majority of users to write their own formatter,
178
- * we will supply a logical default formatter.
179
- * Users can easily replace this formatter with their own by invoking the setLogFormatter method.
180
- * It can also be removed by calling setLogFormatter, and passing a nil parameter.
181
- *
182
- * In addition to the convenience of having a logical default formatter,
183
- * it will also provide a template that makes it easy for developers to copy and change.
184
- **/
185
- @interface DDLogFileFormatterDefault : NSObject <DDLogFormatter>
186
- {
187
- NSDateFormatter *dateFormatter;
188
- }
189
-
190
- - (id)init;
191
- - (instancetype)initWithDateFormatter:(NSDateFormatter *)dateFormatter;
192
-
193
- @end
194
-
195
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
196
- #pragma mark -
197
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198
-
199
- @interface DDFileLogger : DDAbstractLogger <DDLogger>
200
- {
201
- __strong id <DDLogFileManager> logFileManager;
202
-
203
- DDLogFileInfo *currentLogFileInfo;
204
- NSFileHandle *currentLogFileHandle;
205
-
206
- dispatch_source_t currentLogFileVnode;
207
- dispatch_source_t rollingTimer;
208
-
209
- unsigned long long maximumFileSize;
210
- NSTimeInterval rollingFrequency;
211
- }
212
-
213
- - (id)init;
214
- - (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager;
215
-
216
- /**
217
- * Log File Rolling:
218
- *
219
- * maximumFileSize:
220
- * The approximate maximum size to allow log files to grow.
221
- * If a log file is larger than this value after a log statement is appended,
222
- * then the log file is rolled.
223
- *
224
- * rollingFrequency
225
- * How often to roll the log file.
226
- * The frequency is given as an NSTimeInterval, which is a double that specifies the interval in seconds.
227
- * Once the log file gets to be this old, it is rolled.
228
- *
229
- * Both the maximumFileSize and the rollingFrequency are used to manage rolling.
230
- * Whichever occurs first will cause the log file to be rolled.
231
- *
232
- * For example:
233
- * The rollingFrequency is 24 hours,
234
- * but the log file surpasses the maximumFileSize after only 20 hours.
235
- * The log file will be rolled at that 20 hour mark.
236
- * A new log file will be created, and the 24 hour timer will be restarted.
237
- *
238
- * You may optionally disable rolling due to filesize by setting maximumFileSize to zero.
239
- * If you do so, rolling is based solely on rollingFrequency.
240
- *
241
- * You may optionally disable rolling due to time by setting rollingFrequency to zero (or any non-positive number).
242
- * If you do so, rolling is based solely on maximumFileSize.
243
- *
244
- * If you disable both maximumFileSize and rollingFrequency, then the log file won't ever be rolled.
245
- * This is strongly discouraged.
246
- **/
247
- @property (readwrite, assign) unsigned long long maximumFileSize;
248
- @property (readwrite, assign) NSTimeInterval rollingFrequency;
249
-
250
- /**
251
- * The DDLogFileManager instance can be used to retrieve the list of log files,
252
- * and configure the maximum number of archived log files to keep.
253
- *
254
- * @see DDLogFileManager.maximumNumberOfLogFiles
255
- **/
256
- @property (strong, nonatomic, readonly) id <DDLogFileManager> logFileManager;
257
-
258
-
259
- // You can optionally force the current log file to be rolled with this method.
260
- // CompletionBlock will be called on main queue.
261
-
262
- - (void)rollLogFileWithCompletionBlock:(void (^)())completionBlock;
263
-
264
- // Method is deprecated. Use rollLogFileWithCompletionBlock: method instead.
265
-
266
- - (void)rollLogFile __attribute((deprecated));
267
-
268
- // Inherited from DDAbstractLogger
269
-
270
- // - (id <DDLogFormatter>)logFormatter;
271
- // - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
272
-
273
- @end
274
-
275
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
276
- #pragma mark -
277
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
278
-
279
- /**
280
- * DDLogFileInfo is a simple class that provides access to various file attributes.
281
- * It provides good performance as it only fetches the information if requested,
282
- * and it caches the information to prevent duplicate fetches.
283
- *
284
- * It was designed to provide quick snapshots of the current state of log files,
285
- * and to help sort log files in an array.
286
- *
287
- * This class does not monitor the files, or update it's cached attribute values if the file changes on disk.
288
- * This is not what the class was designed for.
289
- *
290
- * If you absolutely must get updated values,
291
- * you can invoke the reset method which will clear the cache.
292
- **/
293
- @interface DDLogFileInfo : NSObject
294
- {
295
- __strong NSString *filePath;
296
- __strong NSString *fileName;
297
-
298
- __strong NSDictionary *fileAttributes;
299
-
300
- __strong NSDate *creationDate;
301
- __strong NSDate *modificationDate;
302
-
303
- unsigned long long fileSize;
304
- }
305
-
306
- @property (strong, nonatomic, readonly) NSString *filePath;
307
- @property (strong, nonatomic, readonly) NSString *fileName;
308
-
309
- @property (strong, nonatomic, readonly) NSDictionary *fileAttributes;
310
-
311
- @property (strong, nonatomic, readonly) NSDate *creationDate;
312
- @property (strong, nonatomic, readonly) NSDate *modificationDate;
313
-
314
- @property (nonatomic, readonly) unsigned long long fileSize;
315
-
316
- @property (nonatomic, readonly) NSTimeInterval age;
317
-
318
- @property (nonatomic, readwrite) BOOL isArchived;
319
-
320
- + (instancetype)logFileWithPath:(NSString *)filePath;
321
-
322
- - (instancetype)initWithFilePath:(NSString *)filePath;
323
-
324
- - (void)reset;
325
- - (void)renameFile:(NSString *)newFileName;
326
-
327
- #if TARGET_IPHONE_SIMULATOR
328
-
329
- // So here's the situation.
330
- // Extended attributes are perfect for what we're trying to do here (marking files as archived).
331
- // This is exactly what extended attributes were designed for.
332
- //
333
- // But Apple screws us over on the simulator.
334
- // Everytime you build-and-go, they copy the application into a new folder on the hard drive,
335
- // and as part of the process they strip extended attributes from our log files.
336
- // Normally, a copy of a file preserves extended attributes.
337
- // So obviously Apple has gone to great lengths to piss us off.
338
- //
339
- // Thus we use a slightly different tactic for marking log files as archived in the simulator.
340
- // That way it "just works" and there's no confusion when testing.
341
- //
342
- // The difference in method names is indicative of the difference in functionality.
343
- // On the simulator we add an attribute by appending a filename extension.
344
- //
345
- // For example:
346
- // "mylog.txt" -> "mylog.archived.txt"
347
- // "mylog" -> "mylog.archived"
348
-
349
- - (BOOL)hasExtensionAttributeWithName:(NSString *)attrName;
350
-
351
- - (void)addExtensionAttributeWithName:(NSString *)attrName;
352
- - (void)removeExtensionAttributeWithName:(NSString *)attrName;
353
-
354
- #else
355
-
356
- // Normal use of extended attributes used everywhere else,
357
- // such as on Macs and on iPhone devices.
358
-
359
- - (BOOL)hasExtendedAttributeWithName:(NSString *)attrName;
360
-
361
- - (void)addExtendedAttributeWithName:(NSString *)attrName;
362
- - (void)removeExtendedAttributeWithName:(NSString *)attrName;
363
-
364
- #endif
365
-
366
- - (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another;
367
- - (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another;
368
-
369
- @end
@@ -1,1539 +0,0 @@
1
- #import "DDFileLogger.h"
2
-
3
- #import <unistd.h>
4
- #import <sys/attr.h>
5
- #import <sys/xattr.h>
6
- #import <libkern/OSAtomic.h>
7
-
8
- /**
9
- * Welcome to Cocoa Lumberjack!
10
- *
11
- * The project page has a wealth of documentation if you have any questions.
12
- * https://github.com/CocoaLumberjack/CocoaLumberjack
13
- *
14
- * If you're new to the project you may wish to read the "Getting Started" wiki.
15
- * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
16
- **/
17
-
18
- #if ! __has_feature(objc_arc)
19
- #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
20
- #endif
21
-
22
- // We probably shouldn't be using DDLog() statements within the DDLog implementation.
23
- // But we still want to leave our log statements for any future debugging,
24
- // and to allow other developers to trace the implementation (which is a great learning tool).
25
- //
26
- // So we use primitive logging macros around NSLog.
27
- // We maintain the NS prefix on the macros to be explicit about the fact that we're using NSLog.
28
-
29
- #define LOG_LEVEL 2
30
-
31
- #define NSLogError(frmt, ...) do{ if(LOG_LEVEL >= 1) NSLog((frmt), ##__VA_ARGS__); } while(0)
32
- #define NSLogWarn(frmt, ...) do{ if(LOG_LEVEL >= 2) NSLog((frmt), ##__VA_ARGS__); } while(0)
33
- #define NSLogInfo(frmt, ...) do{ if(LOG_LEVEL >= 3) NSLog((frmt), ##__VA_ARGS__); } while(0)
34
- #define NSLogDebug(frmt, ...) do{ if(LOG_LEVEL >= 4) NSLog((frmt), ##__VA_ARGS__); } while(0)
35
- #define NSLogVerbose(frmt, ...) do{ if(LOG_LEVEL >= 5) NSLog((frmt), ##__VA_ARGS__); } while(0)
36
-
37
- @interface DDLogFileManagerDefault (PrivateAPI)
38
-
39
- - (void)deleteOldLogFiles;
40
- - (NSString *)defaultLogsDirectory;
41
-
42
- @end
43
-
44
- @interface DDFileLogger (PrivateAPI)
45
-
46
- - (void)rollLogFileNow;
47
- - (void)maybeRollLogFileDueToAge;
48
- - (void)maybeRollLogFileDueToSize;
49
-
50
- @end
51
-
52
- #if TARGET_OS_IPHONE
53
- BOOL doesAppRunInBackground(void);
54
- #endif
55
-
56
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
57
- #pragma mark -
58
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59
-
60
- @implementation DDLogFileManagerDefault
61
-
62
- @synthesize maximumNumberOfLogFiles;
63
-
64
- - (id)init
65
- {
66
- return [self initWithLogsDirectory:nil];
67
- }
68
-
69
- - (instancetype)initWithLogsDirectory:(NSString *)aLogsDirectory
70
- {
71
- if ((self = [super init]))
72
- {
73
- maximumNumberOfLogFiles = DEFAULT_LOG_MAX_NUM_LOG_FILES;
74
-
75
- if (aLogsDirectory)
76
- _logsDirectory = [aLogsDirectory copy];
77
- else
78
- _logsDirectory = [[self defaultLogsDirectory] copy];
79
-
80
- NSKeyValueObservingOptions kvoOptions = NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew;
81
-
82
- [self addObserver:self forKeyPath:NSStringFromSelector(@selector(maximumNumberOfLogFiles)) options:kvoOptions context:nil];
83
-
84
- NSLogVerbose(@"DDFileLogManagerDefault: logsDirectory:\n%@", [self logsDirectory]);
85
- NSLogVerbose(@"DDFileLogManagerDefault: sortedLogFileNames:\n%@", [self sortedLogFileNames]);
86
- }
87
- return self;
88
- }
89
-
90
- - (void)dealloc
91
- {
92
- // try-catch because the observer might be removed or never added. In this case, removeObserver throws and exception
93
- @try {
94
- [self removeObserver:self forKeyPath:NSStringFromSelector(@selector(maximumNumberOfLogFiles))];
95
- }
96
- @catch (NSException *exception) {
97
-
98
- }
99
- }
100
-
101
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102
- #pragma mark Configuration
103
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104
-
105
- - (void)observeValueForKeyPath:(NSString *)keyPath
106
- ofObject:(id)object
107
- change:(NSDictionary *)change
108
- context:(void *)context
109
- {
110
- NSNumber *old = [change objectForKey:NSKeyValueChangeOldKey];
111
- NSNumber *new = [change objectForKey:NSKeyValueChangeNewKey];
112
-
113
- if ([old isEqual:new])
114
- {
115
- // No change in value - don't bother with any processing.
116
- return;
117
- }
118
-
119
- if ([keyPath isEqualToString:NSStringFromSelector(@selector(maximumNumberOfLogFiles))])
120
- {
121
- NSLogInfo(@"DDFileLogManagerDefault: Responding to configuration change: maximumNumberOfLogFiles");
122
-
123
- dispatch_async([DDLog loggingQueue], ^{ @autoreleasepool {
124
-
125
- [self deleteOldLogFiles];
126
- }});
127
- }
128
- }
129
-
130
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131
- #pragma mark File Deleting
132
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
133
-
134
- /**
135
- * Deletes archived log files that exceed the maximumNumberOfLogFiles configuration value.
136
- **/
137
- - (void)deleteOldLogFiles
138
- {
139
- NSLogVerbose(@"DDLogFileManagerDefault: deleteOldLogFiles");
140
-
141
- NSUInteger maxNumLogFiles = self.maximumNumberOfLogFiles;
142
- if (maxNumLogFiles == 0)
143
- {
144
- // Unlimited - don't delete any log files
145
- return;
146
- }
147
-
148
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
149
-
150
- // Do we consider the first file?
151
- // We are only supposed to be deleting archived files.
152
- // In most cases, the first file is likely the log file that is currently being written to.
153
- // So in most cases, we do not want to consider this file for deletion.
154
-
155
- NSUInteger count = [sortedLogFileInfos count];
156
- BOOL excludeFirstFile = NO;
157
-
158
- if (count > 0)
159
- {
160
- DDLogFileInfo *logFileInfo = [sortedLogFileInfos objectAtIndex:0];
161
-
162
- if (!logFileInfo.isArchived)
163
- {
164
- excludeFirstFile = YES;
165
- }
166
- }
167
-
168
- NSArray *sortedArchivedLogFileInfos;
169
- if (excludeFirstFile)
170
- {
171
- count--;
172
- sortedArchivedLogFileInfos = [sortedLogFileInfos subarrayWithRange:NSMakeRange(1, count)];
173
- }
174
- else
175
- {
176
- sortedArchivedLogFileInfos = sortedLogFileInfos;
177
- }
178
-
179
- NSUInteger i;
180
- for (i = maxNumLogFiles; i < count; i++)
181
- {
182
- DDLogFileInfo *logFileInfo = [sortedArchivedLogFileInfos objectAtIndex:i];
183
-
184
- NSLogInfo(@"DDLogFileManagerDefault: Deleting file: %@", logFileInfo.fileName);
185
-
186
- [[NSFileManager defaultManager] removeItemAtPath:logFileInfo.filePath error:nil];
187
- }
188
- }
189
-
190
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
191
- #pragma mark Log Files
192
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
193
-
194
- /**
195
- * Returns the path to the default logs directory.
196
- * If the logs directory doesn't exist, this method automatically creates it.
197
- **/
198
- - (NSString *)defaultLogsDirectory
199
- {
200
- #if TARGET_OS_IPHONE
201
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
202
- NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
203
- NSString *logsDirectory = [baseDir stringByAppendingPathComponent:@"Logs"];
204
-
205
- #else
206
- NSString *appName = [[NSProcessInfo processInfo] processName];
207
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
208
- NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
209
- NSString *logsDirectory = [[basePath stringByAppendingPathComponent:@"Logs"] stringByAppendingPathComponent:appName];
210
-
211
- #endif
212
-
213
- return logsDirectory;
214
- }
215
-
216
- - (NSString *)logsDirectory
217
- {
218
- // We could do this check once, during initalization, and not bother again.
219
- // But this way the code continues to work if the directory gets deleted while the code is running.
220
-
221
- if (![[NSFileManager defaultManager] fileExistsAtPath:_logsDirectory])
222
- {
223
- NSError *err = nil;
224
- if (![[NSFileManager defaultManager] createDirectoryAtPath:_logsDirectory
225
- withIntermediateDirectories:YES attributes:nil error:&err])
226
- {
227
- NSLogError(@"DDFileLogManagerDefault: Error creating logsDirectory: %@", err);
228
- }
229
- }
230
-
231
- return _logsDirectory;
232
- }
233
-
234
- /**
235
- * Default log file name is "<bundle identifier> <date> <time>.log".
236
- * Example: MobileSafari 2013-12-03 17-14.log
237
- *
238
- * You can change it by overriding newLogFileName and isLogFile: methods.
239
- **/
240
- - (BOOL)isLogFile:(NSString *)fileName
241
- {
242
- NSString *appName = [self applicationName];
243
-
244
- BOOL hasProperPrefix = [fileName hasPrefix:appName];
245
- BOOL hasProperSuffix = [fileName hasSuffix:@".log"];
246
- BOOL hasProperDate = NO;
247
-
248
- if (hasProperPrefix && hasProperSuffix)
249
- {
250
- NSUInteger lengthOfMiddle = fileName.length - appName.length - @".log".length;
251
-
252
- // Date string should have at least 16 characters - " 2013-12-03 17-14"
253
- if (lengthOfMiddle >= 17)
254
- {
255
- NSRange range = NSMakeRange(appName.length, lengthOfMiddle);
256
-
257
- NSString *middle = [fileName substringWithRange:range];
258
- NSArray *components = [middle componentsSeparatedByString:@" "];
259
-
260
- // When creating logfile if there is existing file with the same name, we append attemp number at the end.
261
- // Thats why here we can have three or four components. For details see createNewLogFile method.
262
- //
263
- // Components:
264
- // "", "2013-12-03", "17-14"
265
- // or
266
- // "", "2013-12-03", "17-14", "1"
267
- if (components.count == 3 || components.count == 4)
268
- {
269
- NSString *dateString = [NSString stringWithFormat:@"%@ %@", components[1], components[2]];
270
- NSDateFormatter *dateFormatter = [self logFileDateFormatter];
271
-
272
- NSDate *date = [dateFormatter dateFromString:dateString];
273
-
274
- if (date)
275
- {
276
- hasProperDate = YES;
277
- }
278
- }
279
- }
280
- }
281
-
282
- return (hasProperPrefix && hasProperDate && hasProperSuffix);
283
- }
284
-
285
- - (NSDateFormatter *)logFileDateFormatter
286
- {
287
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
288
- [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd' 'HH'-'mm'"];
289
- [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
290
-
291
- return dateFormatter;
292
- }
293
-
294
- /**
295
- * Returns an array of NSString objects,
296
- * each of which is the filePath to an existing log file on disk.
297
- **/
298
- - (NSArray *)unsortedLogFilePaths
299
- {
300
- NSString *logsDirectory = [self logsDirectory];
301
- NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:logsDirectory error:nil];
302
-
303
- NSMutableArray *unsortedLogFilePaths = [NSMutableArray arrayWithCapacity:[fileNames count]];
304
-
305
- for (NSString *fileName in fileNames)
306
- {
307
- // Filter out any files that aren't log files. (Just for extra safety)
308
-
309
- #if TARGET_IPHONE_SIMULATOR
310
- // In case of iPhone simulator there can be 'archived' extension. isLogFile:
311
- // method knows nothing about it. Thus removing it for this method.
312
- //
313
- // See full explanation in the header file.
314
- NSString *theFileName = [fileName stringByReplacingOccurrencesOfString:@".archived"
315
- withString:@""];
316
-
317
- if ([self isLogFile:theFileName])
318
- #else
319
- if ([self isLogFile:fileName])
320
- #endif
321
- {
322
- NSString *filePath = [logsDirectory stringByAppendingPathComponent:fileName];
323
-
324
- [unsortedLogFilePaths addObject:filePath];
325
- }
326
- }
327
-
328
- return unsortedLogFilePaths;
329
- }
330
-
331
- /**
332
- * Returns an array of NSString objects,
333
- * each of which is the fileName of an existing log file on disk.
334
- **/
335
- - (NSArray *)unsortedLogFileNames
336
- {
337
- NSArray *unsortedLogFilePaths = [self unsortedLogFilePaths];
338
-
339
- NSMutableArray *unsortedLogFileNames = [NSMutableArray arrayWithCapacity:[unsortedLogFilePaths count]];
340
-
341
- for (NSString *filePath in unsortedLogFilePaths)
342
- {
343
- [unsortedLogFileNames addObject:[filePath lastPathComponent]];
344
- }
345
-
346
- return unsortedLogFileNames;
347
- }
348
-
349
- /**
350
- * Returns an array of DDLogFileInfo objects,
351
- * each representing an existing log file on disk,
352
- * and containing important information about the log file such as it's modification date and size.
353
- **/
354
- - (NSArray *)unsortedLogFileInfos
355
- {
356
- NSArray *unsortedLogFilePaths = [self unsortedLogFilePaths];
357
-
358
- NSMutableArray *unsortedLogFileInfos = [NSMutableArray arrayWithCapacity:[unsortedLogFilePaths count]];
359
-
360
- for (NSString *filePath in unsortedLogFilePaths)
361
- {
362
- DDLogFileInfo *logFileInfo = [[DDLogFileInfo alloc] initWithFilePath:filePath];
363
-
364
- [unsortedLogFileInfos addObject:logFileInfo];
365
- }
366
-
367
- return unsortedLogFileInfos;
368
- }
369
-
370
- /**
371
- * Just like the unsortedLogFilePaths method, but sorts the array.
372
- * The items in the array are sorted by creation date.
373
- * The first item in the array will be the most recently created log file.
374
- **/
375
- - (NSArray *)sortedLogFilePaths
376
- {
377
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
378
-
379
- NSMutableArray *sortedLogFilePaths = [NSMutableArray arrayWithCapacity:[sortedLogFileInfos count]];
380
-
381
- for (DDLogFileInfo *logFileInfo in sortedLogFileInfos)
382
- {
383
- [sortedLogFilePaths addObject:[logFileInfo filePath]];
384
- }
385
-
386
- return sortedLogFilePaths;
387
- }
388
-
389
- /**
390
- * Just like the unsortedLogFileNames method, but sorts the array.
391
- * The items in the array are sorted by creation date.
392
- * The first item in the array will be the most recently created log file.
393
- **/
394
- - (NSArray *)sortedLogFileNames
395
- {
396
- NSArray *sortedLogFileInfos = [self sortedLogFileInfos];
397
-
398
- NSMutableArray *sortedLogFileNames = [NSMutableArray arrayWithCapacity:[sortedLogFileInfos count]];
399
-
400
- for (DDLogFileInfo *logFileInfo in sortedLogFileInfos)
401
- {
402
- [sortedLogFileNames addObject:[logFileInfo fileName]];
403
- }
404
-
405
- return sortedLogFileNames;
406
- }
407
-
408
- /**
409
- * Just like the unsortedLogFileInfos method, but sorts the array.
410
- * The items in the array are sorted by creation date.
411
- * The first item in the array will be the most recently created log file.
412
- **/
413
- - (NSArray *)sortedLogFileInfos
414
- {
415
- return [[self unsortedLogFileInfos] sortedArrayUsingSelector:@selector(reverseCompareByCreationDate:)];
416
- }
417
-
418
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
419
- #pragma mark Creation
420
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
421
-
422
- /**
423
- * Generates log file name with default format "<bundle identifier> <date> <time>.log"
424
- * Example: MobileSafari 2013-12-03 17-14.log
425
- *
426
- * You can change it by overriding newLogFileName and isLogFile: methods.
427
- **/
428
- - (NSString *)newLogFileName
429
- {
430
- NSString *appName = [self applicationName];
431
-
432
- NSDateFormatter *dateFormatter = [self logFileDateFormatter];
433
- NSString *formattedDate = [dateFormatter stringFromDate:[NSDate date]];
434
-
435
- return [NSString stringWithFormat:@"%@ %@.log", appName, formattedDate];
436
- }
437
-
438
- /**
439
- * Generates a new unique log file path, and creates the corresponding log file.
440
- **/
441
- - (NSString *)createNewLogFile
442
- {
443
- NSString *fileName = [self newLogFileName];
444
- NSString *logsDirectory = [self logsDirectory];
445
-
446
- NSUInteger attempt = 1;
447
- do
448
- {
449
- NSString *actualFileName = fileName;
450
-
451
- if (attempt > 1) {
452
- NSString *extension = [actualFileName pathExtension];
453
-
454
- actualFileName = [actualFileName stringByDeletingPathExtension];
455
- actualFileName = [actualFileName stringByAppendingFormat:@" %lu", (unsigned long)attempt];
456
- if (extension.length) {
457
- actualFileName = [actualFileName stringByAppendingPathExtension:extension];
458
- }
459
- }
460
-
461
- NSString *filePath = [logsDirectory stringByAppendingPathComponent:actualFileName];
462
-
463
- if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
464
- {
465
- NSLogVerbose(@"DDLogFileManagerDefault: Creating new log file: %@", actualFileName);
466
-
467
- NSDictionary *attributes = nil;
468
-
469
- #if TARGET_OS_IPHONE
470
- // When creating log file on iOS we're setting NSFileProtectionKey attribute to NSFileProtectionCompleteUnlessOpen.
471
- //
472
- // But in case if app is able to launch from background we need to have an ability to open log file any time we
473
- // want (even if device is locked). Thats why that attribute have to be changed to
474
- // NSFileProtectionCompleteUntilFirstUserAuthentication.
475
-
476
- NSString *key = doesAppRunInBackground() ?
477
- NSFileProtectionCompleteUntilFirstUserAuthentication : NSFileProtectionCompleteUnlessOpen;
478
-
479
- attributes = @{ NSFileProtectionKey : key };
480
- #endif
481
-
482
- [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:attributes];
483
-
484
- // Since we just created a new log file, we may need to delete some old log files
485
- [self deleteOldLogFiles];
486
-
487
- return filePath;
488
- } else {
489
- attempt++;
490
- }
491
-
492
- } while(YES);
493
- }
494
-
495
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496
- #pragma mark Utility
497
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
498
-
499
- - (NSString *)applicationName
500
- {
501
- static NSString *_appName;
502
- static dispatch_once_t onceToken;
503
-
504
- dispatch_once(&onceToken, ^{
505
- _appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
506
-
507
- if (! _appName)
508
- {
509
- _appName = [[NSProcessInfo processInfo] processName];
510
- }
511
-
512
- if (! _appName)
513
- {
514
- _appName = @"";
515
- }
516
- });
517
-
518
- return _appName;
519
- }
520
-
521
- @end
522
-
523
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
524
- #pragma mark -
525
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
526
-
527
- @implementation DDLogFileFormatterDefault
528
-
529
- - (id)init
530
- {
531
- return [self initWithDateFormatter:nil];
532
- }
533
-
534
- - (instancetype)initWithDateFormatter:(NSDateFormatter *)aDateFormatter
535
- {
536
- if ((self = [super init]))
537
- {
538
- if (aDateFormatter)
539
- {
540
- dateFormatter = aDateFormatter;
541
- }
542
- else
543
- {
544
- dateFormatter = [[NSDateFormatter alloc] init];
545
- [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; // 10.4+ style
546
- [dateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss:SSS"];
547
- }
548
- }
549
- return self;
550
- }
551
-
552
- - (NSString *)formatLogMessage:(DDLogMessage *)logMessage
553
- {
554
- NSString *dateAndTime = [dateFormatter stringFromDate:(logMessage->timestamp)];
555
-
556
- return [NSString stringWithFormat:@"%@ %@", dateAndTime, logMessage->logMsg];
557
- }
558
-
559
- @end
560
-
561
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
562
- #pragma mark -
563
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
564
-
565
- @implementation DDFileLogger
566
-
567
- - (id)init
568
- {
569
- DDLogFileManagerDefault *defaultLogFileManager = [[DDLogFileManagerDefault alloc] init];
570
-
571
- return [self initWithLogFileManager:defaultLogFileManager];
572
- }
573
-
574
- - (instancetype)initWithLogFileManager:(id <DDLogFileManager>)aLogFileManager
575
- {
576
- if ((self = [super init]))
577
- {
578
- maximumFileSize = DEFAULT_LOG_MAX_FILE_SIZE;
579
- rollingFrequency = DEFAULT_LOG_ROLLING_FREQUENCY;
580
-
581
- logFileManager = aLogFileManager;
582
-
583
- formatter = [[DDLogFileFormatterDefault alloc] init];
584
- }
585
- return self;
586
- }
587
-
588
- - (void)dealloc
589
- {
590
- [currentLogFileHandle synchronizeFile];
591
- [currentLogFileHandle closeFile];
592
-
593
- if (currentLogFileVnode) {
594
- dispatch_source_cancel(currentLogFileVnode);
595
- currentLogFileVnode = NULL;
596
- }
597
-
598
- if (rollingTimer)
599
- {
600
- dispatch_source_cancel(rollingTimer);
601
- rollingTimer = NULL;
602
- }
603
- }
604
-
605
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
606
- #pragma mark Properties
607
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
608
-
609
- @synthesize logFileManager;
610
-
611
- - (unsigned long long)maximumFileSize
612
- {
613
- __block unsigned long long result;
614
-
615
- dispatch_block_t block = ^{
616
- result = maximumFileSize;
617
- };
618
-
619
- // The design of this method is taken from the DDAbstractLogger implementation.
620
- // For extensive documentation please refer to the DDAbstractLogger implementation.
621
-
622
- // Note: The internal implementation MUST access the maximumFileSize variable directly,
623
- // This method is designed explicitly for external access.
624
- //
625
- // Using "self." syntax to go through this method will cause immediate deadlock.
626
- // This is the intended result. Fix it by accessing the ivar directly.
627
- // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
628
-
629
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
630
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
631
-
632
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
633
-
634
- dispatch_sync(globalLoggingQueue, ^{
635
- dispatch_sync(loggerQueue, block);
636
- });
637
-
638
- return result;
639
- }
640
-
641
- - (void)setMaximumFileSize:(unsigned long long)newMaximumFileSize
642
- {
643
- dispatch_block_t block = ^{ @autoreleasepool {
644
-
645
- maximumFileSize = newMaximumFileSize;
646
- [self maybeRollLogFileDueToSize];
647
-
648
- }};
649
-
650
- // The design of this method is taken from the DDAbstractLogger implementation.
651
- // For extensive documentation please refer to the DDAbstractLogger implementation.
652
-
653
- // Note: The internal implementation MUST access the maximumFileSize variable directly,
654
- // This method is designed explicitly for external access.
655
- //
656
- // Using "self." syntax to go through this method will cause immediate deadlock.
657
- // This is the intended result. Fix it by accessing the ivar directly.
658
- // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
659
-
660
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
661
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
662
-
663
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
664
-
665
- dispatch_async(globalLoggingQueue, ^{
666
- dispatch_async(loggerQueue, block);
667
- });
668
- }
669
-
670
- - (NSTimeInterval)rollingFrequency
671
- {
672
- __block NSTimeInterval result;
673
-
674
- dispatch_block_t block = ^{
675
- result = rollingFrequency;
676
- };
677
-
678
- // The design of this method is taken from the DDAbstractLogger implementation.
679
- // For extensive documentation please refer to the DDAbstractLogger implementation.
680
-
681
- // Note: The internal implementation should access the rollingFrequency variable directly,
682
- // This method is designed explicitly for external access.
683
- //
684
- // Using "self." syntax to go through this method will cause immediate deadlock.
685
- // This is the intended result. Fix it by accessing the ivar directly.
686
- // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
687
-
688
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
689
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
690
-
691
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
692
-
693
- dispatch_sync(globalLoggingQueue, ^{
694
- dispatch_sync(loggerQueue, block);
695
- });
696
-
697
- return result;
698
- }
699
-
700
- - (void)setRollingFrequency:(NSTimeInterval)newRollingFrequency
701
- {
702
- dispatch_block_t block = ^{ @autoreleasepool {
703
-
704
- rollingFrequency = newRollingFrequency;
705
- [self maybeRollLogFileDueToAge];
706
- }};
707
-
708
- // The design of this method is taken from the DDAbstractLogger implementation.
709
- // For extensive documentation please refer to the DDAbstractLogger implementation.
710
-
711
- // Note: The internal implementation should access the rollingFrequency variable directly,
712
- // This method is designed explicitly for external access.
713
- //
714
- // Using "self." syntax to go through this method will cause immediate deadlock.
715
- // This is the intended result. Fix it by accessing the ivar directly.
716
- // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
717
-
718
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
719
- NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
720
-
721
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
722
-
723
- dispatch_async(globalLoggingQueue, ^{
724
- dispatch_async(loggerQueue, block);
725
- });
726
- }
727
-
728
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
729
- #pragma mark File Rolling
730
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
731
-
732
- - (void)scheduleTimerToRollLogFileDueToAge
733
- {
734
- if (rollingTimer)
735
- {
736
- dispatch_source_cancel(rollingTimer);
737
- rollingTimer = NULL;
738
- }
739
-
740
- if (currentLogFileInfo == nil || rollingFrequency <= 0.0)
741
- {
742
- return;
743
- }
744
-
745
- NSDate *logFileCreationDate = [currentLogFileInfo creationDate];
746
-
747
- NSTimeInterval ti = [logFileCreationDate timeIntervalSinceReferenceDate];
748
- ti += rollingFrequency;
749
-
750
- NSDate *logFileRollingDate = [NSDate dateWithTimeIntervalSinceReferenceDate:ti];
751
-
752
- NSLogVerbose(@"DDFileLogger: scheduleTimerToRollLogFileDueToAge");
753
-
754
- NSLogVerbose(@"DDFileLogger: logFileCreationDate: %@", logFileCreationDate);
755
- NSLogVerbose(@"DDFileLogger: logFileRollingDate : %@", logFileRollingDate);
756
-
757
- rollingTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue);
758
-
759
- dispatch_source_set_event_handler(rollingTimer, ^{ @autoreleasepool {
760
-
761
- [self maybeRollLogFileDueToAge];
762
-
763
- }});
764
-
765
- #if !OS_OBJECT_USE_OBJC
766
- dispatch_source_t theRollingTimer = rollingTimer;
767
- dispatch_source_set_cancel_handler(rollingTimer, ^{
768
- dispatch_release(theRollingTimer);
769
- });
770
- #endif
771
-
772
- uint64_t delay = (uint64_t)([logFileRollingDate timeIntervalSinceNow] * NSEC_PER_SEC);
773
- dispatch_time_t fireTime = dispatch_time(DISPATCH_TIME_NOW, delay);
774
-
775
- dispatch_source_set_timer(rollingTimer, fireTime, DISPATCH_TIME_FOREVER, 1.0);
776
- dispatch_resume(rollingTimer);
777
- }
778
-
779
-
780
- - (void)rollLogFile
781
- {
782
- [self rollLogFileWithCompletionBlock:nil];
783
- }
784
-
785
- - (void)rollLogFileWithCompletionBlock:(void (^)())completionBlock
786
- {
787
- // This method is public.
788
- // We need to execute the rolling on our logging thread/queue.
789
-
790
- dispatch_block_t block = ^{ @autoreleasepool {
791
-
792
- [self rollLogFileNow];
793
-
794
- if (completionBlock)
795
- {
796
- dispatch_async(dispatch_get_main_queue(), ^{
797
- completionBlock();
798
- });
799
- }
800
- }};
801
-
802
- // The design of this method is taken from the DDAbstractLogger implementation.
803
- // For extensive documentation please refer to the DDAbstractLogger implementation.
804
-
805
- if ([self isOnInternalLoggerQueue])
806
- {
807
- block();
808
- }
809
- else
810
- {
811
- dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
812
- NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
813
-
814
- dispatch_async(globalLoggingQueue, ^{
815
- dispatch_async(loggerQueue, block);
816
- });
817
- }
818
- }
819
-
820
- - (void)rollLogFileNow
821
- {
822
- NSLogVerbose(@"DDFileLogger: rollLogFileNow");
823
-
824
-
825
- if (currentLogFileHandle == nil) return;
826
-
827
- [currentLogFileHandle synchronizeFile];
828
- [currentLogFileHandle closeFile];
829
- currentLogFileHandle = nil;
830
-
831
- currentLogFileInfo.isArchived = YES;
832
-
833
- if ([logFileManager respondsToSelector:@selector(didRollAndArchiveLogFile:)])
834
- {
835
- [logFileManager didRollAndArchiveLogFile:(currentLogFileInfo.filePath)];
836
- }
837
-
838
- currentLogFileInfo = nil;
839
-
840
- if (currentLogFileVnode) {
841
- dispatch_source_cancel(currentLogFileVnode);
842
- currentLogFileVnode = NULL;
843
- }
844
-
845
- if (rollingTimer)
846
- {
847
- dispatch_source_cancel(rollingTimer);
848
- rollingTimer = NULL;
849
- }
850
- }
851
-
852
- - (void)maybeRollLogFileDueToAge
853
- {
854
- if (rollingFrequency > 0.0 && currentLogFileInfo.age >= rollingFrequency)
855
- {
856
- NSLogVerbose(@"DDFileLogger: Rolling log file due to age...");
857
-
858
- [self rollLogFileNow];
859
- }
860
- else
861
- {
862
- [self scheduleTimerToRollLogFileDueToAge];
863
- }
864
- }
865
-
866
- - (void)maybeRollLogFileDueToSize
867
- {
868
- // This method is called from logMessage.
869
- // Keep it FAST.
870
-
871
- // Note: Use direct access to maximumFileSize variable.
872
- // We specifically wrote our own getter/setter method to allow us to do this (for performance reasons).
873
-
874
- if (maximumFileSize > 0)
875
- {
876
- unsigned long long fileSize = [currentLogFileHandle offsetInFile];
877
-
878
- if (fileSize >= maximumFileSize)
879
- {
880
- NSLogVerbose(@"DDFileLogger: Rolling log file due to size (%qu)...", fileSize);
881
-
882
- [self rollLogFileNow];
883
- }
884
- }
885
- }
886
-
887
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
888
- #pragma mark File Logging
889
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
890
-
891
- /**
892
- * Returns the log file that should be used.
893
- * If there is an existing log file that is suitable,
894
- * within the constraints of maximumFileSize and rollingFrequency, then it is returned.
895
- *
896
- * Otherwise a new file is created and returned.
897
- **/
898
- - (DDLogFileInfo *)currentLogFileInfo
899
- {
900
- if (currentLogFileInfo == nil)
901
- {
902
- NSArray *sortedLogFileInfos = [logFileManager sortedLogFileInfos];
903
-
904
- if ([sortedLogFileInfos count] > 0)
905
- {
906
- DDLogFileInfo *mostRecentLogFileInfo = [sortedLogFileInfos objectAtIndex:0];
907
-
908
- BOOL useExistingLogFile = YES;
909
- BOOL shouldArchiveMostRecent = NO;
910
-
911
- if (mostRecentLogFileInfo.isArchived)
912
- {
913
- useExistingLogFile = NO;
914
- shouldArchiveMostRecent = NO;
915
- }
916
- else if (maximumFileSize > 0 && mostRecentLogFileInfo.fileSize >= maximumFileSize)
917
- {
918
- useExistingLogFile = NO;
919
- shouldArchiveMostRecent = YES;
920
- }
921
- else if (rollingFrequency > 0.0 && mostRecentLogFileInfo.age >= rollingFrequency)
922
- {
923
- useExistingLogFile = NO;
924
- shouldArchiveMostRecent = YES;
925
- }
926
-
927
-
928
- #if TARGET_OS_IPHONE
929
- // When creating log file on iOS we're setting NSFileProtectionKey attribute to NSFileProtectionCompleteUnlessOpen.
930
- //
931
- // But in case if app is able to launch from background we need to have an ability to open log file any time we
932
- // want (even if device is locked). Thats why that attribute have to be changed to
933
- // NSFileProtectionCompleteUntilFirstUserAuthentication.
934
- //
935
- // If previous log was created when app wasn't running in background, but now it is - we archive it and create
936
- // a new one.
937
-
938
- if (useExistingLogFile && doesAppRunInBackground()) {
939
- NSString *key = mostRecentLogFileInfo.fileAttributes[NSFileProtectionKey];
940
-
941
- if (! [key isEqualToString:NSFileProtectionCompleteUntilFirstUserAuthentication]) {
942
- useExistingLogFile = NO;
943
- shouldArchiveMostRecent = YES;
944
- }
945
- }
946
- #endif
947
-
948
- if (useExistingLogFile)
949
- {
950
- NSLogVerbose(@"DDFileLogger: Resuming logging with file %@", mostRecentLogFileInfo.fileName);
951
-
952
- currentLogFileInfo = mostRecentLogFileInfo;
953
- }
954
- else
955
- {
956
- if (shouldArchiveMostRecent)
957
- {
958
- mostRecentLogFileInfo.isArchived = YES;
959
-
960
- if ([logFileManager respondsToSelector:@selector(didArchiveLogFile:)])
961
- {
962
- [logFileManager didArchiveLogFile:(mostRecentLogFileInfo.filePath)];
963
- }
964
- }
965
- }
966
- }
967
-
968
- if (currentLogFileInfo == nil)
969
- {
970
- NSString *currentLogFilePath = [logFileManager createNewLogFile];
971
-
972
- currentLogFileInfo = [[DDLogFileInfo alloc] initWithFilePath:currentLogFilePath];
973
- }
974
- }
975
-
976
- return currentLogFileInfo;
977
- }
978
-
979
- - (NSFileHandle *)currentLogFileHandle
980
- {
981
- if (currentLogFileHandle == nil)
982
- {
983
- NSString *logFilePath = [[self currentLogFileInfo] filePath];
984
-
985
- currentLogFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
986
- [currentLogFileHandle seekToEndOfFile];
987
-
988
- if (currentLogFileHandle)
989
- {
990
- [self scheduleTimerToRollLogFileDueToAge];
991
-
992
- // Here we are monitoring the log file. In case if it would be deleted ormoved
993
- // somewhere we want to roll it and use a new one.
994
- currentLogFileVnode = dispatch_source_create(
995
- DISPATCH_SOURCE_TYPE_VNODE,
996
- [currentLogFileHandle fileDescriptor],
997
- DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME,
998
- loggerQueue
999
- );
1000
-
1001
- dispatch_source_set_event_handler(currentLogFileVnode, ^{ @autoreleasepool {
1002
- NSLogInfo(@"DDFileLogger: Current logfile was moved. Rolling it and creating a new one");
1003
- [self rollLogFileNow];
1004
- }});
1005
-
1006
- #if !OS_OBJECT_USE_OBJC
1007
- dispatch_source_t vnode = currentLogFileVnode;
1008
- dispatch_source_set_cancel_handler(currentLogFileVnode, ^{
1009
- dispatch_release(vnode);
1010
- });
1011
- #endif
1012
-
1013
- dispatch_resume(currentLogFileVnode);
1014
- }
1015
- }
1016
-
1017
- return currentLogFileHandle;
1018
- }
1019
-
1020
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1021
- #pragma mark DDLogger Protocol
1022
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1023
-
1024
- static int exception_count = 0;
1025
- - (void)logMessage:(DDLogMessage *)logMessage
1026
- {
1027
- NSString *logMsg = logMessage->logMsg;
1028
-
1029
- if (formatter)
1030
- {
1031
- logMsg = [formatter formatLogMessage:logMessage];
1032
- }
1033
-
1034
- if (logMsg)
1035
- {
1036
- if (![logMsg hasSuffix:@"\n"])
1037
- {
1038
- logMsg = [logMsg stringByAppendingString:@"\n"];
1039
- }
1040
-
1041
- NSData *logData = [logMsg dataUsingEncoding:NSUTF8StringEncoding];
1042
-
1043
- @try {
1044
- [[self currentLogFileHandle] writeData:logData];
1045
-
1046
- [self maybeRollLogFileDueToSize];
1047
- }
1048
- @catch (NSException *exception) {
1049
- exception_count++;
1050
- if (exception_count <= 10) {
1051
- NSLogError(@"DDFileLogger.logMessage: %@", exception);
1052
- if (exception_count == 10)
1053
- NSLogError(@"DDFileLogger.logMessage: Too many exceptions -- will not log any more of them.");
1054
- }
1055
- }
1056
- }
1057
- }
1058
-
1059
- - (void)willRemoveLogger
1060
- {
1061
- // If you override me be sure to invoke [super willRemoveLogger];
1062
-
1063
- [self rollLogFileNow];
1064
- }
1065
-
1066
- - (NSString *)loggerName
1067
- {
1068
- return @"cocoa.lumberjack.fileLogger";
1069
- }
1070
-
1071
- @end
1072
-
1073
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1074
- #pragma mark -
1075
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1076
-
1077
- #if TARGET_IPHONE_SIMULATOR
1078
- #define XATTR_ARCHIVED_NAME @"archived"
1079
- #else
1080
- #define XATTR_ARCHIVED_NAME @"lumberjack.log.archived"
1081
- #endif
1082
-
1083
- @implementation DDLogFileInfo
1084
-
1085
- @synthesize filePath;
1086
-
1087
- @dynamic fileName;
1088
- @dynamic fileAttributes;
1089
- @dynamic creationDate;
1090
- @dynamic modificationDate;
1091
- @dynamic fileSize;
1092
- @dynamic age;
1093
-
1094
- @dynamic isArchived;
1095
-
1096
-
1097
- #pragma mark Lifecycle
1098
-
1099
- + (instancetype)logFileWithPath:(NSString *)aFilePath
1100
- {
1101
- return [[self alloc] initWithFilePath:aFilePath];
1102
- }
1103
-
1104
- - (instancetype)initWithFilePath:(NSString *)aFilePath
1105
- {
1106
- if ((self = [super init]))
1107
- {
1108
- filePath = [aFilePath copy];
1109
- }
1110
- return self;
1111
- }
1112
-
1113
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1114
- #pragma mark Standard Info
1115
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1116
-
1117
- - (NSDictionary *)fileAttributes
1118
- {
1119
- if (fileAttributes == nil)
1120
- {
1121
- fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
1122
- }
1123
- return fileAttributes;
1124
- }
1125
-
1126
- - (NSString *)fileName
1127
- {
1128
- if (fileName == nil)
1129
- {
1130
- fileName = [filePath lastPathComponent];
1131
- }
1132
- return fileName;
1133
- }
1134
-
1135
- - (NSDate *)modificationDate
1136
- {
1137
- if (modificationDate == nil)
1138
- {
1139
- modificationDate = [[self fileAttributes] objectForKey:NSFileModificationDate];
1140
- }
1141
-
1142
- return modificationDate;
1143
- }
1144
-
1145
- - (NSDate *)creationDate
1146
- {
1147
- if (creationDate == nil)
1148
- {
1149
- creationDate = [[self fileAttributes] objectForKey:NSFileCreationDate];
1150
- }
1151
- return creationDate;
1152
- }
1153
-
1154
- - (unsigned long long)fileSize
1155
- {
1156
- if (fileSize == 0)
1157
- {
1158
- fileSize = [[[self fileAttributes] objectForKey:NSFileSize] unsignedLongLongValue];
1159
- }
1160
-
1161
- return fileSize;
1162
- }
1163
-
1164
- - (NSTimeInterval)age
1165
- {
1166
- return [[self creationDate] timeIntervalSinceNow] * -1.0;
1167
- }
1168
-
1169
- - (NSString *)description
1170
- {
1171
- return [@{@"filePath": self.filePath ?: @"",
1172
- @"fileName": self.fileName ?: @"",
1173
- @"fileAttributes": self.fileAttributes ?: @"",
1174
- @"creationDate": self.creationDate ?: @"",
1175
- @"modificationDate": self.modificationDate ?: @"",
1176
- @"fileSize": @(self.fileSize),
1177
- @"age": @(self.age),
1178
- @"isArchived": @(self.isArchived)} description];
1179
- }
1180
-
1181
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1182
- #pragma mark Archiving
1183
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1184
-
1185
- - (BOOL)isArchived
1186
- {
1187
-
1188
- #if TARGET_IPHONE_SIMULATOR
1189
-
1190
- // Extended attributes don't work properly on the simulator.
1191
- // So we have to use a less attractive alternative.
1192
- // See full explanation in the header file.
1193
-
1194
- return [self hasExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
1195
-
1196
- #else
1197
-
1198
- return [self hasExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
1199
-
1200
- #endif
1201
- }
1202
-
1203
- - (void)setIsArchived:(BOOL)flag
1204
- {
1205
-
1206
- #if TARGET_IPHONE_SIMULATOR
1207
-
1208
- // Extended attributes don't work properly on the simulator.
1209
- // So we have to use a less attractive alternative.
1210
- // See full explanation in the header file.
1211
-
1212
- if (flag)
1213
- [self addExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
1214
- else
1215
- [self removeExtensionAttributeWithName:XATTR_ARCHIVED_NAME];
1216
-
1217
- #else
1218
-
1219
- if (flag)
1220
- [self addExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
1221
- else
1222
- [self removeExtendedAttributeWithName:XATTR_ARCHIVED_NAME];
1223
-
1224
- #endif
1225
- }
1226
-
1227
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1228
- #pragma mark Changes
1229
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1230
-
1231
- - (void)reset
1232
- {
1233
- fileName = nil;
1234
- fileAttributes = nil;
1235
- creationDate = nil;
1236
- modificationDate = nil;
1237
- }
1238
-
1239
- - (void)renameFile:(NSString *)newFileName
1240
- {
1241
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
1242
- // See full explanation in the header file.
1243
-
1244
- if (![newFileName isEqualToString:[self fileName]])
1245
- {
1246
- NSString *fileDir = [filePath stringByDeletingLastPathComponent];
1247
-
1248
- NSString *newFilePath = [fileDir stringByAppendingPathComponent:newFileName];
1249
-
1250
- NSLogVerbose(@"DDLogFileInfo: Renaming file: '%@' -> '%@'", self.fileName, newFileName);
1251
-
1252
- NSError *error = nil;
1253
- if (![[NSFileManager defaultManager] fileExistsAtPath:newFilePath]){
1254
- if([[NSFileManager defaultManager] removeItemAtPath:newFilePath error:&error]){
1255
- NSLogError(@"DDLogFileInfo: Error deleting archive (%@): %@", self.fileName, error);
1256
- }
1257
- }
1258
-
1259
- if (![[NSFileManager defaultManager] moveItemAtPath:filePath toPath:newFilePath error:&error])
1260
- {
1261
- NSLogError(@"DDLogFileInfo: Error renaming file (%@): %@", self.fileName, error);
1262
- }
1263
-
1264
- filePath = newFilePath;
1265
- [self reset];
1266
- }
1267
- }
1268
-
1269
-
1270
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1271
- #pragma mark Attribute Management
1272
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1273
-
1274
- #if TARGET_IPHONE_SIMULATOR
1275
-
1276
- // Extended attributes don't work properly on the simulator.
1277
- // So we have to use a less attractive alternative.
1278
- // See full explanation in the header file.
1279
-
1280
- - (BOOL)hasExtensionAttributeWithName:(NSString *)attrName
1281
- {
1282
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
1283
- // See full explanation in the header file.
1284
-
1285
- // Split the file name into components. File name may have various format, but generally
1286
- // structure is same:
1287
- //
1288
- // <name part>.<extension part> and <name part>.archived.<extension part>
1289
- // or
1290
- // <name part> and <name part>.archived
1291
- //
1292
- // So we want to search for the attrName in the components (ignoring the first array index).
1293
-
1294
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
1295
-
1296
- // Watch out for file names without an extension
1297
-
1298
- for (NSUInteger i = 1; i < components.count; i++)
1299
- {
1300
- NSString *attr = [components objectAtIndex:i];
1301
-
1302
- if ([attrName isEqualToString:attr])
1303
- {
1304
- return YES;
1305
- }
1306
- }
1307
-
1308
- return NO;
1309
- }
1310
-
1311
- - (void)addExtensionAttributeWithName:(NSString *)attrName
1312
- {
1313
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
1314
- // See full explanation in the header file.
1315
-
1316
- if ([attrName length] == 0) return;
1317
-
1318
- // Example:
1319
- // attrName = "archived"
1320
- //
1321
- // "mylog.txt" -> "mylog.archived.txt"
1322
- // "mylog" -> "mylog.archived"
1323
-
1324
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
1325
-
1326
- NSUInteger count = [components count];
1327
-
1328
- NSUInteger estimatedNewLength = [[self fileName] length] + [attrName length] + 1;
1329
- NSMutableString *newFileName = [NSMutableString stringWithCapacity:estimatedNewLength];
1330
-
1331
- if (count > 0)
1332
- {
1333
- [newFileName appendString:[components objectAtIndex:0]];
1334
- }
1335
-
1336
- NSString *lastExt = @"";
1337
-
1338
- NSUInteger i;
1339
- for (i = 1; i < count; i++)
1340
- {
1341
- NSString *attr = [components objectAtIndex:i];
1342
- if ([attr length] == 0)
1343
- {
1344
- continue;
1345
- }
1346
-
1347
- if ([attrName isEqualToString:attr])
1348
- {
1349
- // Extension attribute already exists in file name
1350
- return;
1351
- }
1352
-
1353
- if ([lastExt length] > 0)
1354
- {
1355
- [newFileName appendFormat:@".%@", lastExt];
1356
- }
1357
-
1358
- lastExt = attr;
1359
- }
1360
-
1361
- [newFileName appendFormat:@".%@", attrName];
1362
-
1363
- if ([lastExt length] > 0)
1364
- {
1365
- [newFileName appendFormat:@".%@", lastExt];
1366
- }
1367
-
1368
- [self renameFile:newFileName];
1369
- }
1370
-
1371
- - (void)removeExtensionAttributeWithName:(NSString *)attrName
1372
- {
1373
- // This method is only used on the iPhone simulator, where normal extended attributes are broken.
1374
- // See full explanation in the header file.
1375
-
1376
- if ([attrName length] == 0) return;
1377
-
1378
- // Example:
1379
- // attrName = "archived"
1380
- //
1381
- // "mylog.archived.txt" -> "mylog.txt"
1382
- // "mylog.archived" -> "mylog"
1383
-
1384
- NSArray *components = [[self fileName] componentsSeparatedByString:@"."];
1385
-
1386
- NSUInteger count = [components count];
1387
-
1388
- NSUInteger estimatedNewLength = [[self fileName] length];
1389
- NSMutableString *newFileName = [NSMutableString stringWithCapacity:estimatedNewLength];
1390
-
1391
- if (count > 0)
1392
- {
1393
- [newFileName appendString:[components objectAtIndex:0]];
1394
- }
1395
-
1396
- BOOL found = NO;
1397
-
1398
- NSUInteger i;
1399
- for (i = 1; i < count; i++)
1400
- {
1401
- NSString *attr = [components objectAtIndex:i];
1402
-
1403
- if ([attrName isEqualToString:attr])
1404
- {
1405
- found = YES;
1406
- }
1407
- else
1408
- {
1409
- [newFileName appendFormat:@".%@", attr];
1410
- }
1411
- }
1412
-
1413
- if (found)
1414
- {
1415
- [self renameFile:newFileName];
1416
- }
1417
- }
1418
-
1419
- #else
1420
-
1421
- - (BOOL)hasExtendedAttributeWithName:(NSString *)attrName
1422
- {
1423
- const char *path = [filePath UTF8String];
1424
- const char *name = [attrName UTF8String];
1425
-
1426
- ssize_t result = getxattr(path, name, NULL, 0, 0, 0);
1427
-
1428
- return (result >= 0);
1429
- }
1430
-
1431
- - (void)addExtendedAttributeWithName:(NSString *)attrName
1432
- {
1433
- const char *path = [filePath UTF8String];
1434
- const char *name = [attrName UTF8String];
1435
-
1436
- int result = setxattr(path, name, NULL, 0, 0, 0);
1437
-
1438
- if (result < 0)
1439
- {
1440
- NSLogError(@"DDLogFileInfo: setxattr(%@, %@): error = %s",
1441
- attrName,
1442
- self.fileName,
1443
- strerror(errno));
1444
- }
1445
- }
1446
-
1447
- - (void)removeExtendedAttributeWithName:(NSString *)attrName
1448
- {
1449
- const char *path = [filePath UTF8String];
1450
- const char *name = [attrName UTF8String];
1451
-
1452
- int result = removexattr(path, name, 0);
1453
-
1454
- if (result < 0 && errno != ENOATTR)
1455
- {
1456
- NSLogError(@"DDLogFileInfo: removexattr(%@, %@): error = %s",
1457
- attrName,
1458
- self.fileName,
1459
- strerror(errno));
1460
- }
1461
- }
1462
-
1463
- #endif
1464
-
1465
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1466
- #pragma mark Comparisons
1467
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1468
-
1469
- - (BOOL)isEqual:(id)object
1470
- {
1471
- if ([object isKindOfClass:[self class]])
1472
- {
1473
- DDLogFileInfo *another = (DDLogFileInfo *)object;
1474
-
1475
- return [filePath isEqualToString:[another filePath]];
1476
- }
1477
-
1478
- return NO;
1479
- }
1480
-
1481
- - (NSComparisonResult)reverseCompareByCreationDate:(DDLogFileInfo *)another
1482
- {
1483
- NSDate *us = [self creationDate];
1484
- NSDate *them = [another creationDate];
1485
-
1486
- NSComparisonResult result = [us compare:them];
1487
-
1488
- if (result == NSOrderedAscending)
1489
- return NSOrderedDescending;
1490
-
1491
- if (result == NSOrderedDescending)
1492
- return NSOrderedAscending;
1493
-
1494
- return NSOrderedSame;
1495
- }
1496
-
1497
- - (NSComparisonResult)reverseCompareByModificationDate:(DDLogFileInfo *)another
1498
- {
1499
- NSDate *us = [self modificationDate];
1500
- NSDate *them = [another modificationDate];
1501
-
1502
- NSComparisonResult result = [us compare:them];
1503
-
1504
- if (result == NSOrderedAscending)
1505
- return NSOrderedDescending;
1506
-
1507
- if (result == NSOrderedDescending)
1508
- return NSOrderedAscending;
1509
-
1510
- return NSOrderedSame;
1511
- }
1512
-
1513
- @end
1514
-
1515
- #if TARGET_OS_IPHONE
1516
- /**
1517
- * When creating log file on iOS we're setting NSFileProtectionKey attribute to NSFileProtectionCompleteUnlessOpen.
1518
- *
1519
- * But in case if app is able to launch from background we need to have an ability to open log file any time we
1520
- * want (even if device is locked). Thats why that attribute have to be changed to
1521
- * NSFileProtectionCompleteUntilFirstUserAuthentication.
1522
- */
1523
- BOOL doesAppRunInBackground()
1524
- {
1525
- BOOL answer = NO;
1526
-
1527
- NSArray *backgroundModes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIBackgroundModes"];
1528
-
1529
- for (NSString *mode in backgroundModes) {
1530
- if (mode.length > 0) {
1531
- answer = YES;
1532
- break;
1533
- }
1534
- }
1535
-
1536
- return answer;
1537
- }
1538
- #endif
1539
-