Commit graph

572 commits

Author SHA1 Message Date
Michael Hanselmann
ceae4a9fa8 Support patterns on extraction, fixes #361
This change implements the functionality requested in issue #361:
extracting files with a given extension. It does so by permitting
patterns to be used instead plain prefix paths. The pattern styles
supported are the same as for exclusions.
2016-01-18 21:26:08 +01:00
Michael Hanselmann
848375e2fe Add and document path prefix as pattern style
The “extract” command supports extracting all files underneath a given
set of prefix paths. The forthcoming support for extracting files using
a pattern (i.e. only files ending in “.zip”) requires the introduction
of path prefixes as a third pattern style, making it also available for
exclusions.
2016-01-18 21:26:08 +01:00
Michael Hanselmann
b6362b5963 Flexible default pattern style
A function to parse pattern specifications was introduced in commit
2bafece. Since then it had a hardcoded default style of “fm”, meaning
fnmatch. With the forthcoming support for extracting files using
patterns this default style must be more flexible.
2016-01-18 20:59:09 +01:00
Michael Hanselmann
1fa4d2e516 Use constants for pattern style prefixes
The prefix used for pattern styles should be kept together with the
respective style implementation.
2016-01-18 20:59:08 +01:00
Michael Hanselmann
190107ada7 Replace use of “exclude_path” in tests
The newly added pattern matcher class can replace the “exclude_path”
function. The latter is going to be removed in a later change.
2016-01-18 20:59:08 +01:00
Michael Hanselmann
9747755131 Add pattern matcher wrapper
The utility functions “adjust_patterns” and “exclude_path” produce
respectively use a standard list object containing pattern objects.
With the forthcoming introduction of patterns for filtering files
to be extracted it's better to move the logic of these classes into
a single class.

The wrapper allows adding any number of patterns to an internal list
together with a value to be returned if a match function finds that
one of the patterns matches. A fallback value is returned otherwise.
2016-01-18 20:59:08 +01:00
Michael Hanselmann
c1feb4b532 Simplify pattern tests
- Stop using “adjust_pattern” and “exclude_path” as they're utility
  functions not relevant to testing pattern classes
- Cover a few more cases, especially with more than one path separator
  and relative paths
- At least one dedicated test function for each pattern style as opposed
  to a single, big test mixing styles
- Use positive instead of negative matching (i.e. the expected list of
  resulting items is a list of items matching a pattern)
2016-01-18 20:47:22 +01:00
TW
735fe557e2 Merge pull request #571 from ThomasWaldmann/fix-570
fix crash when using borg create --dry-run --keep-tag-files, fixes #570
2016-01-18 16:16:54 +01:00
Thomas Waldmann
4c00bb0d2f fix crash when using borg create --dry-run --keep-tag-files, fixes #570 2016-01-18 14:30:41 +01:00
TW
f2f2810b5a Merge pull request #568 from ypid/docs-fixes
Docs fixes.
2016-01-18 11:02:13 +01:00
TW
1878e223d6 Merge pull request #566 from ThomasWaldmann/cache-ctxmgr
implement and use context manager for Cache, partial fix for #285
2016-01-18 01:00:17 +01:00
TW
704b505968 Merge pull request #565 from ThomasWaldmann/repocache-ctxmgr
Repocache ctxmgr
2016-01-18 00:58:23 +01:00
Robin Schneider
576348a9d4
Use HTTPS everywhere. Especially when the website already redirects to HTTPS. 2016-01-17 22:31:08 +01:00
Robin Schneider
1f1ff61375
borg prune only knows "--keep-within" and not "--within". 2016-01-17 21:15:26 +01:00
Thomas Waldmann
22f218baef implement and use context manager for Cache, partial fix for #285
also: make check in Lock.close more precise, check for "is not None".

