Commit Graph

2697 Commits

Author SHA1 Message Date
Carsten Hammer 74bc50125d Replace chain of if statements with switch
and switch over strings where possible. Sometimes if statements are
chained and form a series of comparisons against constants. Using switch
statements improves readability.

Bug: 545856
Change-Id: Iacb78956ee5c20db4d793e6b668508ec67466606
Signed-off-by: Carsten Hammer <carsten.hammer@t-online.de>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-14 20:42:03 +01:00
David Pursehouse 8a633bde8a Merge branch 'stable-5.6'
* stable-5.6:
  Cleanup CommitAndLogCommandTest
  CLI: Add support for excluding paths from Git log command

Change-Id: I2f48e16640ab1b13f0c32779422add3162260c50
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
2019-12-06 10:20:07 +09:00
Matthias Sohn 02dc0ca688 Cleanup CommitAndLogCommandTest
- if a test can throw different exceptions declare it throws Exception
- fix code formatting

Change-Id: I55d63918f3163b31f2297d6217d5855108dd43b5
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-05 22:48:55 +01:00
John Tipper 5bf226d50c CLI: Add support for excluding paths from Git log command
Git log supports the exclude pathspec, which allows for excluding paths
from the log command. JGit only supports adding paths to the log
command. See the following StackOverflow question for details:
https://stackoverflow.com/questions/59143934/java-jgit-how-to-get-git-
commits-not-affecting-certain-directories
This commit adds an excludePath() method to the log command. It does not
yet support regex or glob wildcards.

Change-Id: I8cd59950b87850b55a15c7e2ea5470145c9aae28
Signed-off-by: John Tipper <john_tipper@hotmail.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-05 22:38:12 +01:00
David Pursehouse f350e889d6 Merge branch 'stable-5.6'
* stable-5.6:
  ReftableTest: Clean up boxing warnings on usage of String.format
  MergedReftable: Remove unnecessary semicolon

Change-Id: Id35406acfdd91c3ddf17ce4e1023395f774774f2
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
2019-12-05 10:46:44 +09:00
David Pursehouse b24ec8f715 ReftableTest: Clean up boxing warnings on usage of String.format
Passing int as an argument to String.format causes a warning:

  The expression of type int is boxed into Integer

Most of these are already suppressed, but there are a couple that are
not. Add suppressions for those.

For the existing ones, move the suppression scope from the method to
the actual usage. Where necessary extract the usage out to a local
variable.

Change-Id: I7a7ff6dec49467e4b5c58d27a231c74e6e1c5437
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
2019-12-05 09:54:14 +09:00
Matthias Sohn f487a9eb2e Prepare 5.7.0-SNAPSHOT builds
Change-Id: I7efa0cd08dee711d6fefc3e6bb478a3cb11fe85c
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-05 01:32:59 +01:00
Matthias Sohn 08d4c63b6d Merge branch 'stable-5.6'
* stable-5.6:
  Introduce RefDatabase#hasFastTipsWithSha1
  Update Orbit to R20191126223242 for 2019-12
  Prepare 5.6.0-SNAPSHOT builds
  JGit v5.6.0.201912041214-rc1
  Prepare 5.6.0-SNAPSHOT builds
  JGit v5.6.0.201911271000-m3

Change-Id: Id33b054131bbcd27a0ae7200f564775049698d2c
2019-12-05 01:31:32 +01:00
Han-Wen Nienhuys 5185d288c1 Introduce RefDatabase#hasFastTipsWithSha1
The reftable format supports fast inverse (SHA1 => ref) queries.

If the ref database does not support fast inverse queries, it may be
advantageous to build a complete SHA1 to ref map in advance for
multiple uses. To let applications decide, this function indicates
whether the inverse map is available.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Change-Id: Idaf7e01075906972ec21332cade285289619c2b3
2019-12-04 23:35:32 +01:00
Matthias Sohn 473527e42c Prepare 5.6.0-SNAPSHOT builds
Change-Id: I5e737ff7f262fdd43fc975a0b3594c8b33919663
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-04 22:13:56 +01:00
Matthias Sohn a7e454bc51 JGit v5.6.0.201912041214-rc1
Change-Id: I5ed21fbc5f83096bf0b79f2aa751db415cbcc7e8
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-12-04 18:14:43 +01:00
Masaya Suzuki 6bc3665764 transport: Move handling code to the caller side
This removes a raw IOException at one level. Later we'll add a custom
exception handling mechanism like UploadPack.

