Commit Graph

44674 Commits

Author SHA1 Message Date
Anastasiya Zhyrkevich
baad48586f lfs debug command to receive a bunch of objects
Summary:
debugcommand for receiving several lfs objects from server
Analog to the funtion `debuglfsreceive`, but for several objects

Will be used in replay traffic for Mononoke LFS.

Requires URL and an iterable with oids and sizes.
Format required:
url, (oid1, size1, oid2, size2, ... )

Write all files to the console.

Reviewed By: quark-zju

Differential Revision: D12956274

fbshipit-source-id: f83dd0636b2ad197cace9633222d0f1ed8191dab
2018-11-13 03:11:18 -08:00
Phil Cohen
4b9fdcd042 stablerev: add getstablerev() revset
Summary:
This allows us to expose `arc pull`'s functionality directly from hg.

There are three parts:

- Create a revset that runs a program, reads the stdout and looks up that commit if it exists
- Auto-pulling if the commit doesn't exist
- Supporting an optional argument (target) that's passed to the script

Reviewed By: DurhamG

Differential Revision: D10524541

fbshipit-source-id: 7493c5592e272f9e8a87f109cec1426d44935ecc
2018-11-12 13:38:49 -08:00
Pavel Aslanov
41c2048ce6 record updated onto rev
Summary:
We need to record updated onto rev instead of guessing it in pushrebase replayer.

I will not land this diff until mononoke db schema is update D12923144, D12997125

Reviewed By: quark-zju

Differential Revision: D12922833

fbshipit-source-id: 11c6411c392ca9092be53ffba8baa074faf3a996
2018-11-12 04:17:37 -08:00
Durham Goode
b6a2776924 remotefilelog: make pending local pack writes available for reads
Summary:
Previously, if we were writing local data to pack files we weren't able
to read that data until the pack file had been flushed. Let's add those mutable
packs to the union store so we can see there data.

This is important for unblocking use of hggit and hgsubversion since they may
import many dependent commits in a single transaction.

Reviewed By: quark-zju

Differential Revision: D12959497

fbshipit-source-id: 405c0c5c1e8fc84bc8ffef827a84e91d57eb95d8
2018-11-11 21:37:52 -08:00
Durham Goode
f1d6212c00 remotefilelog: add test showing issue with packlocaldata
Summary:
The config to write local packs has an issue with reading data from
currently pending mutable packs. Let's add a test demonstrating this, and in the
next diff we'll fix it.

Reviewed By: quark-zju

Differential Revision: D12959501

fbshipit-source-id: 5bcb278ccb977cea83e8cd594a404816d4f8f1fa
2018-11-11 21:37:52 -08:00
Durham Goode
729133f6cf remotefilelog: move mutable packs onto fileslog
Summary:
Previously these were stored on the remotefilelogcontentstore, which is
a weird place since it's generally responsible for loose files. Now that we have
the fileslog abstraction let's move the mutable packs on to it.

This mirrors the manifestlog pattern.

Reviewed By: quark-zju

Differential Revision: D12959496

fbshipit-source-id: 25649570a44b50e9baa558b85ba00605883fd403
2018-11-11 21:37:52 -08:00
Durham Goode
ee9beb6c2f remotefilelog: move mutablemanifeststore into shallowutil
Summary:
A future diff will use the same mutable*store pattern to allow pending
file mutable packs to be read from the store. The mutablemanifeststore is
generic and can be reused, so let's move it and rename it.

Reviewed By: quark-zju

Differential Revision: D12959493

fbshipit-source-id: 82710b4d157eb3194440ea630dd458b382896a39
2018-11-11 21:37:52 -08:00
Durham Goode
e9e9022cfe remotefilelog: move file stores onto fileslog
Summary:
Now that all the file store creation logic is inside the fileslog
abstraction, let's also move the storage of all the stores onto this instance,
instead of having them hanging off the repo object.

This matches the manifestlog pattern and gives us better control over the
lifetime of all the filelog stores.

Reviewed By: quark-zju

Differential Revision: D12959500

fbshipit-source-id: f07f8b52bb83a7837e6dc02664bec6111df7a421
2018-11-11 21:37:52 -08:00
Durham Goode
e8a53816b1 remotefilelog: move creation of file stores into fileslog
Summary:
As part of unifying file storage into fileslog, let's move the store
creation logic into fileslog. It still puts the stores on the repo directly, but
a future diff will come back and fix that so the stores are kept on the fileslog
object.