note: a lot of blocks were just indented to be under the "with" statement,
in one case a block had to be moved into a function.
2016-01-17 01:15:42 +01:00
Thomas Waldmann
5ec2a3a49b use the RepositoryCache context manager also in fuse code 2016-01-17 00:30:00 +01:00
Thomas Waldmann
4d73f3cdb9 implement and use context manager for RepositoryCache, fixes #548 2016-01-17 00:30:00 +01:00
Thomas Waldmann
9198f6962c implement --progress option for borg delete <archive> 2016-01-16 20:46:49 +01:00
Thomas Waldmann
0213164d46 implement --progress option for borg upgrade, fixes #291 2016-01-16 20:32:24 +01:00
Thomas Waldmann
e68b800d01 remove unused "repair" rpc method
there is no such method in the code.
we use "check" method to repair the repo, so maybe this was left over
from a time when repair was separate from check.
2016-01-16 18:58:52 +01:00
Thomas Waldmann
845d2144cb fix locking, partial fix for #502
the problem was that the borg process removed its own shared lock when upgrading it to an exclusive lock.
this is fine if we get the exclusive lock, but if we don't, we must re-add our shared lock.

this fixes the KeyError in locking.py:217
2016-01-16 18:03:58 +01:00
TW
f35ba0b577 Merge pull request #559 from ThomasWaldmann/metastream-chunker
finer chunker granularity for items metadata stream, fixes #547, fixes #487
2016-01-15 22:42:20 +01:00
TW
d248a7d537 Merge pull request #557 from hansmi/pattern-cleanup
Rename pattern classes and refactor tests
2016-01-15 21:50:04 +01:00
Thomas Waldmann
888e078382 use finer chunker granularity for items metadata stream, fixes #547, fixes #487
the items metadata stream is usually not that big (compared to the file content data) -
it is just file and dir names and other metadata.

if we use too rough granularity there (and big minimum chunk size), we usually will get no deduplication.
2016-01-15 20:56:21 +01:00
TW
b8789f7bde Merge pull request #552 from ThomasWaldmann/hashtable-resizing
Hashtable resizing
2016-01-15 20:54:28 +01:00
Michael Hanselmann
3a39ddbd83 Rename pattern classes for consistency
The class names “IncludePattern” and “ExcludePattern” may have been
appropriate when they were the only styles. With the recent addition of
regular expression support and with at least one more style being added
in forthcoming changes these classes should be renamed to be more
descriptive. “ExcludeRegex” is also renamed to match the new names.
2016-01-15 17:16:25 +01:00
Michael Hanselmann
2c7ab8595d Refactor Unicode pattern tests
The unit tests for Unicode in path patterns contained a lot of
unnecessary duplication. One set of duplication was for Mac OS X (also
known as Darwin) as it normalizes Unicode in paths to NFD. Then each
test case was repeated for every type of pattern.

With this change the tests become parametrized using py.test. The
duplicated code has been removed.
2016-01-15 17:16:25 +01:00
Thomas Waldmann
96f88a29d2 add --list option for borg create
like --stats enables statistics output, --list enables the file/dirs list output.
2016-01-14 18:57:05 +01:00
Michael Hanselmann
b6d0ee7c13 Capitalization fixes for upgrade help epilog 2016-01-14 17:04:34 +01:00
Thomas Waldmann
5cb47cbedd hashindex: explain hash_sizes 2016-01-14 14:39:59 +01:00
Thomas Waldmann
083f5e31ef hashindex: fix upper limit
use num_buckets (== fully use what we currently have allocated)
2016-01-14 14:39:59 +01:00
Thomas Waldmann
09665805e8 move func defs to avoid implicit declaration compiler warning 2016-01-14 14:39:59 +01:00
Thomas Waldmann
91cde721b4 hashindex: minor refactor
- rename BUCKET_(LOWER|UPPER)_LIMIT to HASH_(MIN|MAX)_LOAD
   as this value is usually called the hash table's minimum/maximum load factor.
- remove MAX_BUCKET_SIZE (not used)
- regroup/reorder definitions
2016-01-14 14:39:59 +01:00
Thomas Waldmann
d88df3edc6 hashtable size follows a growth policy, fixes #527
also: refactor / dedupe some code into functions
2016-01-14 14:39:59 +01:00
TW
89169c3f87 Merge pull request #542 from ThomasWaldmann/fix-stats-logging
log stats consistently, fixes #526
2016-01-14 14:33:53 +01:00
Michael Hanselmann
2369b8a0f2 Strip whitespace when loading exclusions from file
Patterns to exclude files can be loaded from a text file using the
“--exclude-from” option. Whitespace at the beginning or end of lines was
not stripped. Indented comments would be interpreted as a pattern and
a misplaced space at the end of a line--some text editors don't strip
them--could cause an exclusion pattern to not match as desired. With the
recent addition of regular expression support for exclusions the spaces
can be matched if necessary (“^\s” or “\s$”), though it's highly
unlikely that there are many paths deliberately starting or ending with
whitespace.
2016-01-13 17:39:22 +01:00
Michael Hanselmann
2bafece093 Implement exclusions using regular expressions
The existing option to exclude files and directories, “--exclude”, is
implemented using fnmatch[1]. fnmatch matches the slash (“/”) with “*”
and thus makes it impossible to write patterns where a directory with
a given name should be excluded at a specific depth in the directory
hierarchy, but not anywhere else. Consider this structure:

  home/
  home/aaa
  home/aaa/.thumbnails
  home/user
  home/user/img
  home/user/img/.thumbnails