Change-Id: I52a7423798c97b032d848351be8b6f144776b017
Signed-off-by: Masaya Suzuki <masayasuzuki@google.com>
2019-12-02 12:25:03 -08:00
Matthias Sohn 4ea42bc816 Prepare 5.6.0-SNAPSHOT builds
Change-Id: I1e52d2dfb202b87ecb9d0273deaa2c8d8ce1864e
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-27 21:25:38 +01:00
Matthias Sohn 6c9aa82f70 JGit v5.6.0.201911271000-m3
Change-Id: I3810892c2bed947e4dfaa615a7b4d93eeb46abb9
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-27 16:01:20 +01:00
Thomas Wolf 59f9d206c9 Make blame work correctly on merge conflicts
When a conflicting file was blamed, JGit would not identify lines
coming from the merge parents. The main cause for this was that
Blame and BlameCommand simply added the first DirCacheEntry found
for a file to its queue of candidates (blobs or commits) to consider.
In case of a conflict this typically is the merge base commit, and
comparing a auto-merged contents against that base would yield
incorrect results.

Such cases have to be handled specially. The candidate to be
considered by the blame must use the working tree contents, but
at the same time behave like a merge commit/candidate with HEAD
and the MERGE_HEADs as parents. Canonical git does something very
similar, see [1].

Implement that and add tests.

I first did this for the JGit pgm Blame command. When I then tried
to do the same in BlameCommand, I noticed that the latter also
included some fancy but incomplete CR-LF handling. In order to
be able to use the new BlameGenerator.prepareHead() also in
BlameCommand this CR-LF handling was also moved into BlameGenerator
and corrected in doing so.

(Just considering the git config settings was not good enough,
CR-LF behavior can also be influenced by .gitattributes, and even
by whether the file in the index has CR-LF. To correctly determine
CR-LF handling for check-in one needs to do a TreeWalk with at
least a FileTreeIterator and a DirCacheIterator.)

[1] https://github.com/git/git/blob/v2.22.0/blame.c#L174

Bug: 434330
Change-Id: I9d763dd6ba478b0b6ebf9456049d6301f478ef7c
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-11-27 03:03:06 +01:00
Jonathan Nieder aab5ee18fe Merge changes I8698001d,I5c1177ac
* changes:
  Add missing license header to ReftableDatabase
  Add missing license header to UploadPackRefSortingForReachabilityTest
2019-11-25 20:56:23 -05:00
Jonathan Nieder 3e01123a53 Add missing license header to UploadPackRefSortingForReachabilityTest
Forgot to add this in commit 989a927a5f
(checkNotAdvertisedWants: Be lazy convering Ref to RevCommit,
2019-11-20).

Change-Id: I5c1177ac60eabb3a71959bbad4537e076a901b7e
Signed-off-by: Jonathan Nieder <jrn@google.com>
2019-11-25 17:37:40 -08:00
Matthias Sohn 3d4c95293c [spotbugs] Fix potential NPE in FSTest
Change-Id: I6ca37d045642e3aada7e6b42b3cb8c3bba014455
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-26 01:57:20 +01:00
Han-Wen Nienhuys 9cb8e2f310 RepositoryCache: don't require HEAD in git repositories
Reftable-enabled repositories don't have a file called HEAD. Check for
reftable/ instead.

This fixes repository creation on reftable in Gerrit.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Change-Id: I778c2be01d96aaf135affae4b457b5fe5b483bee
2019-11-26 01:57:19 +01:00
Han-Wen Nienhuys e0744891fe FileRepository: cleanup refs outside refs/ on reftable conversion
Change-Id: Iab7d3a08906e826e26572f534512a09d3a5876b0
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-26 01:57:19 +01:00
David Pursehouse f2ccc42132 UploadPackTest: Fix unused parameter in checkUnadvertisedIfUnallowed
Change-Id: I6042c401fff55325128d47e7e9098fc7e60d501d
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
2019-11-25 09:31:49 +09:00
Ivan Frade f5f5c80bf5 BitmappedReachabilityChecker: Use only one bitmap for the whole check
The checker is creating a new bitmap per branch leading to excessive
memory consumption. For the reachability check one bitmap with the
reachability of all branches aggregated is enough.

Build the reachability bitmap with a filter. The filter itself uses it
to emit only commits not reached before and the caller to check what
targets have been reached already.

BitmapCalculator is not required anymore.

Change-Id: Ic5c62f77fe0f188913215b7eaa51d849a9aae6a5
Signed-off-by: Ivan Frade <ifrade@google.com>
2019-11-21 14:07:04 -08:00
Ivan Frade 989a927a5f checkNotAdvertisedWants: Be lazy converting Ref to RevCommit
The ref points to an ObjectId that then is translated into a RevCommit.
This translation can be costly and with the incremental reachability
check is probably not needed for most of the elements.