Reviewed By: quark-zju

Differential Revision: D12959498

fbshipit-source-id: f3defc88b34c74c95bf1604f194b1b5883bad24d
2018-11-11 21:37:52 -08:00
Durham Goode
60c80f4f48 remotefilelog: move remotefilelog specific fileslog logic to remotefilelog
Summary:
We had remotefilelog specific logic in core mercurial code. Now that
we have the fileslog abstraction we can hide remotefilelog specific invalidation
in a remotefilelog specific fileslog implementation.

Reviewed By: quark-zju

Differential Revision: D12959495

fbshipit-source-id: ccf224bf9799eb1af74f0dff6021fcbc2eb20d68
2018-11-11 21:37:52 -08:00
Durham Goode
55010e4e41 remotefilelog: introduce the concepts of a fileslog
Summary:
In upcoming diffs I want to introduce lifetime management for
structures receiving writes for file content. We need to be able commit these at
the end of a transaction, and roll them back in the event of an abort.

We already have this, but it's adhoc and inconsistent. Let's introduce the
concept of a fileslog on the repository that is responsible for all filelog read
writes. At the moment it doesn't manage reads, and only governs remotefilelog
writes, but we can extend this later.

This pattern of a top level repo.*log property that manages the reading/writing
of a type of object is already used in the manifestlog and has proven to be
relatively clean.

Reviewed By: quark-zju

Differential Revision: D12959494

fbshipit-source-id: 676aa86c313cb7e48512091a9c19b9452e8f114a
2018-11-11 21:37:52 -08:00
Durham Goode
23f7e93958 remotefilelog: remove writestore concept from union stores
Summary:
Previously, remotefilelog tried to hide which store should receive
writes behind the union store abstraction. This is starting to make things a
little complicated though. For instance, it means that right now both local data
and local history are written via one api on the remotefilelogcontentstore, even
though the remotefilelogcontentstore should only be about data. It also means
that remotefilelogcontentstore had to become aware of pack files, which it can't
read, so it no longer upholds the guarantee that anything written to it can be
immediately read. Overall it's just confusing.

This diff rips out the writestore concept, and instead has the store setup logic
store the writable stores directly on the repo, and changes the write path to
write to those stores directly. Thus removing the notion of pack files from
remotefilelogcontentstore.

A future diff will clean this up even further, and fix the bug where you can't
read data that was just written to a local pack.

Reviewed By: quark-zju

Differential Revision: D12959502

fbshipit-source-id: 85c39c0696febd0972a21f22f3640fd6954901c1
2018-11-11 21:37:52 -08:00
Jun Wu
647f7dfb8e indexedlog: fix misc benchmark
Summary:
The "misc" benchmark requires the base16 module to be public. It was made
private in a previous change. Let's make it public again so the benchmark can
run.

Reviewed By: singhsrb

Differential Revision: D13015031

fbshipit-source-id: 0dc1542803aae290de26651e367898eebfc95e83
2018-11-09 20:49:56 -08:00
Phil Cohen
1d0f1cd7bf hgsubversion: log conflicted paths on failed SVN push
Summary:
This will help us in identifying commonly conflicted files/artifacts.

Alas, I think SVN only includes one path in the error message. But better than nothing.

Reviewed By: quark-zju

Differential Revision: D13009975

fbshipit-source-id: 220bcaa679222718c58e42174f28fd0bbeb618d2
2018-11-09 16:56:35 -08:00
Jun Wu
ef5f621baa progress: drop config to specify condtype
Summary:
The Rust condition implemenation seems working okay. Therefore drop the support
to switch to buggy `threading.Condition`.

Reviewed By: phillco

Differential Revision: D12875128

fbshipit-source-id: 15f41bdc3fceeaa7de7d8cdbd76ee6d70951c107
2018-11-09 15:27:52 -08:00
Marla Azriel
4027f3a7e9 commands: update help text for smartlog, show, diff
Summary: Provides updated help text for hg smartlog, hg show, and hg diff

Reviewed By: markbt

Differential Revision: D12950765