fnmatch incorrectly excludes “home/user/img/.thumbnails” with a pattern
of “home/*/.thumbnails” when the intention is to exclude “.thumbnails”
in all home directories while retaining directories with the same name
in all other locations.

With this change regular expressions are introduced as an additional
pattern syntax. The syntax is selected using a prefix on “--exclude”'s
value. “re:” is for regular expression and “fm:”, the default, selects
fnmatch. Selecting the syntax is necessary when regular expressions are
desired or when the desired fnmatch pattern starts with two alphanumeric
characters followed by a colon (i.e. “aa:something/*”). The exclusion
described above can be implemented as follows:

  --exclude 're:^home/[^/]+/\.thumbnails$'

The “--exclude-from” option permits loading exclusions from a text file
where the same prefixes can now be used, e.g. “re:\.tmp$”.

The documentation has been extended and now not only describes the two
pattern styles, but also the file format supported by “--exclude-from”.

This change has been discussed in issue #43 and in change request #497.

[1] https://docs.python.org/3/library/fnmatch.html

Signed-off-by: Michael Hanselmann <public@hansmi.ch>
2016-01-13 17:39:19 +01:00
Michael Hanselmann
93c9c49250 Reduce code duplication in inclusion/exclusion pattern logic
The two classes for applying inclusion and exclusion patterns contained
unnecessarily duplicated logic. The introduction of a shared base class
allows for easier reuse, especially considering that two more classes
are going to be added in forthcoming changes (regular expressions and
shell-style patterns).
2016-01-13 14:35:59 +01:00
Michael Hanselmann
5d40eba175 Convert pattern test to py.test
The test for exclusion patterns was written using the standard unittest
module. The py.test module provides facilities to parametrize the test.
2016-01-13 12:39:37 +01:00
TW
4a9672e8d5 Merge pull request #538 from ThomasWaldmann/fix-library-path
unset LD_LIBRARY_PATH before invoking ssh, hopefully fixes #514
2016-01-12 19:58:04 +01:00
TW
2921b60e69 Merge pull request #539 from ThomasWaldmann/add-version
display borg version below tracebacks, fixes #532
2016-01-12 19:57:41 +01:00
TW
0f02513410 Merge pull request #540 from ThomasWaldmann/isotimestamp-with-wkday
add abbreviated weekday to timestamp format, fixes #496
2016-01-12 19:57:14 +01:00
Michael Hanselmann
98da9d1b96 Dedent pattern help text
The help text describing patterns should be dedented like other
multi-paragraph text blocks.
2016-01-12 17:53:34 +01:00
Thomas Waldmann
84672f7081 log stats consistently, fixes #526
prune and create now both require --verbose --stats to show stats.
it was implemented in this way (and not with print) so you can feed the stats data
into the logging system, too.

delete now says "Archive deleted" in verbose mode (for consistency,
it already said "Repository deleted" when deleting a repo).

also: add helpers.log_multi to comfortably and prettily output a block of log lines
2016-01-12 00:41:06 +01:00
Thomas Waldmann
e5c29bd145 add abbreviated weekday to timestamp format, fixes #496 2016-01-11 23:31:24 +01:00
Thomas Waldmann
857f563307 display borg version below tracebacks, fixes #532 2016-01-11 23:22:04 +01:00
Michael Hanselmann
02e04653b6 Factorize and test loading of excludes from file
The parsing code for exclude files (given via `--exclude-from`) was not
tested. Its core is factorized into a separate function to facilitate an
easier test. The observable behaviour is unchanged.
2016-01-11 12:24:26 +01:00
Thomas Waldmann
170f847e74 unset LD_LIBRARY_PATH before invoking ssh, hopefully fixes #514 2016-01-11 02:08:58 +01:00
Michael Hanselmann
d668901df4 Fix typo in comment 2016-01-07 11:18:03 +01:00
TW
48e9b9cb15 Merge pull request #524 from ThomasWaldmann/libc-loader-fallback
add some error handling/fallback for C library loading, fixes #494
2016-01-06 14:43:17 +01:00
Thomas Waldmann
4ed71e2cf5 add some error handling/fallback for C library loading, fixes #494 2015-12-27 14:10:41 +01:00
Thomas Waldmann
c9afa2b27b output progress indication from inner loop, fixes #500
- so it shows progress while it backups a bigger file
- so it announces the filename earlier

also: move rate limiting code to show_progress()
2015-12-27 11:06:03 +01:00
Thomas Waldmann
57b913bc88 fix badly named environment variable, fixes #503
added: BORG_DELETE_I_KNOW_WHAT_I_AM_DOING for the check in "borg delete"
2015-12-20 02:03:33 +01:00
Thomas Waldmann
95f6cd4a4e Merge branch 'master' of github.com:borgbackup/borg 2015-12-13 14:26:49 +01:00
Thomas Waldmann
0c166898bf fix python 3.2 str.splitlines() compatibility issue 2015-12-13 00:51:39 +01:00
Thomas Waldmann
aa97724c0c add --prefix to check to check only some specific archives, fixes #206 2015-12-13 00:39:52 +01:00
Thomas Waldmann
942120997e log remote exceptions, add remote sysinfo 2015-12-12 22:45:29 +01:00
Thomas Waldmann
2df0bb1f83 remote stderr: keep line endings as is
so even the \r trick works for overwriting the same line.
2015-12-12 22:15:08 +01:00
Thomas Waldmann
2e2e145372 sane remote logging, remote stderr, fixes #461 2015-12-12 22:15:08 +01:00
Thomas Waldmann
229512b6f5 determine log level from the logger, so it works with logging.conf also 2015-12-12 22:15:08 +01:00
Thomas Waldmann
f59db03c60 ProgressIndicator: flush the output file or it won't work correctly via ssh
likely due to buffering, the progress indication was not visible.
2015-12-12 22:15:08 +01:00
Thomas Waldmann
eab60cce99 pass through some global options from client to server
new: logging level options
refactored:
- umask option and remote_path
- cleanly separated ssh command from borg command
2015-12-12 22:15:08 +01:00
Thomas Waldmann
c194f3ca1c give (all) args to open_repository 2015-12-12 22:15:08 +01:00
Thomas Waldmann
9c271afefa unify repo/archive parameter name to "location" 2015-12-12 22:15:08 +01:00
Thomas Waldmann
e3d5898add borg upgrade - use inplace parameter, fixes #466
i checked it: copying the index.* and hints.* files in advance is not needed, open() and close() do not modify them.

also: fix unicode exception with encoded filename
2015-12-11 22:18:18 +01:00
TW
bbeda1f743 Merge pull request #481 from ThomasWaldmann/fix-progress
remove --progress magic, fixes #476
2015-12-10 13:34:02 +01:00
Thomas Waldmann
60babd14c3 borg upgrade - do not overwrite backup_repo/index.*, fixes #466
the code obviously wrote to both index.* files as they were hardlinked.
now we make a normal copy of index (and also hints) to avoid this.
2015-12-10 11:59:13 +01:00
Thomas Waldmann
cd804e72b7 borg upgrade - move some code to convert_repo_index
it was a bit confusing to have repo-related code in a method called "convert_cache".
also fixed a typo "index index".
2015-12-10 11:35:48 +01:00
Thomas Waldmann
7acda553ff borg upgrade - fix locking
because Repository.__init__ normally opens and locks the repo, and the upgrader just
inherited from (borg) Repository, it created a lock file there before the "backup copy"
was made.

No big problem, but a bit unclean.

Fixed it to not lock at the beginning, then make the copy, then lock.
2015-12-10 11:11:06 +01:00
Thomas Waldmann
e9ab11be49 borg upgrade - fix README contents 2015-12-10 10:51:56 +01:00
Thomas Waldmann
34b35761dd remove --progress magic, fixes #476
For 0.29 we worked towards a "silent by default" behaviour, so interactive usage will include -v more frequently in future.

But I noticed that this conflicts with the progress display. This would be no problem if users willingly decide which one
of --verbose or --progress they want to see, but before this fix, the progress display was activated magically when
a tty was detected. So, to counteract this magic, users would need to use --no-progress.

That's backwards imho, so I removed the magic again and users have to give --progress when they want
to see a progress indicator. Or (alternatively) they give --verbose when they want to see the long file list.
2015-12-10 10:28:43 +01:00
Thomas Waldmann
8671be1ef2 Increase FUSE read_size to 1024.
From https://github.com/borgbackup/borg/pull/480 discussion:

Did you try 1024 (linux cache block size) or 4096 (internal sector size of bigger
hdds, also used in msgpack fallback.py as lower bound, see link)?

I've tested different values - 512 and 1024 are slightly better than 4096 in my case.

read_size = 1    ls -laR: 75.57 sec
read_size = 64   ls -laR: 27.81 sec
read_size = 512          ls -laR: 27.40 sec
read_size = 1024         ls -laR: 27.20 sec
read_size = 4096         ls -laR: 30.15 sec
read_size = 0    ls -laR: 442.96 sec (default)

OK, maybe we should go for 1024 then. That happens to be < MTU size, so in case someone works on NFS
(or other network FS) we will have less reads, less network packets, less latency.
2015-12-10 10:09:06 +01:00
TW
c4588e4eb4 Merge pull request #480 from alex3d/patch-1
Optimized fuse inode cache
2015-12-10 10:05:09 +01:00
alex3d
3256f22c74 Optimized fuse inode cache
Single-shot unpacker read buffer decreased from (default) 1Mb to 512b.
"ls -alR" on ~100k files backup mounted with fuse went from ~7min to 30 seconds.
2015-12-09 00:34:25 +03:00
Thomas Waldmann
499b6f7313 add a test that invokes borg prune --save-space 2015-12-08 18:36:41 +01:00
Thomas Waldmann
0c076ad114 compact_segments: save_space -> free unused segments quickly
as soon as one target segment is full, it is a good time to commit it and remove the source segments
that are already completely unused (because they were transferred int the target segment).

so, for compact_segments(save_space=True), the additional space needed should be about 1 segment size.

note: we can't just do that at the end of one source segment as this might create very small
target segments, which is not wanted.
2015-12-08 18:36:41 +01:00
Thomas Waldmann
b41f6dfbbf Merge branch 'silent' of https://github.com/ThomasWaldmann/borg into ThomasWaldmann-silent 2015-12-08 01:56:44 +01:00
Thomas Waldmann
cb821b119b remove --log-level, add --debug and --info option, update docs
removed --log-level due to overlap with how --verbose works now.

for consistency, added --info as alias to --verbose (as the effect is
setting INFO log level).

also added --debug which sets DEBUG log level.
note: there are no messages emitted at DEBUG level yet.

WARNING is the default (because we want mostly silent behaviour,
except if something serious happens), so we don't need --warning
as an option.
2015-12-08 01:37:34 +01:00
Thomas Waldmann
68225af449 archive checker: remove report_progress, fix log levels 2015-12-08 00:59:41 +01:00
TW
d05b9b8ac9 Merge pull request #473 from ThomasWaldmann/hashindex-add
hashindex_add C implementation
2015-12-07 22:32:55 +01:00
Thomas Waldmann
720fc49498 hashindex_add C implementation
this was also the loop contents of hashindex_merge, but we also need it callable from Cython/Python code.

this saves some cycles, esp. if the key is already present in the index.
2015-12-07 19:13:58 +01:00
Jakob Schnitzer
3ca1d33d5c fix format of umask in help pages
fixes #463
2015-12-07 18:42:50 +01:00
Jakob Schnitzer
17952dff48 helpers: remove functions that are only used once
The read_msgpack and write_msgpack functions were only used in one place
each.  Since msgpack is read and written in lots of places, having
functions with these generic names is confusing. Also, the helpers
module is quite a mess, so reducing its size seems to be a good idea.
2015-12-07 14:29:01 +01:00
Thomas Waldmann
6d083c0695 increase rpc protocol version to 2
this is needed because due to the locking improvements, some rpc calls' signature changed slightly.
2015-12-03 17:50:37 +01:00
TW
f5634092a2 Merge pull request #455 from ThomasWaldmann/add-progress-indication
Add progress indication, fixes #394
2015-12-03 15:04:44 +01:00
Thomas Waldmann
df24ce5acd progress indicators: add tests 2015-12-03 14:45:16 +01:00
Thomas Waldmann
887196b00e progress indicators: better docstring, minor code improvement 2015-12-03 14:14:28 +01:00
TW
9005586ca4 Merge pull request #452 from ThomasWaldmann/hashtable
misc. hash table tuning
2015-12-02 16:45:39 +01:00
Stavros Korokithakis
d572ceaca2 Display proper repo URL. 2015-12-02 16:51:49 +02:00
Thomas Waldmann
21bd01ef16 add a --filter option replacing --changed/--unchanged
the problem here was that we do not just have changed and unchanged items,
but also a lot of items besides regular files which we just back up "as is" without
determining whether they are changed or not. thus, we can't support changed/unchanged
in a way users would expect them to work.

the A/M/U status only applies to the data content of regular files (compared to the index).
for all items, we ALWAYS save the metadata, there is no changed / not changed detection there.

thus, I replaced this with a --filter option where you can just specify which
status chars you want to see listed in the output.

E.g. --filter AM will only show regular files with A(dded) or M(odified) state, but nothing else.
Not giving --filter defaults to showing all items no matter what status they have.

Output is emitted via logger at info level, so it won't show up except if the logger is at that level.
2015-12-02 03:29:20 +01:00
Thomas Waldmann
fe6916bd22 refactor upgrade progress indication code to use ProgressIndicatorPercent 2015-12-02 01:26:26 +01:00
Thomas Waldmann
7a1316cb79 implement ProgressIndicators, use it for repo check and segment replay, fixes #195, fixes #188 2015-12-02 01:06:07 +01:00
Thomas Waldmann
610300c1ce misc. hash table tuning
BUCKET_UPPER_LIMIT: 90% load degrades hash table performance severely,
so I lowered that to 75% (which is a usual value - java uses 75%, python uses 66%).
I chose the higher value of both because we also should not consume too much
memory, considering the RAM usage already is rather high.

MIN_BUCKETS: I can't explain why, but benchmarks showed that choosing 2^N as
table size severely degrades performance (by 3 orders of magnitude!). So a prime
start value improves this a lot, even if we later still use the grow-by-2x algorithm.

hashindex_resize: removed the hashindex_get() call as we already know that the values
come at key + key_size address.

hashindex_init: do not calloc X*Y elements of size 1, but rather X elements of size Y.
Makes the code simpler, not sure if it affects performance.

The tests needed fixing as the resulting hashtable blob is now of course different due
to the above changes, so its sha hash changed.
2015-12-01 21:18:58 +01:00
Antoine Beaupré
b09643e14f change file status test and cleanup last ref to --verbose
this ports the changes here to #445
2015-11-24 12:11:43 -05:00
Antoine Beaupré
1785ca54ba do not display unchanged files by default
add a --unchanged topical file to display those files
2015-11-24 12:07:57 -05:00
Antoine Beaupré
fce5aed5bb move changed with other topical flags
we need to have a sane default there otherwise the option may not be defined in some sub-commands and will crash
2015-11-24 12:07:57 -05:00
Antoine Beaupré
8d3d1c22d6 silence borg by default
this also prints file status on stderr directly, bypassing the logger
as we do with other topical flags (like progress and status)
2015-11-24 12:07:56 -05:00
Antoine Beaupré
9899eaf241 silence file listing unless --changed is present 2015-11-24 12:07:56 -05:00
Antoine Beaupré
6b265f2a53 alias --verbose to --log-level=info
print_verbose is now simply logger.info() and is always displayed if
log level allows it. this affects only the `prune` and `mount`
commands which were the only users of the --verbose option. the
additional display is which archives are kept and pruned and a single
message when the fileystem is mounted.

files iteration in create and extract is now printed through a
separate function which will be later controled through a topical
flag.
2015-11-24 12:07:03 -05:00
Antoine Beaupré
a75d77226b add test for the weird unchanged file status
this tests the behaviour found in #403 and documented in #418, but doesn't fail on the unexpected A
2015-11-23 19:44:54 -05:00