Delay the translation from ObjectId to RevCommit to when it is needed.
Use Streams, that have the laziness built-in, all the way from Ref to
RevCommit.

This should reduce the latency for reachability checks over big sets of
references.

Change-Id: I28693087321b2beff3eaa1f3d2e7840ab0eedc6d
Signed-off-by: Ivan Frade <ifrade@google.com>
2019-11-21 09:30:19 -08:00
Ivan Frade a0204a4727 ReachabilityChecker: Receive a Stream instead of a Collection
Preparatory change. Converting ObjectIds to RevCommits is potentially
expensive and in the incremental reachability check, it is probably not
required for all elements in the collection.

Pass a Stream to the reachability checker. In the follow up we make
the conversion from ObjectId to RevCommit in the stream (i.e. on
demand). This should reduce the latency of reachability checks over big
sets of references.

Change-Id: I9f310e331de5b0bf8de34143bd7dcd34316d2fba
Signed-off-by: Ivan Frade <ifrade@google.com>
2019-11-21 09:30:19 -08:00
Han-Wen Nienhuys 38586d54d0 file: implement FileReftableDatabase
Reftable is a binary, block-based storage format for the ref-database.
It provides several advantages over the traditional packed + loose
storage format:

 * O(1) write performance, even for deletions and transactions.

 * atomic updates to the ref database.

 * O(log N) lookup and prefix scans

 * free from restrictions imposed by the file system: it is
   case-sensitive even on case-insensitive file systems, and has
   no inherent limitations for directory/file conflicts

 * prefix compression reduces space usage for repetitive ref names,
   such as gerrit's refs/changes/xx/xxxxx format.

FileReftableDatabase is based on FileReftableStack, which does
compactions inline. This is simple, and has good median performance,
but every so often it will rewrite the entire ref database.

For testing, a FileReftableTest (mirroring RefUpdateTest) is added to
check for Reftable specific behavior. This must be done separately, as
reflogs have different semantics.

Add a reftable flavor of BatchRefUpdateTest.

Add a FileReftableStackTest to exercise compaction.

Add FileRepository#convertToReftable so existing testdata can be
reused.

CQ: 21007
Change-Id: I1837f268e91c6b446cb0155061727dbaccb714b8
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-16 23:16:01 -08:00
Thomas Wolf 1daf6f13aa RewriteGenerator: avoid adding null parent
Prevent adding a null parent to a commit's parent array. Doing so
can cause NPEs later on.

Bug: 552160
Change-Id: Ib24b7b9b7b08e0b6f246006b4a4cade7eeb830b9
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-11-15 16:00:48 -08:00
Thomas Wolf 345e2648df DiffFormatter: support core.quotePath = false
core.quotePath = false means that "bytes higher than 0x80 are not
considered "unusal" anymore"[1], i.e., they are not escaped. In
essence this preserves non-ASCII characters in path names in output.

Note that control characters and other special characters in the
ASCII range will still be escaped.

Add a new QuotedString.GIT_PATH_MINIMAL singleton implementing this.
Change the normal GIT_PATH algorithm to use bytes instead of characters
so it can be re-used. Provide a setter in DiffFormatter for the quoting
style so that an application can override the default, which is the
setting from the git config (and by default "true"). Use the new
QuotedString.GIT_PATH_MINIMAL when core.quotePath == false.

[1] https://git-scm.com/docs/git-config#Documentation/git-config.txt-corequotePath

Bug: 552467
Change-Id: Ifcb233e7d10676333bf42011e32d01a4e1138059
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-11-15 15:12:23 -08:00
Thomas Wolf 7a3b93cbed IndexDiff/SubmoduleWalk: handle submodule.<name>.ignore correctly
IndexDiff would apply ignore mode ALL from .gitmodules to all remaining
submodules, and would ignore other settings from .gitignore and always
apply the setting defined on the IndexDiff instead. Correct that.

In canonical git the ignore setting from .gitmodules can also be
overridden by .git/config.[1] Implement that override in SubmoduleWalk.

[1] https://git-scm.com/docs/gitmodules#Documentation/gitmodules.txt-submoduleltnamegtignore

Bug: 521613
Change-Id: I9199fd447e41c7838924856dce40678370b66395
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-11-15 14:48:44 -08:00
Jonathan Nieder 83b9b84e4a Merge changes I583491f6,Idd44e3bb
* changes:
  Run Eclipse formatter on BatchRefUpdateTest
  Move KetchSystem.delay to FileUtils.