fbshipit-source-id: d442079499abada1740760c8b6d0c27bf4a2b2d3
2018-11-09 13:14:20 -08:00
Liubov Dmitrieva
372c5594b4 Scm Daemon: support cat tokens via passing token type to the URL
Summary: This is the final step to make CAT authentification work

Reviewed By: markbt

Differential Revision: D12975214

fbshipit-source-id: e445ca502f8abaac914140f3f30476d50b3c2fbc
2018-11-09 11:48:50 -08:00
Liubov Dmitrieva
299ecd354a Scm Daemon: support CAT tokens
Summary:
To solve friction with OAuth tokens we will support CAT tokens as well in Scm Daemon.

Icebreaker support has been done in D12942971

CATs tokens can be generated on dev servers without user (via the tool based on TLS certs).

So we are going to use them in the next diff.

This will allow us to enable token-less cloud sync for everyone, scm daemon will use CATs.

Reviewed By: markbt

Differential Revision: D12962342

fbshipit-source-id: 173301387ee446622bf77b2d6bed6934b5ced2c3
2018-11-09 09:51:26 -08:00
Liubov Dmitrieva
8a024ed563 Scm Daemon: make scm daemon more robust with expiration of tokens
Summary:
Basically if Unauthorized it will try to access the token again and restart all the subscriptions
rather than trying to reconnect with the same token in infinite loop.

We know OAuth tokens have potential to be invalidated.

CAT token (that we are going to support as well) will always be valid for some time - like 1 day, so we need a smooth way to recover from  Unauthorized and issue a fresh token.

Reviewed By: markbt

Differential Revision: D12960843

fbshipit-source-id: 630c446c490b0724df38c61507ee555dc7ed7241
2018-11-09 09:51:26 -08:00
Aida Getoeva
1c7a7e8eb2 debugcrdump: add --nobinary flag to avoid dumping binaries
Summary: Jellyfish uses `hg debugcrdump` to get commit data, including binary files. Now we want in jf to be able avoid dumping binary files, so I added `--nobinary` option to crdump

Reviewed By: quark-zju

Differential Revision: D12981968

fbshipit-source-id: 669ef4cf8f6225b911f5085c1a47fb7242f259bf
2018-11-09 08:50:37 -08:00
Jun Wu
6a01a5de06 linelog: update README
Summary: This is a backport of my upstream patch https://phab.mercurial-scm.org/D4147

Differential Revision: D12970974

fbshipit-source-id: ed9d8db2e32818e6e5ab3f23f5a0097bfa2cc14e
2018-11-08 12:34:36 -08:00
Jun Wu
4a49dc876f crecord: fix line number in hunk header
Summary:
`@@ -1,1 +-1,0 @@` is not a valid patch hunk header.
Change it to `@@ -1,1 +0,0 @@`.

This is a backport of my upstream patch https://phab.mercurial-scm.org/D3737

Reviewed By: singhsrb

Differential Revision: D12970975

fbshipit-source-id: eb769e93076efc932a8c4be7387ba21933aae331
2018-11-08 12:34:36 -08:00
Saurabh Singh
b481467dd4 doc: fix 'make doc'
Summary: This has been broken after D12832280.

Reviewed By: quark-zju

Differential Revision: D12981581

fbshipit-source-id: 3f411260e24e623abb6f18814fa5b0bf87b416cd
2018-11-08 10:46:24 -08:00
Kostia Balytskyi
d2c2c250e0 windows: use correct rename exception raising logic
Summary:
The way I wrote this, `if e.errno != errno.EEXIST or e.errno != errno.EACCES`
this condition never succeeds. So we're re-raising always, rather than falling
back to a `delete/rename` strategy.

Differential Revision: D12974035

fbshipit-source-id: 0b500d009315ba0094019a82576d5a3698b624b2
2018-11-08 06:00:16 -08:00
Marla Azriel
96cb1050bc commands: update help summary text
Summary: Updated the global help summaries that are displayed for each command when you run 'hg help' and fixed corresponding tests

Reviewed By: markbt, kulshrax

Differential Revision: D12832280

fbshipit-source-id: 950dad1c805feab573d7d0182da523ae12299d3b
2018-11-07 19:59:47 -08:00
Jun Wu
4401ea1473 tests: add a test showing sparse issues
Summary: There are multiple issues here. Expose them.

Reviewed By: DurhamG

Differential Revision: D10861608

fbshipit-source-id: 5e55e4550574b0955eec92b70c700599eebccc6e
2018-11-07 16:36:41 -08:00
Kostia Balytskyi
825a9ddee5 windows: implement a more atomic rename/replace
Summary:
Our `rename` is not atomic:
```
def rename(src, dst):
    """Rename file src to dst, replacing dst if it exists"""
    try:
        os.rename(src, dst)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise
        unlink(dst)
        # What if the process is interrupted here?
        os.rename(src, dst)
```

However, the `MoveFileEx` Windows API provides a way to to
replace the existing file, thus eliminating the need to do `unlink`.

Unfortunately, it only works for files, not for dirs, therefore
we're introducing a new file-specific rename function.

Differential Revision: D12940555

fbshipit-source-id: a6749a9b16a285788de0f5c06d51a15c919166ce
2018-11-07 10:37:23 -08:00
Mark Thomas
b7fe1b52f8 pushrebase: pluralize strings correctly
Summary: Pluralize strings using `mercurial.i18n._n`

Reviewed By: quark-zju

Differential Revision: D12944849

fbshipit-source-id: 536f2edf37fe5603cbf3c7737afb3445988b41f6
2018-11-07 04:32:46 -08:00
Mark Thomas
088e0a8ed6 pushrebase: only prevent phase updates if replacements received
Summary:
If the commits being pushrebased don't actually need to be rebased, pushrebase
will accept them like a normal push.  In this case we shouldn't prevent them
from be changed to public commits on the client.

Track this by detecting whether we receive a changegroup part from the server.
If we do, only the commits that are marked as replaced with obsmarkers (if
enabled) can be marked as public.

Reviewed By: quark-zju

Differential Revision: D12944851

fbshipit-source-id: 44f8fc17b36397d949cba5d3e787fad813bab4ea
2018-11-07 04:32:46 -08:00
Mark Thomas
9b4c89abe5 pushrebase: add test demonstrating pushrebase phase change failure
Summary:
When pushrebase is enabled, pushing a commit that doesn't result in any
rebasing action acts like a normal push (the commit is not modifed and a new
hash is not returned), however the phase update doesn't apply, so the commit
remains draft.

Reviewed By: quark-zju

Differential Revision: D12944850

fbshipit-source-id: 2145d9b7eebc27bfdff34544e73802c13f30dbd2
2018-11-07 04:32:46 -08:00
Jun Wu
f37a5d8df7 rust: upgrade rust to 1.30.0 and bump zstd-sys version
Summary:
The vendored crates were changed by D12811597. Bump `zstd-sys` in `Cargo.toml` to be compatible.
As we're here, also bump rust compiler to 1.30.0 so it's consistent with buck build.

Reviewed By: kulshrax

Differential Revision: D12952552

fbshipit-source-id: 6274bf829b98b16aeb6795209d12aba8b475b46d
2018-11-06 18:13:20 -08:00
Saurabh Singh
b496efcc9a test-hgsubversion-globalrevs: test revset interoperability
Summary:
D12888964 added the capability for `svnrev` revsets to be
interoperable with the `globalrev` revsets. This commit adds the tests for it.

Reviewed By: quark-zju

Differential Revision: D12888960

fbshipit-source-id: 07b12632d534a329c32179e978b058b1e427e688
2018-11-06 16:42:11 -08:00
Saurabh Singh
ff98fdcc08 test-hgsubversion-globalrevs: remove the capturing ui
Summary:
The capturing UI is not required as we can use the much cleaner
`ui.pushbuffer`/`ui.popbuffer` for the intended purpose.

Reviewed By: quark-zju

Differential Revision: D12906912

fbshipit-source-id: ae93e6417135ca23b28a11af63745464344fa3cf
2018-11-06 16:42:11 -08:00
Saurabh Singh
32b539a13a test-hgsubversion-globalrevs: add useful params to the assert log method
Summary:
This method always prints the graph for the commits in the repository.
This commit adds supports for specifying any revset as input for the log and
also, makes printing the graph optional.

Reviewed By: quark-zju

Differential Revision: D12888965

fbshipit-source-id: 794606fa17f9836fd73675d36d11220b11994f41
2018-11-06 16:42:11 -08:00
Saurabh Singh
e9ebb554f3 test-hgsubversion-globalrevs: include svnrev in tests instead of rev
Summary: The `svnrev` is more useful than the `rev` in this context.