2019-11-14 18:21:04 -05:00
Han-Wen Nienhuys 63fba337b2 Run Eclipse formatter on BatchRefUpdateTest
Change-Id: I583491f621e54401c60150efb285fcc7243a9355
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
2019-11-14 13:48:28 -08:00
Masaya Suzuki 3e9a5f993b transport: Merge BaseReceivePack into ReceivePack
Move the BaseReceivePack implementation back into ReceivePack. This is a
backward-incompatible change. For example, BaseReceivePack.FirstLine no
longer exists and cannot be referenced.  However, most of the code
should just work by replacing BaseReceivePack with ReceivePack.

Although this is an API change, it only affects callers using JGit as a
server, and there are very few of those in the wild.

Change-Id: I1ce92869435d5eebb7d671be44561e69c6233134
Signed-off-by: Masaya Suzuki <masayasuzuki@google.com>
2019-11-13 15:57:04 -08:00
Matthias Sohn 826317942f Merge branch 'stable-5.5'
* stable-5.5:
  BaseReceivePack: Fix the format
  Prepend hostname to subsection used to store file timestamp resolution
  Store filesystem timestamp resolution in extra jgit config
  SystemReader: extract updating config and its parents if outdated

Change-Id: Iecfddce8081303af29badcdcd3d72a0da50c964f
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-11 11:07:17 -08:00
Matthias Sohn 838b5a84b5 Store filesystem timestamp resolution in extra jgit config
This avoids polluting hand-crafted user level config with
auto-configured options which might disturb in environments where
the user level config is replicated between different machines.

Add a jgit config as parent of the system level config. Persist
measured timestamp resolutions always in this jgit config and read it
via the user global config. This has the effect that auto-configured
timestamp resolution will be used by default and can be overridden in
either the system level or user level config.

Store the jgit config under the XDG_CONFIG_HOME directory following the
XDG base directory specification [1] in order to ensure that we have
write permissions to persist the file. This has the effect that each OS
user will use its jgit config since they typically use different
XDG_CONFIG_HOME directories.

If the environment variable XDG_CONFIG_HOME is defined the jgit config
file is located at $XDG_CONFIG_HOME/jgit/config otherwise the default is
~/.config/jgit/config.

If you want to avoid redundant measurement for different OS users
manually copy the values measured and auto-configured for one OS user to
the system level git config.

[1] https://wiki.archlinux.org/index.php/XDG_Base_Directory

Bug: 551850
Change-Id: I0022bd40ae62f82e5b964c2ea25822eb55d94687
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-11-09 18:01:19 +01:00
Thomas Wolf 64f2407f19 WorkingTreeModifiedEvent: must be fired explicitly after merge
A merge may write files to the working tree. After a successful
merge one must fire a WorkingTreeModifiedEvent explicitly if
getModifiedFiles() is not empty.

Also, any touched files must be reported by the
WorkingTreeModifiedEvent fired by DirCacheCheckout.checkout().

Bug: 552636
Change-Id: I5fab8279ed8be8a4ae34cddfa726836b9277aea6
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-11-03 10:10:16 +01:00
David Pursehouse b29e9bd1cb Merge "HttpSupport.proxyFor(): use only scheme, host, and port" 2019-10-30 19:20:30 -04:00
Han-Wen Nienhuys 7c75a68b96 reftable: enforce ascending order in sortAndWriteRefs
MergedReftableTest#scanDuplicates tests whether we can write duplicate
keys in a merged reftable. Apparently, the first key appearing should
get precedence, and this works because the sort() algorithm on ordered
collections is stable.

This is potentially confusing behavior, because you can write data
into the table that cannot be retrieved (Merged table can only have
one entry per key), and the APIs such as exactRef() only return a
single value.

Make this consistent with behavior introduced in I04f55c481 "reftable:
enforce ordering for ref and log writes" by considering a duplicate key
in sortAndWriteRefs as a fatal runtime error.

Change-Id: I1eedd18f028180069f78c5c467169dcfe1521157
Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
2019-10-30 18:00:24 +01:00
Thomas Wolf b7d1eb4185 HttpSupport.proxyFor(): use only scheme, host, and port
Some URLs cannot be converted via URL.toURI(). So don't convert
the full URL but only the bits that are needed to find a proxy
via java.net.ProxySelector.