Reviewed By: quark-zju

Differential Revision: D12888963

fbshipit-source-id: a902c57ecc3bc3eca9da77ab6e14ef58512d5ad8
2018-11-06 16:42:11 -08:00
Saurabh Singh
6f25c6e5c9 hgsubversion: support resolving revset string with prefix 'r' during tests
Summary:
This is required for testing `globalrevs` integration with
`hgsubversion`. In particular, we will test out whether we can resolve
`r<svnrev>/r<globalrev>` correctly later. Seems like this configuration should
be on during all the tests because it is the configuration we use in
production. Therefore, this commit in resolves revset string with prefix `r`
for all the `hgsubversion` tests.

Reviewed By: quark-zju

Differential Revision: D12888961

fbshipit-source-id: af9b2e1aea9771f42fe1fb2d3f9a759a926b1ce3
2018-11-06 16:42:11 -08:00
Saurabh Singh
51f556080f globalrevs: add support for interoperability with 'svnrev' revsets
Summary:
This commit adds support for the `globalrev` and `svnrev` based
revsets to be interoperable. In particular, we want the commands

```
   hg log -r "svnrev(<svnrev>/<globalrev>)"
   hg log -r "globalrev(<svnrev>/<globalrev>)"
   hg log -r "r<svnrev>/r<globalrev>"
   hg log -r "m<svnrev>/m<globalrev>"
```

to resolve to a commit with <svnrev> as the corresponding svn revision number
and <globalrev> as the corresponding strictly increasing global revision
number.

Reviewed By: quark-zju

Differential Revision: D12888964

fbshipit-source-id: 1c4e6e2cf3febb5a1d8a476554ad62cc630dc96e
2018-11-06 16:42:10 -08:00
Saurabh Singh
f9f787762f globalrevs: make the extension wrapping logic more clear
Summary:
After some cleanup and improvements by quark-zju, we only wrap the
`hgsql` extension for embedding `globalrev` in a commit. Therefore, lets remove
the unnecessary verbosity in the code and make it more clear.

Reviewed By: quark-zju

Differential Revision: D12888962

fbshipit-source-id: b1fcebd6ce6c9cdf1c5cb7bb8b3532695f20d32c
2018-11-06 16:42:10 -08:00
Saurabh Singh
0d204fba6f globalrevs: introduce configuration for specifying valid starting revision
Summary:
We need a configuration option for specifying the starting revision
beyond which we will consider the global revisions associated with the commit
valid for the following reasons:

 - It lets us have the flexibility to support `globalrevs` from a commit of our
   choice.
 - We need this configuration to decide when we should fallback to looking at
   the `svnrev` instead of the `globalrev`.

Reviewed By: quark-zju

Differential Revision: D12888966

fbshipit-source-id: 46d6314886ed5074edb537ba340d5606ec354619
2018-11-06 16:42:10 -08:00
Jeremy Fitzhardinge
911e07172e tp2/rust: update to rust-1.30.0
Summary:
rustc-1.30.0 tries to work out what the linker actually is from the name, and
gets confused because the script we pass it is actually gcc (or clang), but has
`ld` in the name. Update the command-line options to also pass
`-Zlinker-flavor=gcc` to override the linker flavor inference.

proc_macros are now stable. The `quote` crate has a dependency on the `proc_macro`
which is now a shared object as part of the rustc distribution, which means that things
using `quote` must have a runtime linkage with the rustc libraries. The Thrift `codegen`
binary is the main thing affected by this, and I've hacked around it by putting an
`LD_LIBRARY_PATH` in the Buck macros. Need to find a nicer fix though.

rustc 1.30 now implements `#[macro_export(local_inner_macros)]`, which has
strict semantics around namespaces and symbol hygiene, which doesn't work with
common/rust/sql's macros. Work around this for now by just exporting
everything.

Reviewed By: kulshrax

Differential Revision: D12811597

fbshipit-source-id: f18d12e6d99994876c29d3a6bd6ae43f1f37dd17
2018-11-06 16:16:09 -08:00
Jun Wu
a411ecb012 hgmain: remove default features
Summary:
The default feature requires additional environment setup. Since environment
setup cannot be avoided, let's rely on the "environment setup" logic to specify
"with_chg" feature correctly. So "cargo build" without specifying features can
work.