Bug: 549690
Change-Id: I55b5ecee70c6b52f72f9bdba9ce552fde7f33976
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-30 15:16:51 +01:00
Thomas Wolf 6a39da37fe GPG: implement more OpenPGP UserId matching formats
Instead of just looking for a substring match of user.signingKey
in a key's user ID implement the GPG matching formats[1] for:

'=' Full exact match
'<' Full exact match of the e-mail address
'@' Substring match within the e-mail address only
'*' General case-insensitive substring match (default)

When user.signingKey is not set, the committer's e-mail address is
used by default. In that case, use '<', i.e., require an exact match
on the OpenPGP e-mail address.

Also handle the optional "0x" prefix for (partial) key fingerprints.

[1] https://www.gnupg.org/documentation/manuals/gnupg/Specify-a-User-ID.html

Bug: 550335
Change-Id: I6ce482a099ff1a0dc9de45435cd4d3ec5b504f12
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-23 11:17:24 +02:00
Jonathan Tan 0bf165b7b6 Merge "TreeRevFilterTest: Simplify filter used" 2019-10-22 13:36:46 -04:00
Jonathan Tan 91979f93fa TreeRevFilterTest: Simplify filter used
TreeRevFilterTest uses an unncessarily complicated TreeFilter - an
AndTreeFilter - when it should be as simple as possible because this
class tests TreeRevFilter, not AndTreeFilter. Replace the filter with a
simpler one.

Change-Id: I3256a65f6e0042d32fd76a9224b79a835674ff3a
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
2019-10-22 10:13:54 -07:00
Thomas Wolf 385b503ae8 Support for core.hooksPath
Support the core.hooksPath git config. This can be an absolute or
relative path of a directory where to find git hooks; a relative
path is resolved relative to the directory the hook will run in.

Bug: 500266
Change-Id: I671999a6386a837e897c31718583c91d8035f3ba
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-21 18:05:31 -04:00
Thomas Wolf c020848dbb Close ObjectReaders in tests
Change-Id: Ic839af4f85861fb48091d45679e2a614f001d770
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-21 11:39:46 +02:00
Thomas Wolf 123634e2aa Close some Repository instances in tests
This doesn't yet ensure that _all_ repositories are closed. It only
handles the obvious, local, and easy cases.

Change-Id: I0f9f8607791f0f03ed1f5ad71e9595e78b78892f
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-21 11:39:46 +02:00
Thomas Wolf 1b8da0dcfa Close ObjectInserters in tests
Change-Id: I0048a9ae23aee79cfecafb15855c63cd92818c57
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-21 11:39:46 +02:00
Matthias Sohn bceac7bd03 Remove meaningless comment in CloneCommandTest
This comment was probably copied from testCloneRepositoryWithBranch() to
testBareCloneRepositoryOnlyOneBranch() where it doesn't make sense.
Hence remove it.

Change-Id: I846debd084dd77fd473c3602a799f195a8390f77
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-10-21 09:29:50 +02:00
Matthias Sohn 6216b0de8a Implement mirror option in CloneCommand
Bug: 552173
Change-Id: If79adf578b303890314a3285d7a6d2c71f48d091
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
2019-10-21 09:27:13 +02:00
David Pursehouse 98cdca9b5a Enable and fix "Statement unnecessarily nested within else clause" warnings
Since [1] the gerrit project includes jgit as a submodule, and has this
warning enabled, resulting in 100s of warnings in the console.

Also enable the warning here, and fix them.

At the same time, add missing braces around adjacent and nearby one-line
blocks.

[1] https://gerrit-review.googlesource.com/c/gerrit/+/227897

Change-Id: I81df3fc7ed6eedf6874ce1a3bedfa727a1897e4c
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
2019-10-17 10:20:14 +09:00
Thomas Wolf 762f6212b4 Close RevWalks in tests
Change-Id: Id28804ace2572e8f659271660e78454a0d6ccc49
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
2019-10-16 18:45:34 -04:00
Jonathan Tan 3b96aeb2c9 Merge "reftable: fix lookup by ID in merged reftables" 2019-10-16 13:33:20 -04:00
Han-Wen Nienhuys 218bacdc1f reftable: fix lookup by ID in merged reftables
On changing a ref, the old SHA1 is not updated in the object => ref
mapping. This means search by object ID may still turn up a ref from
deeper within the stack. To fix this, check all refs produced by the
merged iterator against the merged reftables.

Signed-off-by: Han-Wen Nienhuys <hanwen@google.com>
Change-Id: I41e9cd395b0608eedeeaead0a9fd997238d747c9
2019-10-16 15:15:55 +02:00