This might fix the Windows CI build.

Reviewed By: DurhamG

Differential Revision: D12948723

fbshipit-source-id: cf2609bccace69cd22a9e4ef4fd2c1fc1bf73338
2018-11-06 15:40:25 -08:00
Jun Wu
2c58a7b39f setup: fix libchg cflags
Summary: chg needs `_GNU_SOURCE` to build correctly.

Reviewed By: DurhamG

Differential Revision: D12947813

fbshipit-source-id: 26e3a7f506f959d016abba3e7a773d9f5940f19b
2018-11-06 14:36:47 -08:00
Durham Goode
718d19fce6 datapack: fix not including rename information in datapack blobs
Summary:
It turns out data packs contain the exact mercurial file blob,
including the rename metadata header. This is different from how loose files work, which
contain the non-headered text and instead store the rename in the history at the
end of the file.

Ideally we'd change datapacks to not store the metadata version of the file, but
unfortunately this is how it has always been, so instead we must change the
commit-straight-to-pack code to write the headered blob.

Differential Revision: D12936247

fbshipit-source-id: 3f909d2964d7f7200ac0e31e47bd195b0c9b03e5
2018-11-06 14:06:55 -08:00
Mark Thomas
529aa8872e absorb: use ngettext for message plurals
Summary: Pluralize messages using ngettext.

Reviewed By: quark-zju

Differential Revision: D12921683

fbshipit-source-id: a8dce90b3b9318597f888a8aca72351012de05ae
2018-11-06 03:19:01 -08:00
Mark Thomas
6f7fabcecf i18n: support ngettext for pluralized strings
Summary:
Support pluralized translation strings using ngettext.

This allows strings that are appropriately pluralized based on the count of the
item.  To use import `_n` from the `i18n` module and provide it with singular
and plural messages, along with the count of the item that should be pluralized:

```
from mercurial.i18n import _n

ui.write(_n("%d item processed", "%d items processed", count) % count)
```

When using `%`-based string formatting in Python, both variants of the format
string must have the same number of subsitutions: it's not possible to leave
out the `%d` in the singular case.

Reviewed By: quark-zju

Differential Revision: D12921684

fbshipit-source-id: 756d1350a827d0451a07279f6884ee57dba6ac9f
2018-11-06 03:19:01 -08:00
Mark Thomas
fcafaf9750 discovery: don't exclude extinct commits
Summary:
Discovery excludes extinct (obsoleted without any non-obsolete descendants)
commits from the candidates that can be exchanged.  This is unnecessary, and
the user may legitimately want to exchange an extinct commit.

Reviewed By: quark-zju

Differential Revision: D12924522

fbshipit-source-id: 1ea53f2c7bdfd7b4d97c6fbae43ebdcbaf322614
2018-11-06 03:14:58 -08:00
Kostia Balytskyi
9a14c01dfd hg.rust: add osx python installation path
Reviewed By: markbt

Differential Revision: D12922593

fbshipit-source-id: c74fc5b0227fb488b5e8d4690063220f9245e775
2018-11-05 11:54:44 -08:00
Kostia Balytskyi
475f7f8d90 hg.rust: add support for passing control to chg
Summary:
This is needed before we start moving builtins into `hg.rust`. The decision
to run or not run a builtin needs to be made before the decision to run or not
run a `chg`.

Reviewed By: quark-zju

Differential Revision: D10859033

fbshipit-source-id: 04018904684fc3c8ca2b927bfb828e40a8d09938
2018-11-05 10:08:29 -08:00
Kostia Balytskyi
c5aa7a01b3 chg: learn to build a static lib
Summary:
In order to be able to run `chg` from the main `hg.rust` binary, we decided
that we will turn it into a static lib. This diff teaches our current build
scripts to do this.

Reviewed By: quark-zju

Differential Revision: D10853906

fbshipit-source-id: 8e0f37aa7e52d4a0610f36d7903eb0a318c193ad
2018-11-05 10:08:29 -08:00
Xinyuan Wang
0c46230a94 lfs: log download size and time
Summary: Log the downloading time spend and the downloading size when hg is using lfs

Reviewed By: ikostia

Differential Revision: D12813953

fbshipit-source-id: adbcb8c508f5d3668b05d5c894cd7e32085a74f0
2018-11-05 10:01:00 -08:00