What is Git?
Git is a version control software, which means it records changes to
a file or set of files over time so that you can recall specific
versions later. Git works by essentially taking snapshots of a file’s
contents over time, such that you can return to a old snapshot at some
point in the future.
Git vocabulary
repository (repo): folder containing all tracked
files as well as the version control history
local: a version of a repository stored on a
personal computer
remote: a version of a repository stored on a remote
server like GitHub
branch: a parallel version of the files in a
repository
clone: download a copy of a remote repository to
your personal computer
stage (noun): the staging area holds the files to be
included in the next commit
stage (verb): to mark a file to be included in the next
commit
commit (noun): a snapshot of changes made to the
staged file(s)
commit (verb): save a snapshot of changes made to the
staged file(s)
fork (noun): a copy of another user’s
repository
fork (verb): to copy someone else’s repository
merge: update files by incorporating the changes
from new commits
pull: retrieve commits from a remote repository and
merge them into a local repository
push: send commits from a local repository to a
remote repository
pull request: a message sent by one GitHub user to
another with a request to merge their commits from their remote
repository into another user’s remote repository
Git commands
To begin, we will be using Git via the command line, which means
having to type out each instruction. Every Git command begins with the
word git
. If you are running Mac OS, you’ll use
Terminal. If you are running Windows, you’ll use the
Git Bash app that comes with your installation of
Git.
git help
This will bring up the 21 most common Git commands. You can also type
git help blah
where blah
is the name of a
specific command to get more specific information.
git config
Short for “configure”, this is how you set up Git for the first
time.
git init
This initializes a new Git repository, which you will need to do inside
a repository (directory) before Git will recognize it as something to
track.
git status
Check the status of your repository. See which files are inside it and
which changes still need to be committed. This command also offers
helpful hints about possible next steps (e.g., unstaging a commit).
git add
This is a bit misleading as it doesn’t actually add new files to your
repository. Rather, it merely alerts Git to start paying attention to a
file.
git commit
This is the most important command, as it tells Git to take a
snapshot of any changed files in the repository.
git push
This moves (“pushes”) changes from your local repo up to a remote
repository like GitHub.
git pull
This moves (“pulls”) changes from a remote repository like GitHub to
your local repo.
git branch
This creates a new branch in the current repo.
git checkout
This command has two uses: 1) inspect a new branch, and 2) discard any
changes to a local file and revert it back to the way it was at the last
commit.
git merge
When you’re done working on a branch, you can merge your changes back to
the master branch, which is visible to all collaborators. git merge cats
would take all the changes you made to the “cats” branch and add them to
the master.
Getting set up
Create a sandbox
We’ll begin by creating a so-called “sandbox” for playing around with
the various features of Git. In this case, it is simply a folder
(directory).
Using the MacOS Finder or Windows Explorer, create a new folder
(directory) on your Desktop and call it tryout
.
Set working directory
Open RStudio and set your working directory to the
tryout
folder (directory) you just created using the
command line or menu options.
Option 1: command line
username
below is your user name on your computer.
Mac
> setwd("/Users/username/Desktop/tryout")
Windows
> setwd("C:/Desktop/tryout")
Using the command line
We’ll start by using Git via its standard command line interface,
which means you’ll have to do a bit of typing. In the future, you may
very well choose to use Git via a graphical client (e.g., GitHub Desktop, GitKraken) or directly within
Rstudio, which you’ll see in the next lesson. You might then be asking
yourself, “Why do it via the command line?” As you start using Git more
in your workflows, there is a very real possibility that you will want
some assistance to fix a problem or undo a change. The advice you
receive, either from someone you know or via online searches, will very
likely involve direct Git syntax.
Although you can use any suitable terminal interface (e.g.,
Terminal on Mac OS or Windows), we will use the
terminal within RStudio itself.
Click on the Terminal tab to switch from the R
console to the terminal.

If you haven’t used the Terminal before, the text may look a bit
confusing. The information you see is
[computer-name]:[directory] [user-name]$
where [computer-name]
is the name of your computer
(Marks-MacBook-Pro-4
in the example above),
[directory]
is the current terminal directory
(~
indicates the root directory in the example above), and
[user-name]
is your user name on your computer
(mark
in the example above). The $
marks the
beginning of the command line where you can start typing commands.
At this point our R working directory and our terminal directory are
different, so we need to fix that.
Click on the “Terminal 1” downarrow and select “Go to Current
Directory”.

The terminal will echo the actual command you would use to change
directories (cd ~/Desktop/tryout
) and the directory has
switched from [computer-name]:~
to
[computer-name]:tryout
.

Configuring Git
Before using Git for version control, you’ll need to configure it to
use your name and email address.
The following command line instructions will just begin with a
$
instead of the full path
[computer-name]:[directory] [user-name]$
The first step is to tell Git who you are.
Set your user name. Replace first last
with your first
and last names, and be sure to include the quotation marks.
$ git config --global user.name "first last"
The next step is to give Git your email address.
Set your email address. Replace your_email
with your
actual email address and again be sure to include the quotation
marks.
$ git config --global user.email "your_email"
Verify that your user name and email are set correctly.
$ git config --list
You should see something like the output below with your name and
email address. Don’t be alarmed if Git also returns some additional
information.
user.name=First Last
user.email=email@uw.edu
Initialize the repo
Before Git will start tracking the changes to files and folders, you
need to “initialize” your project folder.
Go ahead and initialize the folder.
Input
$ git init
Output
Initialized empty Git repository in /Users/[user-name]/Desktop/tryout/.git/
The command git status
will report all kinds of
information related to the contents of a repo.
Input
$ git status
Output
On branch main
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Here Git is telling us 3 things of interest:
Our branch is set to main
We have not yet made any commits
There is nothing in the folder to commit
Adding files
Before you can commit a file to the tracking history, you need to
“add” it to the list of things for Git to track. To do so, we’ll use
git add
as Git suggested when we typed
git status
above, but at the moment our folder is empty so
we need to populate it with something.
Open a new R script by selecting File > New File > R
Script from the RStudio menu.

Add the following lines of code to your new script.
## a test script
a <- 1
b <- 2

Save your R script to your tryout
folder as
test_script.R
.

Now that we have a new file in our tryout
folder, check
the status of Git.
Input
$ git status
Output
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
test_script.R
nothing added to commit but untracked files present (use "git add" to track)
Here Git is reporting that test_script.R
is “untracked”
and it suggests that you use git add
to track it.
Track the new file with git add filename
, where
filename
is the name of our R script.
Input
$ git add test_script.R
Output
$
git add
is another silent command that doesn’t return
anything.
Check the status of our repo.
Input
$ git status
Output
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: test_script.R
Git reports back that our new file test_script.R
is
“staged” and ready to be committed to the Git history.
Other options for git add
So far we’ve added only one file at a time.
Here are some options for git add
that allow you to add
multiple files at once:
git add *.R
will stage all .R files
git add data/
will stage the folder data
and its contents
git add .
will stage all new and modified files, but
does not remove any deleted files
git add -u
will stage all modified and deleted files,
but does not stage any new files
git add -A
stages all new, modified and deleted
files
Committing a file
Committing files in Git is the backbone of the whole version control
process. To do so, we’ll use git commit
with some
additional information about what we’re committing via a “commit
message”. Commit messages should be “short but informative”, which means
they should include enough information to help you and others understand
what was done without being verbose.
Tip: Mark recommends beginning your commit message
with a past tense verb. For example,
- “created new R script for data ingest”
- “started work on background info for analysis”
- “added new year of data to samples.csv”
Commit your new R script and don’t forget the quotes (the
-m
flag stands for “message”).
Input
$ git commit -m "created test R script"
Output
[main (root-commit) 5e40183] created test R script
1 file changed, 3 insertions(+)
create mode 100644 test_script.R
When we run git commit
, Git takes everything we have
told it to save by using git add
and stores a copy
permanently inside the special .git
directory. This
permanent copy is called a commit and its short identifier is
5e40183
(note that your commit will likely have a different
identifier).
Check the status of your repo and see where things stand.
Input
$ git status
Output
On branch main
nothing to commit, working tree clean
Now Git is reporting that everything is up to date.
If you want a report of your recent activity, you can ask Git to show
you the project’s history using git log
.
Input
$ git log
Output
commit 5e401831a92cf9e6980d0ee78a19966d6b310b78 (HEAD -> main)
Author: First Last <email@domain.edu>
Date: Fri Jan 13 09:05:06 2023 -0800
created test R script
The log lists all commits made to a repository in reverse
chronological order, which includes:
- a full 40-character identifier (i.e., the “SHA-1 checksum”),
starting with the same 7 characters as the short identifier printed by
the
git commit
command we used earlier
- the commit author’s name and email address
- the date/time stamp of when it was created
- the commit message passed to Git
Summary
At this point you’ve seen how to
- initialize a Git repository
- add (stage) a file to be committed
- commit a file to the repository
This figure from Blischak
et al. (2018) shows that process graphically.

Making changes to a file
Let’s now imagine you wanted to return to the R script we created
earlier and add some more lines of code, or make some changes to the
existing code.
Add the following lines of new code to test_script.R
and
save the file when you are done.
## an operation
a + b

Check on the status of your repo.
Input
$ git status
Output
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test_script.R
no changes added to commit (use "git add" and/or "git commit -a")
This output indicates that there is one file
(test_script.R
) that has been modified, but importantly,
nothing has yet been added to the staging area. This is what the last
line of the output is telling us.
Before adding a file to staging, it’s a good idea to inspect the
changes that were made to it. To do this in Git, we’ll use
git diff
, which is short for “difference”.
Input
$ git diff
Output
diff --git a/test_script.R b/test_script.R
index 05922e5..4cdf1a7 100644
--- a/test_script.R
+++ b/test_script.R
@@ -1,3 +1,6 @@
## a test script
a <- 1
b <- 2
+## an operation
+a + b
+
Hmm, this output is definitely a bit cryptic.
- The first line indicates that the Git output is similar to the Unix
diff
command comparing the old
(a/test_script.R
) and new (b/test_script.R
)
versions of the file.
- The second line indicates which versions of the file Git is
comparing (i.e.,
05922e5
and 4cdf1a7
are their
unique version-specific labels).
- The third and fourth lines once again show the name of the file
being changed (
test_script.R
).
- The remaining lines show the actual differences and the lines on
which they occur; the
+
sign in the first column shows the
lines that were added most recently (note that the last line of the R
script is blank).
All of this is good information and everything is okay.
Commit the new changes to our R script.
Input
$ git commit -m "added an addition operation to test R script"
Output
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test_script.R
no changes added to commit (use "git add" and/or "git commit -a")
We forgot to add our file to the staging area, so nothing happened.
Git suggests that we either use git add
and/or
git commit -a
.
Use git add
to add the file to staging and then commit
it.
Input
$ git add test_script.R
$ git commit -m "added an addition operation to test R script"
Output
[main 07eaad4] added an addition operation to test R script
1 file changed, 3 insertions(+)
OK, it looks like that worked, but it’s a good idea to check on the
status of the repo to be sure.
Input
$ git status
Output
On branch main
nothing to commit, working tree clean
Everything seems to be in working order.
Once again, we can check out the history of what we’ve done so
far.
Input
$ git log
Output
commit 07eaad4b2fcbe4be7068c47612dcc4f3f7c6373d (HEAD -> main)
Author: First Last <email@domain.edu>
Date: Fri Jan 13 09:33:32 2023 -0800
added an addition operation to test R script
commit 5e401831a92cf9e6980d0ee78a19966d6b310b78
Author: First Last <email@domain.edu>
Date: Fri Jan 13 09:39:32 2023 -0800
created test R script
Now we can see both of our commits, with the most recent one at the
top.
Add another operation to your R script with the following lines of
code and save the file when done. (For now ignore the fact that this
code is problematic–we’ll return to that later.)
## another operation
(a + b) / 0

Add this file and commit it.
Input
$ git add test_script.R
$ git commit -m "added a division operation to R test script"
Output
[main 17c1a74] added a division operation to R test script
1 file changed, 2 insertions(+), 1 deletion(-)
Reviewing file history
One of the major advantages to using a formal version control system
like Git is that you can go back in time and examine changes that were
made to files. We saw previously that we can use git diff
to inspect the changes that were made to a staged file. Here we’ll
expand that functionality to look back further in time.
Examine the changes to our R script with git diff
.
Input
$ git diff test_script.R
Output
$
In this case there have been no new changes to our file, so the
output is blank.
Git refers to the most recent version of a file as its
HEAD
. Earlier versions of a file are referenced with the
tilde ~
and an integer, such that HEAD~1
is
the version that immediately precedes the current version. Similarly,
HEAD~10
refers to the version 10 steps prior to the current
version.
We can use git diff HEAD filename
to inspect changes to
the current version, but in this case it will yield the same thing as
git diff filename
.
Input
$ git diff HEAD test_script.R
Output
$
Take a peek back at the version prior to your current version and
compare their differences.
Input
$ git diff HEAD~1 test_script.R
Output
diff --git a/test_script.R b/test_script.R
index 4cdf1a7..faed447 100644
--- a/test_script.R
+++ b/test_script.R
@@ -3,4 +3,5 @@
## a test script
a <- 1
b <- 2
## an operation
a + b
-
+## another operation
+(a + b) / 0
Here we can see that we deleted the blank line at the end of the
script as indicated by the -
, and replaced it with the 2
lines beginning with ## another operation
.
Go back and look at the changes relative to your first version of the
script.
Input
$ git diff HEAD~2 test_script.R
Output
diff --git a/test_script.R b/test_script.R
index 05922e5..faed447 100644
--- a/test_script.R
+++ b/test_script.R
@@ -1,3 +1,7 @@
## a test script
a <- 1
b <- 2
+## an operation
+a + b
+## another operation
+(a + b) / 0
Here you can see that the first version had only 3 lines of code and
since then we’ve added 4 new lines of code.
Recovering an old version
Let’s imagine we weren’t happy with the current version of our test
script because perhaps we broke something or we simply can’t get it to
work. Because Git is a version control system, we can easily restore
files to a state they were in at some previous commit.
We can use git checkout
to restore a previous version of
a file by referencing it with HEAD~n
where n
refers to the version we’d like.
The last operation we added to our file will clearly create some
problems for us because it contains a divide-by-zero.
Let’s revert our script to the version just prior to that when
everything was working properly.
Input
$ git checkout HEAD~1 test_script.R
Output
Updated 1 path from b478816
Hmm. That did something, but it’s not immediately clear if it was
what we wanted.
You can use cat
to inspect a file’s contents and see if
it was indeed switched back to the prior version.
Input
$ cat test_script.R
Output
## a test script
a <- 1
b <- 2
## an operation
a + b
Our script is back to the previous working version.
Your open R script in RStudio should have also reverted to the
previous version.

Check on the status of the directory.
Input
$ git status
Output
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test_script.R
Once again Git is telling us that we still need to commit the changes
to our file, so let’s do that.
Input
$ git commit -m "changed test script back to version before division op"
Output
[main 2743b47] changed test script back to version before division op
1 file changed, 1 insertion(+), 2 deletions(-)
Lastly, run git status
again to make sure we’ve gotten
everything cleaned up.
Input
$ git status
Output
On branch main
nothing to commit, working tree clean
Everything seems to be in proper working order!
Git clients
It can be tricky to learn all of the ins and outs of Git, especially
when typing a bunch of cryptic text into the command line. Fortunately,
there are several graphical user interfaces (GUIs) for Git that help
visualize what is being done. We’ll see next time that RStudio offers a
relatively simple interface to Git, but there are others that have much
more functionality. I suggest reading Jenny Bryan’s treatment of them here.
Endnote
You’ve now done the following:
- Initialized a Git repository
- Staged and added files to be tracked
- Committed a file to the Git history
- Compared changes to previous versions of a file
- Reverted a file back to a previous version
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIEdpdCIKZGF0ZTogIjE3IEphbnVhcnkgMjAyNSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGV4dG1hdGUKICAgIGNzczogIi4uL2xlY3R1cmVfaW5zdC5jc3MiCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgo8YnI+CgojIFdoYXQgaXMgR2l0PwoKR2l0IGlzIGEgdmVyc2lvbiBjb250cm9sIHNvZnR3YXJlLCB3aGljaCBtZWFucyBpdCByZWNvcmRzIGNoYW5nZXMgdG8gYSBmaWxlIG9yIHNldCBvZiBmaWxlcyBvdmVyIHRpbWUgc28gdGhhdCB5b3UgY2FuIHJlY2FsbCBzcGVjaWZpYyB2ZXJzaW9ucyBsYXRlci4gR2l0IHdvcmtzIGJ5IGVzc2VudGlhbGx5IHRha2luZyBzbmFwc2hvdHMgb2YgYSBmaWxlJ3MgY29udGVudHMgb3ZlciB0aW1lLCBzdWNoIHRoYXQgeW91IGNhbiByZXR1cm4gdG8gYSBvbGQgc25hcHNob3QgYXQgc29tZSBwb2ludCBpbiB0aGUgZnV0dXJlLgoKKioqCgojIEdpdCB2b2NhYnVsYXJ5Cgo8YnI+CgoqKnJlcG9zaXRvcnkgKHJlcG8pKio6IGZvbGRlciBjb250YWluaW5nIGFsbCB0cmFja2VkIGZpbGVzIGFzIHdlbGwgYXMgdGhlIHZlcnNpb24gY29udHJvbCBoaXN0b3J5CgoqKmxvY2FsKio6IGEgdmVyc2lvbiBvZiBhIHJlcG9zaXRvcnkgc3RvcmVkIG9uIGEgcGVyc29uYWwgY29tcHV0ZXIKCioqcmVtb3RlKio6IGEgdmVyc2lvbiBvZiBhIHJlcG9zaXRvcnkgc3RvcmVkIG9uIGEgcmVtb3RlIHNlcnZlciBsaWtlIEdpdEh1YgoKKipicmFuY2gqKjogYSBwYXJhbGxlbCB2ZXJzaW9uIG9mIHRoZSBmaWxlcyBpbiBhIHJlcG9zaXRvcnkKCioqY2xvbmUqKjogZG93bmxvYWQgYSBjb3B5IG9mIGEgcmVtb3RlIHJlcG9zaXRvcnkgdG8geW91ciBwZXJzb25hbCBjb21wdXRlcgoKKipzdGFnZSAobm91bikqKjogdGhlIHN0YWdpbmcgYXJlYSBob2xkcyB0aGUgZmlsZXMgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIG5leHQgY29tbWl0ICAKKipzdGFnZSAodmVyYikqKjogdG8gbWFyayBhIGZpbGUgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIG5leHQgY29tbWl0CgoqKmNvbW1pdCAobm91bikqKjogYSBzbmFwc2hvdCBvZiBjaGFuZ2VzIG1hZGUgdG8gdGhlIHN0YWdlZCBmaWxlKHMpICAKKipjb21taXQgKHZlcmIpKio6IHNhdmUgYSBzbmFwc2hvdCBvZiBjaGFuZ2VzIG1hZGUgdG8gdGhlIHN0YWdlZCBmaWxlKHMpCgoqKmZvcmsgKG5vdW4pKio6IGEgY29weSBvZiBhbm90aGVyIHVzZXIncyByZXBvc2l0b3J5ICAKKipmb3JrICh2ZXJiKSoqOiB0byBjb3B5IHNvbWVvbmUgZWxzZSdzIHJlcG9zaXRvcnkKCioqbWVyZ2UqKjogdXBkYXRlIGZpbGVzIGJ5IGluY29ycG9yYXRpbmcgdGhlIGNoYW5nZXMgZnJvbSBuZXcgY29tbWl0cwoKKipwdWxsKio6IHJldHJpZXZlIGNvbW1pdHMgZnJvbSBhIHJlbW90ZSByZXBvc2l0b3J5IGFuZCBtZXJnZSB0aGVtIGludG8gYSBsb2NhbCByZXBvc2l0b3J5CgoqKnB1c2gqKjogc2VuZCBjb21taXRzIGZyb20gYSBsb2NhbCByZXBvc2l0b3J5IHRvIGEgcmVtb3RlIHJlcG9zaXRvcnkKCioqcHVsbCByZXF1ZXN0Kio6IGEgbWVzc2FnZSBzZW50IGJ5IG9uZSBHaXRIdWIgdXNlciB0byBhbm90aGVyIHdpdGggYSByZXF1ZXN0IHRvIG1lcmdlIHRoZWlyIGNvbW1pdHMgZnJvbSB0aGVpciByZW1vdGUgcmVwb3NpdG9yeSBpbnRvIGFub3RoZXIgdXNlcidzIHJlbW90ZSByZXBvc2l0b3J5CgoqKioKCiMgR2l0IGNvbW1hbmRzCgpUbyBiZWdpbiwgd2Ugd2lsbCBiZSB1c2luZyBHaXQgdmlhIHRoZSBjb21tYW5kIGxpbmUsIHdoaWNoIG1lYW5zIGhhdmluZyB0byB0eXBlIG91dCBlYWNoIGluc3RydWN0aW9uLiBFdmVyeSBHaXQgY29tbWFuZCBiZWdpbnMgd2l0aCB0aGUgd29yZCBgZ2l0YC4gSWYgeW91IGFyZSBydW5uaW5nIE1hYyBPUywgeW91J2xsIHVzZSAqKlRlcm1pbmFsKiouIElmIHlvdSBhcmUgcnVubmluZyBXaW5kb3dzLCB5b3UnbGwgdXNlIHRoZSAqKkdpdCBCYXNoKiogYXBwIHRoYXQgY29tZXMgd2l0aCB5b3VyIGluc3RhbGxhdGlvbiBvZiBHaXQuCgpgZ2l0IGhlbHBgICAKVGhpcyB3aWxsIGJyaW5nIHVwIHRoZSAyMSBtb3N0IGNvbW1vbiBHaXQgY29tbWFuZHMuIFlvdSBjYW4gYWxzbyB0eXBlIGBnaXQgaGVscCBibGFoYCB3aGVyZSBgYmxhaGAgaXMgdGhlIG5hbWUgb2YgYSBzcGVjaWZpYyBjb21tYW5kIHRvIGdldCBtb3JlIHNwZWNpZmljIGluZm9ybWF0aW9uLgoKYGdpdCBjb25maWdgICAKU2hvcnQgZm9yICJjb25maWd1cmUiLCB0aGlzIGlzIGhvdyB5b3Ugc2V0IHVwIEdpdCBmb3IgdGhlIGZpcnN0IHRpbWUuCgpgZ2l0IGluaXRgICAKVGhpcyBpbml0aWFsaXplcyBhIG5ldyBHaXQgcmVwb3NpdG9yeSwgd2hpY2ggeW91IHdpbGwgbmVlZCB0byBkbyBpbnNpZGUgYSByZXBvc2l0b3J5IChkaXJlY3RvcnkpIGJlZm9yZSBHaXQgd2lsbCByZWNvZ25pemUgaXQgYXMgc29tZXRoaW5nIHRvIHRyYWNrLgoKYGdpdCBzdGF0dXNgICAKQ2hlY2sgdGhlIHN0YXR1cyBvZiB5b3VyIHJlcG9zaXRvcnkuIFNlZSB3aGljaCBmaWxlcyBhcmUgaW5zaWRlIGl0IGFuZCB3aGljaCBjaGFuZ2VzIHN0aWxsIG5lZWQgdG8gYmUgY29tbWl0dGVkLiBUaGlzIGNvbW1hbmQgYWxzbyBvZmZlcnMgaGVscGZ1bCBoaW50cyBhYm91dCBwb3NzaWJsZSBuZXh0IHN0ZXBzIChlLmcuLCB1bnN0YWdpbmcgYSBjb21taXQpLgoKYGdpdCBhZGRgICAKVGhpcyBpcyBhIGJpdCBtaXNsZWFkaW5nIGFzIGl0IGRvZXNuJ3QgYWN0dWFsbHkgYWRkIG5ldyBmaWxlcyB0byB5b3VyIHJlcG9zaXRvcnkuIFJhdGhlciwgaXQgbWVyZWx5IGFsZXJ0cyBHaXQgdG8gc3RhcnQgcGF5aW5nIGF0dGVudGlvbiB0byBhIGZpbGUuCgpgZ2l0IGNvbW1pdGAgIApUaGlzIGlzICp0aGUgbW9zdCBpbXBvcnRhbnQqIGNvbW1hbmQsIGFzIGl0IHRlbGxzIEdpdCB0byB0YWtlIGEgc25hcHNob3Qgb2YgYW55IGNoYW5nZWQgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkuCgpgZ2l0IHB1c2hgICAKVGhpcyBtb3ZlcyAoInB1c2hlcyIpIGNoYW5nZXMgZnJvbSB5b3VyIGxvY2FsIHJlcG8gdXAgdG8gYSByZW1vdGUgcmVwb3NpdG9yeSBsaWtlIEdpdEh1Yi4KCmBnaXQgcHVsbGAgIApUaGlzIG1vdmVzICgicHVsbHMiKSBjaGFuZ2VzIGZyb20gYSByZW1vdGUgcmVwb3NpdG9yeSBsaWtlIEdpdEh1YiB0byB5b3VyIGxvY2FsIHJlcG8uCgpgZ2l0IGJyYW5jaGAgIApUaGlzIGNyZWF0ZXMgYSBuZXcgYnJhbmNoIGluIHRoZSBjdXJyZW50IHJlcG8uCgpgZ2l0IGNoZWNrb3V0YCAgClRoaXMgY29tbWFuZCBoYXMgdHdvIHVzZXM6IDEpIGluc3BlY3QgYSBuZXcgYnJhbmNoLCBhbmQgMikgZGlzY2FyZCBhbnkgY2hhbmdlcyB0byBhIGxvY2FsIGZpbGUgYW5kIHJldmVydCBpdCBiYWNrIHRvIHRoZSB3YXkgaXQgd2FzIGF0IHRoZSBsYXN0IGNvbW1pdC4KCmBnaXQgbWVyZ2VgICAKV2hlbiB5b3XigJlyZSBkb25lIHdvcmtpbmcgb24gYSBicmFuY2gsIHlvdSBjYW4gbWVyZ2UgeW91ciBjaGFuZ2VzIGJhY2sgdG8gdGhlIG1hc3RlciBicmFuY2gsIHdoaWNoIGlzIHZpc2libGUgdG8gYWxsIGNvbGxhYm9yYXRvcnMuIGdpdCBtZXJnZSBjYXRzIHdvdWxkIHRha2UgYWxsIHRoZSBjaGFuZ2VzIHlvdSBtYWRlIHRvIHRoZSDigJxjYXRz4oCdIGJyYW5jaCBhbmQgYWRkIHRoZW0gdG8gdGhlIG1hc3Rlci4KCioqKgoKIyBHZXR0aW5nIHNldCB1cAoKIyMgQ3JlYXRlIGEgc2FuZGJveAoKV2UnbGwgYmVnaW4gYnkgY3JlYXRpbmcgYSBzby1jYWxsZWQgInNhbmRib3giIGZvciBwbGF5aW5nIGFyb3VuZCB3aXRoIHRoZSB2YXJpb3VzIGZlYXR1cmVzIG9mIEdpdC4gSW4gdGhpcyBjYXNlLCBpdCBpcyBzaW1wbHkgYSBmb2xkZXIgKGRpcmVjdG9yeSkuCgo6OjogdGFzawoKVXNpbmcgdGhlIE1hY09TIEZpbmRlciBvciBXaW5kb3dzIEV4cGxvcmVyLCBjcmVhdGUgYSBuZXcgZm9sZGVyIChkaXJlY3RvcnkpIG9uIHlvdXIgRGVza3RvcCBhbmQgY2FsbCBpdCBgdHJ5b3V0YC4KCjo6OgoKIyMgU2V0IHdvcmtpbmcgZGlyZWN0b3J5Cgo6OjogdGFzawoKT3BlbiBSU3R1ZGlvIGFuZCBzZXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgYHRyeW91dGAgZm9sZGVyIChkaXJlY3RvcnkpIHlvdSBqdXN0IGNyZWF0ZWQgdXNpbmcgdGhlIGNvbW1hbmQgbGluZSBvciBtZW51IG9wdGlvbnMuCgo6OjoKCiMjIyBPcHRpb24gMTogY29tbWFuZCBsaW5lCgo6OjogdGlwCgpgdXNlcm5hbWVgIGJlbG93IGlzIHlvdXIgdXNlciBuYW1lIG9uIHlvdXIgY29tcHV0ZXIuCgo6OjoKCioqTWFjKioKCmBgYHNoCj4gc2V0d2QoIi9Vc2Vycy91c2VybmFtZS9EZXNrdG9wL3RyeW91dCIpCmBgYAoKKipXaW5kb3dzKioKCmBgYHNoCj4gc2V0d2QoIkM6L0Rlc2t0b3AvdHJ5b3V0IikKYGBgCgo8YnI+CgojIyMgT3B0aW9uIDI6IFJTdHVkaW8gbWVudQoKIVtdKGltYWdlcy9yc3R1ZGlvX3NldHdkLnBuZyl7IGhlaWdodD04MCUgd2lkdGg9ODAlIH0KCjxicj4KCioqKgoKIyBVc2luZyB0aGUgY29tbWFuZCBsaW5lCgpXZSdsbCBzdGFydCBieSB1c2luZyBHaXQgdmlhIGl0cyBzdGFuZGFyZCBjb21tYW5kIGxpbmUgaW50ZXJmYWNlLCB3aGljaCBtZWFucyB5b3UnbGwgaGF2ZSB0byBkbyBhIGJpdCBvZiB0eXBpbmcuIEluIHRoZSBmdXR1cmUsIHlvdSBtYXkgdmVyeSB3ZWxsIGNob29zZSB0byB1c2UgR2l0IHZpYSBhIGdyYXBoaWNhbCBjbGllbnQgKGUuZy4sIFtHaXRIdWIgRGVza3RvcF0oaHR0cHM6Ly9kZXNrdG9wLmdpdGh1Yi5jb20vKSwgW0dpdEtyYWtlbl0oaHR0cHM6Ly93d3cuZ2l0a3Jha2VuLmNvbS8pKSBvciBkaXJlY3RseSB3aXRoaW4gUnN0dWRpbywgd2hpY2ggeW91J2xsIHNlZSBpbiB0aGUgbmV4dCBsZXNzb24uIFlvdSBtaWdodCB0aGVuIGJlIGFza2luZyB5b3Vyc2VsZiwgIldoeSBkbyBpdCB2aWEgdGhlIGNvbW1hbmQgbGluZT8iIEFzIHlvdSBzdGFydCB1c2luZyBHaXQgbW9yZSBpbiB5b3VyIHdvcmtmbG93cywgdGhlcmUgaXMgYSB2ZXJ5IHJlYWwgcG9zc2liaWxpdHkgdGhhdCB5b3Ugd2lsbCB3YW50IHNvbWUgYXNzaXN0YW5jZSB0byBmaXggYSBwcm9ibGVtIG9yIHVuZG8gYSBjaGFuZ2UuIFRoZSBhZHZpY2UgeW91IHJlY2VpdmUsIGVpdGhlciBmcm9tIHNvbWVvbmUgeW91IGtub3cgb3IgdmlhIG9ubGluZSBzZWFyY2hlcywgd2lsbCB2ZXJ5IGxpa2VseSBpbnZvbHZlIGRpcmVjdCBHaXQgc3ludGF4LgoKQWx0aG91Z2ggeW91IGNhbiB1c2UgYW55IHN1aXRhYmxlIHRlcm1pbmFsIGludGVyZmFjZSAoZS5nLiwgICoqVGVybWluYWwqKiBvbiBNYWMgT1Mgb3IgV2luZG93cyksIHdlIHdpbGwgdXNlIHRoZSB0ZXJtaW5hbCB3aXRoaW4gUlN0dWRpbyBpdHNlbGYuIAoKOjo6IHRhc2sKCkNsaWNrIG9uIHRoZSAqKlRlcm1pbmFsKiogdGFiIHRvIHN3aXRjaCBmcm9tIHRoZSBSIGNvbnNvbGUgdG8gdGhlIHRlcm1pbmFsLgoKOjo6CgohW10oaW1hZ2VzL3Rlcm1fb3Blbi5wbmcpeyBoZWlnaHQ9ODAlIHdpZHRoPTgwJSB9Cgo8YnI+CgpJZiB5b3UgaGF2ZW4ndCB1c2VkIHRoZSBUZXJtaW5hbCBiZWZvcmUsIHRoZSB0ZXh0IG1heSBsb29rIGEgYml0IGNvbmZ1c2luZy4gVGhlIGluZm9ybWF0aW9uIHlvdSBzZWUgaXMKCmBgYHNoCltjb21wdXRlci1uYW1lXTpbZGlyZWN0b3J5XSBbdXNlci1uYW1lXSQKYGBgCgp3aGVyZSBgW2NvbXB1dGVyLW5hbWVdYCBpcyB0aGUgbmFtZSBvZiB5b3VyIGNvbXB1dGVyIChgTWFya3MtTWFjQm9vay1Qcm8tNGAgaW4gdGhlIGV4YW1wbGUgYWJvdmUpLCBgW2RpcmVjdG9yeV1gIGlzIHRoZSBjdXJyZW50IHRlcm1pbmFsIGRpcmVjdG9yeSAoYH5gIGluZGljYXRlcyB0aGUgcm9vdCBkaXJlY3RvcnkgaW4gdGhlIGV4YW1wbGUgYWJvdmUpLCBhbmQgYFt1c2VyLW5hbWVdYCBpcyB5b3VyIHVzZXIgbmFtZSBvbiB5b3VyIGNvbXB1dGVyIChgbWFya2AgaW4gdGhlIGV4YW1wbGUgYWJvdmUpLiBUaGUgYCRgIG1hcmtzIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNvbW1hbmQgbGluZSB3aGVyZSB5b3UgY2FuIHN0YXJ0IHR5cGluZyBjb21tYW5kcy4KCkF0IHRoaXMgcG9pbnQgb3VyIFIgd29ya2luZyBkaXJlY3RvcnkgYW5kIG91ciB0ZXJtaW5hbCBkaXJlY3RvcnkgYXJlIGRpZmZlcmVudCwgc28gd2UgbmVlZCB0byBmaXggdGhhdC4KCjo6OiB0YXNrCgpDbGljayBvbiB0aGUgIlRlcm1pbmFsIDEiIGRvd25hcnJvdyBhbmQgc2VsZWN0ICJHbyB0byBDdXJyZW50IERpcmVjdG9yeSIuCgo6OjoKCiFbXShpbWFnZXMvdGVybV9jdXJyZW50X2Rpci5wbmcpeyBoZWlnaHQ9ODAlIHdpZHRoPTgwJSB9Cgo8YnI+Cgo6OjogdGlwCgpUaGUgdGVybWluYWwgd2lsbCBlY2hvIHRoZSBhY3R1YWwgY29tbWFuZCB5b3Ugd291bGQgdXNlIHRvIGNoYW5nZSBkaXJlY3RvcmllcyAoYGNkIH4vRGVza3RvcC90cnlvdXRgKSBhbmQgdGhlIGRpcmVjdG9yeSBoYXMgc3dpdGNoZWQgZnJvbSBgW2NvbXB1dGVyLW5hbWVdOn5gIHRvIGBbY29tcHV0ZXItbmFtZV06dHJ5b3V0YC4KCjo6OgoKIVtdKGltYWdlcy90ZXJtX2Rpcl9zZXQucG5nKXsgaGVpZ2h0PTgwJSB3aWR0aD04MCUgfQoKPGJyPgoKCgoqKioKCiMgQ29uZmlndXJpbmcgR2l0CgpCZWZvcmUgdXNpbmcgR2l0IGZvciB2ZXJzaW9uIGNvbnRyb2wsIHlvdSdsbCBuZWVkIHRvIGNvbmZpZ3VyZSBpdCB0byB1c2UgeW91ciBuYW1lIGFuZCBlbWFpbCBhZGRyZXNzLgoKOjo6IG5vdGUKClRoZSBmb2xsb3dpbmcgY29tbWFuZCBsaW5lIGluc3RydWN0aW9ucyB3aWxsIGp1c3QgYmVnaW4gd2l0aCBhIGAkYCBpbnN0ZWFkIG9mIHRoZSBmdWxsIHBhdGggYFtjb21wdXRlci1uYW1lXTpbZGlyZWN0b3J5XSBbdXNlci1uYW1lXSRgCgo6OjoKClRoZSBmaXJzdCBzdGVwIGlzIHRvIHRlbGwgR2l0IHdobyB5b3UgYXJlLgoKOjo6IHRhc2sKClNldCB5b3VyIHVzZXIgbmFtZS4gUmVwbGFjZSBgZmlyc3QgbGFzdGAgd2l0aCB5b3VyIGZpcnN0IGFuZCBsYXN0IG5hbWVzLCBhbmQgYmUgc3VyZSB0byBpbmNsdWRlIHRoZSBxdW90YXRpb24gbWFya3MuCgo6OjoKCmBgYHNoCiQgZ2l0IGNvbmZpZyAtLWdsb2JhbCB1c2VyLm5hbWUgImZpcnN0IGxhc3QiCmBgYAoKVGhlIG5leHQgc3RlcCBpcyB0byBnaXZlIEdpdCB5b3VyIGVtYWlsIGFkZHJlc3MuCgo6OjogdGFzawoKU2V0IHlvdXIgZW1haWwgYWRkcmVzcy4gUmVwbGFjZSBgeW91cl9lbWFpbGAgd2l0aCB5b3VyIGFjdHVhbCBlbWFpbCBhZGRyZXNzIGFuZCBhZ2FpbiBiZSBzdXJlIHRvIGluY2x1ZGUgdGhlIHF1b3RhdGlvbiBtYXJrcy4KCjo6OgoKYGBgc2gKJCBnaXQgY29uZmlnIC0tZ2xvYmFsIHVzZXIuZW1haWwgInlvdXJfZW1haWwiCmBgYAoKOjo6IHRhc2sKClZlcmlmeSB0aGF0IHlvdXIgdXNlciBuYW1lIGFuZCBlbWFpbCBhcmUgc2V0IGNvcnJlY3RseS4KCjo6OgoKYGBgc2gKJCBnaXQgY29uZmlnIC0tbGlzdApgYGAKCjo6OiB0YXNrCgpZb3Ugc2hvdWxkIHNlZSBzb21ldGhpbmcgbGlrZSB0aGUgb3V0cHV0IGJlbG93IHdpdGggeW91ciBuYW1lIGFuZCBlbWFpbCBhZGRyZXNzLiBEb24ndCBiZSBhbGFybWVkIGlmIEdpdCBhbHNvIHJldHVybnMgc29tZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uLgoKOjo6CgpgYGBzaAp1c2VyLm5hbWU9Rmlyc3QgTGFzdAp1c2VyLmVtYWlsPWVtYWlsQHV3LmVkdQpgYGAKCioqKgoKIyBJbml0aWFsaXplIHRoZSByZXBvCgpCZWZvcmUgR2l0IHdpbGwgc3RhcnQgdHJhY2tpbmcgdGhlIGNoYW5nZXMgdG8gZmlsZXMgYW5kIGZvbGRlcnMsIHlvdSBuZWVkIHRvICJpbml0aWFsaXplIiB5b3VyIHByb2plY3QgZm9sZGVyLgoKOjo6IHRhc2sKCkdvIGFoZWFkIGFuZCBpbml0aWFsaXplIHRoZSBmb2xkZXIuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgaW5pdApgYGAKCioqT3V0cHV0KioKCmBgYHNoCkluaXRpYWxpemVkIGVtcHR5IEdpdCByZXBvc2l0b3J5IGluIC9Vc2Vycy9bdXNlci1uYW1lXS9EZXNrdG9wL3RyeW91dC8uZ2l0LwpgYGAKCjo6OiB0YXNrCgpUaGUgY29tbWFuZCBgZ2l0IHN0YXR1c2Agd2lsbCByZXBvcnQgYWxsIGtpbmRzIG9mIGluZm9ybWF0aW9uIHJlbGF0ZWQgdG8gdGhlIGNvbnRlbnRzIG9mIGEgcmVwby4KCjo6OgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBzdGF0dXMKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApPbiBicmFuY2ggbWFpbgoKTm8gY29tbWl0cyB5ZXQKCm5vdGhpbmcgdG8gY29tbWl0IChjcmVhdGUvY29weSBmaWxlcyBhbmQgdXNlICJnaXQgYWRkIiB0byB0cmFjaykKYGBgCgo6Ojogbm90ZQoKSGVyZSBHaXQgaXMgdGVsbGluZyB1cyAzIHRoaW5ncyBvZiBpbnRlcmVzdDoKCjEpIE91ciBicmFuY2ggaXMgc2V0IHRvIGBtYWluYAogIAoyKSBXZSBoYXZlIG5vdCB5ZXQgbWFkZSBhbnkgY29tbWl0cwoKMykgVGhlcmUgaXMgbm90aGluZyBpbiB0aGUgZm9sZGVyIHRvIGNvbW1pdAoKOjo6CgoKKioqCgojIEFkZGluZyBmaWxlcwoKQmVmb3JlIHlvdSBjYW4gY29tbWl0IGEgZmlsZSB0byB0aGUgdHJhY2tpbmcgaGlzdG9yeSwgeW91IG5lZWQgdG8gImFkZCIgaXQgdG8gdGhlIGxpc3Qgb2YgdGhpbmdzIGZvciBHaXQgdG8gdHJhY2suIFRvIGRvIHNvLCB3ZSdsbCB1c2UgYGdpdCBhZGRgIGFzIEdpdCBzdWdnZXN0ZWQgd2hlbiB3ZSB0eXBlZCBgZ2l0IHN0YXR1c2AgYWJvdmUsIGJ1dCBhdCB0aGUgbW9tZW50IG91ciBmb2xkZXIgaXMgZW1wdHkgc28gd2UgbmVlZCB0byBwb3B1bGF0ZSBpdCB3aXRoIHNvbWV0aGluZy4gCgo6OjogdGFzawoKT3BlbiBhIG5ldyBSIHNjcmlwdCBieSBzZWxlY3RpbmcgKipGaWxlID4gTmV3IEZpbGUgPiBSIFNjcmlwdCoqIGZyb20gdGhlIFJTdHVkaW8gbWVudS4KCjo6OgoKIVtdKGltYWdlcy9SX3NjcmlwdF9uZXcucG5nKXsgaGVpZ2h0PTgwJSB3aWR0aD04MCUgfQoKPGJyPgoKOjo6IHRhc2sKCkFkZCB0aGUgZm9sbG93aW5nIGxpbmVzIG9mIGNvZGUgdG8geW91ciBuZXcgc2NyaXB0LgoKOjo6CgpgYGBzaAojIyBhIHRlc3Qgc2NyaXB0CmEgPC0gMQpiIDwtIDIKYGBgCgohW10oaW1hZ2VzL1Jfc2NyaXB0X2FkZF8xLnBuZyl7IGhlaWdodD04MCUgd2lkdGg9ODAlIH0KCjxicj4KCjo6OiB0YXNrCgpTYXZlIHlvdXIgUiBzY3JpcHQgdG8geW91ciBgdHJ5b3V0YCBmb2xkZXIgYXMgYHRlc3Rfc2NyaXB0LlJgIC4KCjo6OgoKIVtdKGltYWdlcy9SX3NjcmlwdF9zYXZlZF8xLnBuZyl7IGhlaWdodD04MCUgd2lkdGg9ODAlIH0KCjxicj4KCjo6OiB0YXNrCgpOb3cgdGhhdCB3ZSBoYXZlIGEgbmV3IGZpbGUgaW4gb3VyIGB0cnlvdXRgIGZvbGRlciwgY2hlY2sgdGhlIHN0YXR1cyBvZiBHaXQuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgc3RhdHVzCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKT24gYnJhbmNoIG1haW4KCk5vIGNvbW1pdHMgeWV0CgpVbnRyYWNrZWQgZmlsZXM6CiAgKHVzZSAiZ2l0IGFkZCA8ZmlsZT4uLi4iIHRvIGluY2x1ZGUgaW4gd2hhdCB3aWxsIGJlIGNvbW1pdHRlZCkKCXRlc3Rfc2NyaXB0LlIKCm5vdGhpbmcgYWRkZWQgdG8gY29tbWl0IGJ1dCB1bnRyYWNrZWQgZmlsZXMgcHJlc2VudCAodXNlICJnaXQgYWRkIiB0byB0cmFjaykKYGBgCgo6Ojogbm90ZQoKSGVyZSBHaXQgaXMgcmVwb3J0aW5nIHRoYXQgYHRlc3Rfc2NyaXB0LlJgIGlzICJ1bnRyYWNrZWQiIGFuZCBpdCBzdWdnZXN0cyB0aGF0IHlvdSB1c2UgYGdpdCBhZGRgIHRvIHRyYWNrIGl0LgoKOjo6Cgo6OjogdGFzawoKVHJhY2sgdGhlIG5ldyBmaWxlIHdpdGggYGdpdCBhZGQgZmlsZW5hbWVgLCB3aGVyZSBgZmlsZW5hbWVgIGlzIHRoZSBuYW1lIG9mIG91ciBSIHNjcmlwdC4KCjo6OgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBhZGQgdGVzdF9zY3JpcHQuUgpgYGAKCioqT3V0cHV0KioKCmBgYHNoCiQKYGBgCgo6Ojogbm90ZQoKYGdpdCBhZGRgIGlzIGFub3RoZXIgc2lsZW50IGNvbW1hbmQgdGhhdCBkb2Vzbid0IHJldHVybiBhbnl0aGluZy4KCjo6OgoKOjo6IHRhc2sKCkNoZWNrIHRoZSBzdGF0dXMgb2Ygb3VyIHJlcG8uCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgc3RhdHVzCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKT24gYnJhbmNoIG1haW4KCk5vIGNvbW1pdHMgeWV0CgpDaGFuZ2VzIHRvIGJlIGNvbW1pdHRlZDoKICAodXNlICJnaXQgcm0gLS1jYWNoZWQgPGZpbGU+Li4uIiB0byB1bnN0YWdlKQoJbmV3IGZpbGU6ICAgdGVzdF9zY3JpcHQuUgoKYGBgCgo6Ojogbm90ZQoKR2l0IHJlcG9ydHMgYmFjayB0aGF0IG91ciBuZXcgZmlsZSBgdGVzdF9zY3JpcHQuUmAgaXMgInN0YWdlZCIgYW5kIHJlYWR5IHRvIGJlIGNvbW1pdHRlZCB0byB0aGUgR2l0IGhpc3RvcnkuCgo6OjoKCiMjIyBPdGhlciBvcHRpb25zIGZvciBgZ2l0IGFkZGAKClNvIGZhciB3ZSd2ZSBhZGRlZCBvbmx5IG9uZSBmaWxlIGF0IGEgdGltZS4KCjo6OiB0aXAKCkhlcmUgYXJlIHNvbWUgb3B0aW9ucyBmb3IgYGdpdCBhZGRgIHRoYXQgYWxsb3cgeW91IHRvIGFkZCBtdWx0aXBsZSBmaWxlcyBhdCBvbmNlOgoKKiBgZ2l0IGFkZCAqLlJgIHdpbGwgc3RhZ2UgYWxsIC5SIGZpbGVzCiogYGdpdCBhZGQgZGF0YS9gIHdpbGwgc3RhZ2UgdGhlIGZvbGRlciBgZGF0YWAgYW5kIGl0cyBjb250ZW50cwoqIGBnaXQgYWRkIC5gIHdpbGwgc3RhZ2UgYWxsIG5ldyBhbmQgbW9kaWZpZWQgZmlsZXMsIGJ1dCBkb2VzIG5vdCByZW1vdmUgYW55IGRlbGV0ZWQgZmlsZXMKKiBgZ2l0IGFkZCAtdWAgd2lsbCBzdGFnZSBhbGwgbW9kaWZpZWQgYW5kIGRlbGV0ZWQgZmlsZXMsIGJ1dCBkb2VzIG5vdCBzdGFnZSBhbnkgbmV3IGZpbGVzCiogYGdpdCBhZGQgLUFgIHN0YWdlcyBhbGwgbmV3LCBtb2RpZmllZCBhbmQgZGVsZXRlZCBmaWxlcwoKOjo6CgoqKioKCiMgQ29tbWl0dGluZyBhIGZpbGUKCkNvbW1pdHRpbmcgZmlsZXMgaW4gR2l0IGlzIHRoZSBiYWNrYm9uZSBvZiB0aGUgd2hvbGUgdmVyc2lvbiBjb250cm9sIHByb2Nlc3MuIFRvIGRvIHNvLCB3ZSdsbCB1c2UgYGdpdCBjb21taXRgIHdpdGggc29tZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHdoYXQgd2UncmUgY29tbWl0dGluZyB2aWEgYSAiY29tbWl0IG1lc3NhZ2UiLiBDb21taXQgbWVzc2FnZXMgc2hvdWxkIGJlICJzaG9ydCBidXQgaW5mb3JtYXRpdmUiLCB3aGljaCBtZWFucyB0aGV5IHNob3VsZCBpbmNsdWRlIGVub3VnaCBpbmZvcm1hdGlvbiB0byBoZWxwIHlvdSBhbmQgb3RoZXJzIHVuZGVyc3RhbmQgd2hhdCB3YXMgZG9uZSB3aXRob3V0IGJlaW5nIHZlcmJvc2UuCgo6OjogdGlwCgoqKlRpcDoqKiBNYXJrIHJlY29tbWVuZHMgYmVnaW5uaW5nIHlvdXIgY29tbWl0IG1lc3NhZ2Ugd2l0aCBhIHBhc3QgdGVuc2UgdmVyYi4gRm9yIGV4YW1wbGUsCgoqICJjcmVhdGVkIG5ldyBSIHNjcmlwdCBmb3IgZGF0YSBpbmdlc3QiCiogInN0YXJ0ZWQgd29yayBvbiBiYWNrZ3JvdW5kIGluZm8gZm9yIGFuYWx5c2lzIgoqICJhZGRlZCBuZXcgeWVhciBvZiBkYXRhIHRvIHNhbXBsZXMuY3N2IgoKOjo6Cgo6OjogdGFzawoKQ29tbWl0IHlvdXIgbmV3IFIgc2NyaXB0IGFuZCBkb24ndCBmb3JnZXQgdGhlIHF1b3RlcyAodGhlIGAtbWAgZmxhZyBzdGFuZHMgZm9yICJtZXNzYWdlIikuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgY29tbWl0IC1tICJjcmVhdGVkIHRlc3QgUiBzY3JpcHQiCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKW21haW4gKHJvb3QtY29tbWl0KSA1ZTQwMTgzXSBjcmVhdGVkIHRlc3QgUiBzY3JpcHQKIDEgZmlsZSBjaGFuZ2VkLCAzIGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCB0ZXN0X3NjcmlwdC5SCmBgYAoKV2hlbiB3ZSBydW4gYGdpdCBjb21taXRgLCBHaXQgdGFrZXMgZXZlcnl0aGluZyB3ZSBoYXZlIHRvbGQgaXQgdG8gc2F2ZSBieSB1c2luZyBgZ2l0IGFkZGAgYW5kIHN0b3JlcyBhIGNvcHkgcGVybWFuZW50bHkgaW5zaWRlIHRoZSBzcGVjaWFsIGAuZ2l0YCBkaXJlY3RvcnkuIFRoaXMgcGVybWFuZW50IGNvcHkgaXMgY2FsbGVkIGEgY29tbWl0IGFuZCBpdHMgc2hvcnQgaWRlbnRpZmllciBpcyBgNWU0MDE4M2AgKG5vdGUgdGhhdCB5b3VyIGNvbW1pdCB3aWxsIGxpa2VseSBoYXZlIGEgZGlmZmVyZW50IGlkZW50aWZpZXIpLgoKOjo6IHRhc2sKCkNoZWNrIHRoZSBzdGF0dXMgb2YgeW91ciByZXBvIGFuZCBzZWUgd2hlcmUgdGhpbmdzIHN0YW5kLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IHN0YXR1cwpgYGAKCioqT3V0cHV0KioKCmBgYHNoCk9uIGJyYW5jaCBtYWluCm5vdGhpbmcgdG8gY29tbWl0LCB3b3JraW5nIHRyZWUgY2xlYW4KYGBgCgpOb3cgR2l0IGlzIHJlcG9ydGluZyB0aGF0IGV2ZXJ5dGhpbmcgaXMgdXAgdG8gZGF0ZS4gCgo6OjogdGlwCgpJZiB5b3Ugd2FudCBhIHJlcG9ydCBvZiB5b3VyIHJlY2VudCBhY3Rpdml0eSwgeW91IGNhbiBhc2sgR2l0IHRvIHNob3cgeW91IHRoZSBwcm9qZWN0J3MgaGlzdG9yeSB1c2luZyBgZ2l0IGxvZ2AuCgo6OjoKCjo6OiB0YXNrCgpDaGVjayB0aGUgbG9nLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGxvZwpgYGAKCioqT3V0cHV0KioKCmBgYHNoCmNvbW1pdCA1ZTQwMTgzMWE5MmNmOWU2OTgwZDBlZTc4YTE5OTY2ZDZiMzEwYjc4IChIRUFEIC0+IG1haW4pCkF1dGhvcjogRmlyc3QgTGFzdCA8ZW1haWxAZG9tYWluLmVkdT4KRGF0ZTogICBGcmkgSmFuIDEzIDA5OjA1OjA2IDIwMjMgLTA4MDAKCiAgICBjcmVhdGVkIHRlc3QgUiBzY3JpcHQKYGBgCgo6Ojogbm90ZQoKVGhlIGxvZyBsaXN0cyBhbGwgY29tbWl0cyBtYWRlIHRvIGEgcmVwb3NpdG9yeSBpbiByZXZlcnNlIGNocm9ub2xvZ2ljYWwgb3JkZXIsIHdoaWNoIGluY2x1ZGVzOgoKKiBhIGZ1bGwgNDAtY2hhcmFjdGVyIGlkZW50aWZpZXIgKGkuZS4sIHRoZSAiU0hBLTEgY2hlY2tzdW0iKSwgc3RhcnRpbmcgd2l0aCB0aGUgc2FtZSA3IGNoYXJhY3RlcnMgYXMgdGhlIHNob3J0IGlkZW50aWZpZXIgcHJpbnRlZCBieSB0aGUgYGdpdCBjb21taXRgIGNvbW1hbmQgd2UgdXNlZCBlYXJsaWVyCiogdGhlIGNvbW1pdCBhdXRob3IncyBuYW1lIGFuZCBlbWFpbCBhZGRyZXNzCiogdGhlIGRhdGUvdGltZSBzdGFtcCBvZiB3aGVuIGl0IHdhcyBjcmVhdGVkCiogdGhlIGNvbW1pdCBtZXNzYWdlIHBhc3NlZCB0byBHaXQKCjo6OgoKIyMjIFN1bW1hcnkKCjo6OiBzdWNjZXNzCgpBdCB0aGlzIHBvaW50IHlvdSd2ZSBzZWVuIGhvdyB0bwoKKiBpbml0aWFsaXplIGEgR2l0IHJlcG9zaXRvcnkKKiBhZGQgKHN0YWdlKSBhIGZpbGUgdG8gYmUgY29tbWl0dGVkCiogY29tbWl0IGEgZmlsZSB0byB0aGUgcmVwb3NpdG9yeQoKOjo6CgpUaGlzIGZpZ3VyZSBmcm9tIFtCbGlzY2hhayBldCBhbC4gKDIwMTgpXShodHRwczovL2pvdXJuYWxzLnBsb3Mub3JnL3Bsb3Njb21wYmlvbC9hcnRpY2xlP2lkPTEwLjEzNzEvam91cm5hbC5wY2JpLjEwMDQ2NjgpIHNob3dzIHRoYXQgcHJvY2VzcyBncmFwaGljYWxseS4KCjxicj4KCiFbXShpbWFnZXMvZ2l0X3dvcmtmbG93LnBuZyl7IGhlaWdodD03MCUgd2lkdGg9NzAlIH0KCioqKgoKIyBNYWtpbmcgY2hhbmdlcyB0byBhIGZpbGUKCkxldCdzIG5vdyBpbWFnaW5lIHlvdSB3YW50ZWQgdG8gcmV0dXJuIHRvIHRoZSBSIHNjcmlwdCB3ZSBjcmVhdGVkIGVhcmxpZXIgYW5kIGFkZCBzb21lIG1vcmUgbGluZXMgb2YgY29kZSwgb3IgbWFrZSBzb21lIGNoYW5nZXMgdG8gdGhlIGV4aXN0aW5nIGNvZGUuCgo8YnI+Cgo6OjogdGFzawoKQWRkIHRoZSBmb2xsb3dpbmcgbGluZXMgb2YgbmV3IGNvZGUgdG8gYHRlc3Rfc2NyaXB0LlJgIGFuZCBzYXZlIHRoZSBmaWxlIHdoZW4geW91IGFyZSBkb25lLgoKOjo6CgpgYGBzaAojIyBhbiBvcGVyYXRpb24KYSArIGIKYGBgCgohW10oaW1hZ2VzL1Jfc2NyaXB0X2FkZF8yLnBuZyl7IGhlaWdodD04MCUgd2lkdGg9ODAlIH0KCjxicj4KCjo6OiB0YXNrCgpDaGVjayBvbiB0aGUgc3RhdHVzIG9mIHlvdXIgcmVwby4KCjo6OgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBzdGF0dXMKYGBgCgoqKk91dHB1dCoqCgpgYGAKT24gYnJhbmNoIG1haW4KQ2hhbmdlcyBub3Qgc3RhZ2VkIGZvciBjb21taXQ6CiAgKHVzZSAiZ2l0IGFkZCA8ZmlsZT4uLi4iIHRvIHVwZGF0ZSB3aGF0IHdpbGwgYmUgY29tbWl0dGVkKQogICh1c2UgImdpdCByZXN0b3JlIDxmaWxlPi4uLiIgdG8gZGlzY2FyZCBjaGFuZ2VzIGluIHdvcmtpbmcgZGlyZWN0b3J5KQoJbW9kaWZpZWQ6ICAgdGVzdF9zY3JpcHQuUgoKbm8gY2hhbmdlcyBhZGRlZCB0byBjb21taXQgKHVzZSAiZ2l0IGFkZCIgYW5kL29yICJnaXQgY29tbWl0IC1hIikKYGBgCgpUaGlzIG91dHB1dCBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBpcyBvbmUgZmlsZSAoYHRlc3Rfc2NyaXB0LlJgKSB0aGF0IGhhcyBiZWVuIG1vZGlmaWVkLCBidXQgaW1wb3J0YW50bHksIG5vdGhpbmcgaGFzIHlldCBiZWVuIGFkZGVkIHRvIHRoZSBzdGFnaW5nIGFyZWEuIFRoaXMgaXMgd2hhdCB0aGUgbGFzdCBsaW5lIG9mIHRoZSBvdXRwdXQgaXMgdGVsbGluZyB1cy4KCjo6OiB0aXAKCkJlZm9yZSBhZGRpbmcgYSBmaWxlIHRvIHN0YWdpbmcsIGl0J3MgYSBnb29kIGlkZWEgdG8gaW5zcGVjdCB0aGUgY2hhbmdlcyB0aGF0IHdlcmUgbWFkZSB0byBpdC4gVG8gZG8gdGhpcyBpbiBHaXQsIHdlJ2xsIHVzZSBgZ2l0IGRpZmZgLCB3aGljaCBpcyBzaG9ydCBmb3IgImRpZmZlcmVuY2UiLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGRpZmYKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApkaWZmIC0tZ2l0IGEvdGVzdF9zY3JpcHQuUiBiL3Rlc3Rfc2NyaXB0LlIKaW5kZXggMDU5MjJlNS4uNGNkZjFhNyAxMDA2NDQKLS0tIGEvdGVzdF9zY3JpcHQuUgorKysgYi90ZXN0X3NjcmlwdC5SCkBAIC0xLDMgKzEsNiBAQAogIyMgYSB0ZXN0IHNjcmlwdAogYSA8LSAxCiBiIDwtIDIKKyMjIGFuIG9wZXJhdGlvbgorYSArIGIKKwpgYGAKCkhtbSwgdGhpcyBvdXRwdXQgaXMgZGVmaW5pdGVseSBhIGJpdCBjcnlwdGljLgoKKiBUaGUgZmlyc3QgbGluZSBpbmRpY2F0ZXMgdGhhdCB0aGUgR2l0IG91dHB1dCBpcyBzaW1pbGFyIHRvIHRoZSBVbml4IGBkaWZmYCBjb21tYW5kIGNvbXBhcmluZyB0aGUgb2xkIChgYS90ZXN0X3NjcmlwdC5SYCkgYW5kIG5ldyAoYGIvdGVzdF9zY3JpcHQuUmApIHZlcnNpb25zIG9mIHRoZSBmaWxlLiAgCiogVGhlIHNlY29uZCBsaW5lIGluZGljYXRlcyB3aGljaCB2ZXJzaW9ucyBvZiB0aGUgZmlsZSBHaXQgaXMgY29tcGFyaW5nIChpLmUuLCBgMDU5MjJlNWAgYW5kIGA0Y2RmMWE3YCBhcmUgdGhlaXIgdW5pcXVlIHZlcnNpb24tc3BlY2lmaWMgbGFiZWxzKS4gIAoqIFRoZSB0aGlyZCBhbmQgZm91cnRoIGxpbmVzIG9uY2UgYWdhaW4gc2hvdyB0aGUgbmFtZSBvZiB0aGUgZmlsZSBiZWluZyBjaGFuZ2VkIChgdGVzdF9zY3JpcHQuUmApLiAgCiogVGhlIHJlbWFpbmluZyBsaW5lcyBzaG93IHRoZSBhY3R1YWwgZGlmZmVyZW5jZXMgYW5kIHRoZSBsaW5lcyBvbiB3aGljaCB0aGV5IG9jY3VyOyB0aGUgYCtgIHNpZ24gaW4gdGhlIGZpcnN0IGNvbHVtbiBzaG93cyB0aGUgbGluZXMgdGhhdCB3ZXJlIGFkZGVkIG1vc3QgcmVjZW50bHkgKG5vdGUgdGhhdCB0aGUgbGFzdCBsaW5lIG9mIHRoZSBSIHNjcmlwdCBpcyBibGFuaykuCiAgICAKQWxsIG9mIHRoaXMgaXMgZ29vZCBpbmZvcm1hdGlvbiBhbmQgZXZlcnl0aGluZyBpcyBva2F5LgoKOjo6IHRhc2sKCkNvbW1pdCB0aGUgbmV3IGNoYW5nZXMgdG8gb3VyIFIgc2NyaXB0LgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGNvbW1pdCAtbSAiYWRkZWQgYW4gYWRkaXRpb24gb3BlcmF0aW9uIHRvIHRlc3QgUiBzY3JpcHQiCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKT24gYnJhbmNoIG1haW4KQ2hhbmdlcyBub3Qgc3RhZ2VkIGZvciBjb21taXQ6CiAgKHVzZSAiZ2l0IGFkZCA8ZmlsZT4uLi4iIHRvIHVwZGF0ZSB3aGF0IHdpbGwgYmUgY29tbWl0dGVkKQogICh1c2UgImdpdCByZXN0b3JlIDxmaWxlPi4uLiIgdG8gZGlzY2FyZCBjaGFuZ2VzIGluIHdvcmtpbmcgZGlyZWN0b3J5KQoJbW9kaWZpZWQ6ICAgdGVzdF9zY3JpcHQuUgoKbm8gY2hhbmdlcyBhZGRlZCB0byBjb21taXQgKHVzZSAiZ2l0IGFkZCIgYW5kL29yICJnaXQgY29tbWl0IC1hIikKYGBgCgo6Ojogbm90ZQoKV2UgZm9yZ290IHRvIGFkZCBvdXIgZmlsZSB0byB0aGUgc3RhZ2luZyBhcmVhLCBzbyBub3RoaW5nIGhhcHBlbmVkLiBHaXQgc3VnZ2VzdHMgdGhhdCB3ZSBlaXRoZXIgdXNlIGBnaXQgYWRkYCBhbmQvb3IgYGdpdCBjb21taXQgLWFgLiAKCjo6OgoKOjo6IHRhc2sKClVzZSBgZ2l0IGFkZGAgdG8gYWRkIHRoZSBmaWxlIHRvIHN0YWdpbmcgYW5kIHRoZW4gY29tbWl0IGl0LgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGFkZCB0ZXN0X3NjcmlwdC5SCiQgZ2l0IGNvbW1pdCAtbSAiYWRkZWQgYW4gYWRkaXRpb24gb3BlcmF0aW9uIHRvIHRlc3QgUiBzY3JpcHQiCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKW21haW4gMDdlYWFkNF0gYWRkZWQgYW4gYWRkaXRpb24gb3BlcmF0aW9uIHRvIHRlc3QgUiBzY3JpcHQKIDEgZmlsZSBjaGFuZ2VkLCAzIGluc2VydGlvbnMoKykKYGBgCgpPSywgaXQgbG9va3MgbGlrZSB0aGF0IHdvcmtlZCwgYnV0IGl0J3MgYSBnb29kIGlkZWEgdG8gY2hlY2sgb24gdGhlIHN0YXR1cyBvZiB0aGUgcmVwbyB0byBiZSBzdXJlLgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBzdGF0dXMKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApPbiBicmFuY2ggbWFpbgpub3RoaW5nIHRvIGNvbW1pdCwgd29ya2luZyB0cmVlIGNsZWFuCmBgYAoKOjo6IHN1Y2Nlc3MKCkV2ZXJ5dGhpbmcgc2VlbXMgdG8gYmUgaW4gd29ya2luZyBvcmRlci4KCjo6OgoKOjo6IHRpcAoKT25jZSBhZ2Fpbiwgd2UgY2FuIGNoZWNrIG91dCB0aGUgaGlzdG9yeSBvZiB3aGF0IHdlJ3ZlIGRvbmUgc28gZmFyLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGxvZwpgYGAKCioqT3V0cHV0KioKCmBgYHNoCmNvbW1pdCAwN2VhYWQ0YjJmY2JlNGJlNzA2OGM0NzYxMmRjYzRmM2Y3YzYzNzNkIChIRUFEIC0+IG1haW4pCkF1dGhvcjogRmlyc3QgTGFzdCA8ZW1haWxAZG9tYWluLmVkdT4KRGF0ZTogICBGcmkgSmFuIDEzIDA5OjMzOjMyIDIwMjMgLTA4MDAKCiAgICBhZGRlZCBhbiBhZGRpdGlvbiBvcGVyYXRpb24gdG8gdGVzdCBSIHNjcmlwdAoKY29tbWl0IDVlNDAxODMxYTkyY2Y5ZTY5ODBkMGVlNzhhMTk5NjZkNmIzMTBiNzgKQXV0aG9yOiBGaXJzdCBMYXN0IDxlbWFpbEBkb21haW4uZWR1PgpEYXRlOiAgIEZyaSBKYW4gMTMgMDk6Mzk6MzIgMjAyMyAtMDgwMAoKICAgIGNyZWF0ZWQgdGVzdCBSIHNjcmlwdApgYGAKCk5vdyB3ZSBjYW4gc2VlIGJvdGggb2Ygb3VyIGNvbW1pdHMsIHdpdGggdGhlIG1vc3QgcmVjZW50IG9uZSBhdCB0aGUgdG9wLgoKOjo6IHRhc2sKCkFkZCBhbm90aGVyIG9wZXJhdGlvbiB0byB5b3VyIFIgc2NyaXB0IHdpdGggdGhlIGZvbGxvd2luZyBsaW5lcyBvZiBjb2RlIGFuZCBzYXZlIHRoZSBmaWxlIHdoZW4gZG9uZS4gKEZvciBub3cgaWdub3JlIHRoZSBmYWN0IHRoYXQgdGhpcyBjb2RlIGlzIHByb2JsZW1hdGljLS13ZSdsbCByZXR1cm4gdG8gdGhhdCBsYXRlci4pCgo6OjoKCmBgYHNoCiMjIGFub3RoZXIgb3BlcmF0aW9uCihhICsgYikgLyAwCmBgYAoKIVtdKGltYWdlcy9SX3NjcmlwdF9hZGRfMy5wbmcpeyBoZWlnaHQ9ODAlIHdpZHRoPTgwJSB9Cgo8YnI+Cgo6OjogdGFzawoKQWRkIHRoaXMgZmlsZSBhbmQgY29tbWl0IGl0LgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGFkZCB0ZXN0X3NjcmlwdC5SCiQgZ2l0IGNvbW1pdCAtbSAiYWRkZWQgYSBkaXZpc2lvbiBvcGVyYXRpb24gdG8gUiB0ZXN0IHNjcmlwdCIKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApbbWFpbiAxN2MxYTc0XSBhZGRlZCBhIGRpdmlzaW9uIG9wZXJhdGlvbiB0byBSIHRlc3Qgc2NyaXB0CiAxIGZpbGUgY2hhbmdlZCwgMiBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0pCmBgYAoKKioqCgojIFJldmlld2luZyBmaWxlIGhpc3RvcnkKCk9uZSBvZiB0aGUgbWFqb3IgYWR2YW50YWdlcyB0byB1c2luZyBhIGZvcm1hbCB2ZXJzaW9uIGNvbnRyb2wgc3lzdGVtIGxpa2UgR2l0IGlzIHRoYXQgeW91IGNhbiBnbyBiYWNrIGluIHRpbWUgYW5kIGV4YW1pbmUgY2hhbmdlcyB0aGF0IHdlcmUgbWFkZSB0byBmaWxlcy4gV2Ugc2F3IHByZXZpb3VzbHkgdGhhdCB3ZSBjYW4gdXNlIGBnaXQgZGlmZmAgdG8gaW5zcGVjdCB0aGUgY2hhbmdlcyB0aGF0IHdlcmUgbWFkZSB0byBhIHN0YWdlZCBmaWxlLiBIZXJlIHdlJ2xsIGV4cGFuZCB0aGF0IGZ1bmN0aW9uYWxpdHkgdG8gbG9vayBiYWNrIGZ1cnRoZXIgaW4gdGltZS4KCjxicj4KCjo6OiB0YXNrCgpFeGFtaW5lIHRoZSBjaGFuZ2VzIHRvIG91ciBSIHNjcmlwdCB3aXRoIGBnaXQgZGlmZmAuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgZGlmZiB0ZXN0X3NjcmlwdC5SCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKJApgYGAKCjo6OiBub3RlCgpJbiB0aGlzIGNhc2UgdGhlcmUgaGF2ZSBiZWVuIG5vIG5ldyBjaGFuZ2VzIHRvIG91ciBmaWxlLCBzbyB0aGUgb3V0cHV0IGlzIGJsYW5rLiAKCjo6OgoKR2l0IHJlZmVycyB0byB0aGUgbW9zdCByZWNlbnQgdmVyc2lvbiBvZiBhIGZpbGUgYXMgaXRzIGBIRUFEYC4gRWFybGllciB2ZXJzaW9ucyBvZiBhIGZpbGUgYXJlIHJlZmVyZW5jZWQgd2l0aCB0aGUgdGlsZGUgYH5gIGFuZCBhbiBpbnRlZ2VyLCBzdWNoIHRoYXQgYEhFQUR+MWAgaXMgdGhlIHZlcnNpb24gdGhhdCBpbW1lZGlhdGVseSBwcmVjZWRlcyB0aGUgY3VycmVudCB2ZXJzaW9uLiBTaW1pbGFybHksIGBIRUFEfjEwYCByZWZlcnMgdG8gdGhlIHZlcnNpb24gMTAgc3RlcHMgcHJpb3IgdG8gdGhlIGN1cnJlbnQgdmVyc2lvbi4gCgo6OjogdGlwCgpXZSBjYW4gdXNlIGBnaXQgZGlmZiBIRUFEIGZpbGVuYW1lYCB0byBpbnNwZWN0IGNoYW5nZXMgdG8gdGhlIGN1cnJlbnQgdmVyc2lvbiwgYnV0IGluIHRoaXMgY2FzZSBpdCB3aWxsIHlpZWxkIHRoZSBzYW1lIHRoaW5nIGFzIGBnaXQgZGlmZiBmaWxlbmFtZWAuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgZGlmZiBIRUFEIHRlc3Rfc2NyaXB0LlIKYGBgCgoqKk91dHB1dCoqCgpgYGBzaAokCmBgYAoKOjo6IHRhc2sKClRha2UgYSBwZWVrIGJhY2sgYXQgdGhlIHZlcnNpb24gcHJpb3IgdG8geW91ciBjdXJyZW50IHZlcnNpb24gYW5kIGNvbXBhcmUgdGhlaXIgZGlmZmVyZW5jZXMuCgo6OjoKCioqSW5wdXQqKgoKYGBgc2gKJCBnaXQgZGlmZiBIRUFEfjEgdGVzdF9zY3JpcHQuUgpgYGAKCioqT3V0cHV0KioKCmBgYHNoCmRpZmYgLS1naXQgYS90ZXN0X3NjcmlwdC5SIGIvdGVzdF9zY3JpcHQuUgppbmRleCA0Y2RmMWE3Li5mYWVkNDQ3IDEwMDY0NAotLS0gYS90ZXN0X3NjcmlwdC5SCisrKyBiL3Rlc3Rfc2NyaXB0LlIKQEAgLTMsNCArMyw1IEBACiAjIyBhIHRlc3Qgc2NyaXB0CiBhIDwtIDEKIGIgPC0gMgogIyMgYW4gb3BlcmF0aW9uCiBhICsgYgotCisjIyBhbm90aGVyIG9wZXJhdGlvbgorKGEgKyBiKSAvIDAKYGBgCgpIZXJlIHdlIGNhbiBzZWUgdGhhdCB3ZSBkZWxldGVkIHRoZSBibGFuayBsaW5lIGF0IHRoZSBlbmQgb2YgdGhlIHNjcmlwdCBhcyBpbmRpY2F0ZWQgYnkgdGhlIGAtYCwgYW5kIHJlcGxhY2VkIGl0IHdpdGggdGhlIDIgbGluZXMgYmVnaW5uaW5nIHdpdGggYCMjIGFub3RoZXIgb3BlcmF0aW9uYC4KCjo6OiB0YXNrCgpHbyBiYWNrIGFuZCBsb29rIGF0IHRoZSBjaGFuZ2VzIHJlbGF0aXZlIHRvIHlvdXIgZmlyc3QgdmVyc2lvbiBvZiB0aGUgc2NyaXB0LgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGRpZmYgSEVBRH4yIHRlc3Rfc2NyaXB0LlIKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApkaWZmIC0tZ2l0IGEvdGVzdF9zY3JpcHQuUiBiL3Rlc3Rfc2NyaXB0LlIKaW5kZXggMDU5MjJlNS4uZmFlZDQ0NyAxMDA2NDQKLS0tIGEvdGVzdF9zY3JpcHQuUgorKysgYi90ZXN0X3NjcmlwdC5SCkBAIC0xLDMgKzEsNyBAQAogIyMgYSB0ZXN0IHNjcmlwdAogYSA8LSAxCiBiIDwtIDIKKyMjIGFuIG9wZXJhdGlvbgorYSArIGIKKyMjIGFub3RoZXIgb3BlcmF0aW9uCisoYSArIGIpIC8gMApgYGAKCkhlcmUgeW91IGNhbiBzZWUgdGhhdCB0aGUgZmlyc3QgdmVyc2lvbiBoYWQgb25seSAzIGxpbmVzIG9mIGNvZGUgYW5kIHNpbmNlIHRoZW4gd2UndmUgYWRkZWQgNCBuZXcgbGluZXMgb2YgY29kZS4KCioqKgoKIyBSZWNvdmVyaW5nIGFuIG9sZCB2ZXJzaW9uCgpMZXQncyBpbWFnaW5lIHdlIHdlcmVuJ3QgaGFwcHkgd2l0aCB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIG91ciB0ZXN0IHNjcmlwdCBiZWNhdXNlIHBlcmhhcHMgd2UgYnJva2Ugc29tZXRoaW5nIG9yIHdlIHNpbXBseSBjYW4ndCBnZXQgaXQgdG8gd29yay4gQmVjYXVzZSBHaXQgaXMgYSB2ZXJzaW9uIGNvbnRyb2wgc3lzdGVtLCB3ZSBjYW4gZWFzaWx5IHJlc3RvcmUgZmlsZXMgdG8gYSBzdGF0ZSB0aGV5IHdlcmUgaW4gYXQgc29tZSBwcmV2aW91cyBjb21taXQuIAoKOjo6IHRpcAoKV2UgY2FuIHVzZSBgZ2l0IGNoZWNrb3V0YCB0byByZXN0b3JlIGEgcHJldmlvdXMgdmVyc2lvbiBvZiBhIGZpbGUgYnkgcmVmZXJlbmNpbmcgaXQgd2l0aCBgSEVBRH5uYCB3aGVyZSBgbmAgcmVmZXJzIHRvIHRoZSB2ZXJzaW9uIHdlJ2QgbGlrZS4KCjo6OgoKVGhlIGxhc3Qgb3BlcmF0aW9uIHdlIGFkZGVkIHRvIG91ciBmaWxlIHdpbGwgY2xlYXJseSBjcmVhdGUgc29tZSBwcm9ibGVtcyBmb3IgdXMgYmVjYXVzZSBpdCBjb250YWlucyBhIGRpdmlkZS1ieS16ZXJvLiAKCjo6OiB0YXNrCgpMZXQncyByZXZlcnQgb3VyIHNjcmlwdCB0byB0aGUgdmVyc2lvbiBqdXN0IHByaW9yIHRvIHRoYXQgd2hlbiBldmVyeXRoaW5nIHdhcyB3b3JraW5nIHByb3Blcmx5LgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IGNoZWNrb3V0IEhFQUR+MSB0ZXN0X3NjcmlwdC5SCmBgYAoKKipPdXRwdXQqKgoKYGBgc2gKVXBkYXRlZCAxIHBhdGggZnJvbSBiNDc4ODE2CmBgYAoKSG1tLiBUaGF0IGRpZCBzb21ldGhpbmcsIGJ1dCBpdCdzIG5vdCBpbW1lZGlhdGVseSBjbGVhciBpZiBpdCB3YXMgd2hhdCB3ZSB3YW50ZWQuCgo6OjogdGlwCgpZb3UgY2FuIHVzZSBgY2F0YCB0byBpbnNwZWN0IGEgZmlsZSdzIGNvbnRlbnRzIGFuZCBzZWUgaWYgaXQgd2FzIGluZGVlZCBzd2l0Y2hlZCBiYWNrIHRvIHRoZSBwcmlvciB2ZXJzaW9uLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgY2F0IHRlc3Rfc2NyaXB0LlIKYGBgCgoqKk91dHB1dCoqCgpgYGBzaAojIyBhIHRlc3Qgc2NyaXB0CmEgPC0gMQpiIDwtIDIKIyMgYW4gb3BlcmF0aW9uCmEgKyBiCmBgYAoKOjo6IHN1Y2Nlc3MKCk91ciBzY3JpcHQgaXMgYmFjayB0byB0aGUgcHJldmlvdXMgd29ya2luZyB2ZXJzaW9uLiAKCjo6OgoKOjo6IG5vdGUKCllvdXIgb3BlbiBSIHNjcmlwdCBpbiBSU3R1ZGlvIHNob3VsZCBoYXZlIGFsc28gcmV2ZXJ0ZWQgdG8gdGhlIHByZXZpb3VzIHZlcnNpb24uCgo6OjoKCiFbXShpbWFnZXMvUl9zY3JpcHRfYWRkXzIucG5nKXsgaGVpZ2h0PTgwJSB3aWR0aD04MCUgfQoKPGJyPgoKOjo6IHRhc2sKCkNoZWNrIG9uIHRoZSBzdGF0dXMgb2YgdGhlIGRpcmVjdG9yeS4KCjo6OgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBzdGF0dXMKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApPbiBicmFuY2ggbWFpbgpDaGFuZ2VzIHRvIGJlIGNvbW1pdHRlZDoKICAodXNlICJnaXQgcmVzdG9yZSAtLXN0YWdlZCA8ZmlsZT4uLi4iIHRvIHVuc3RhZ2UpCgltb2RpZmllZDogICB0ZXN0X3NjcmlwdC5SCgpgYGAKCjo6OiB0aXAKCk9uY2UgYWdhaW4gR2l0IGlzIHRlbGxpbmcgdXMgdGhhdCB3ZSBzdGlsbCBuZWVkIHRvIGNvbW1pdCB0aGUgY2hhbmdlcyB0byBvdXIgZmlsZSwgc28gbGV0J3MgZG8gdGhhdC4KCjo6OgoKKipJbnB1dCoqCgpgYGBzaAokIGdpdCBjb21taXQgLW0gImNoYW5nZWQgdGVzdCBzY3JpcHQgYmFjayB0byB2ZXJzaW9uIGJlZm9yZSBkaXZpc2lvbiBvcCIKYGBgCgoqKk91dHB1dCoqCgpgYGBzaApbbWFpbiAyNzQzYjQ3XSBjaGFuZ2VkIHRlc3Qgc2NyaXB0IGJhY2sgdG8gdmVyc2lvbiBiZWZvcmUgZGl2aXNpb24gb3AKIDEgZmlsZSBjaGFuZ2VkLCAxIGluc2VydGlvbigrKSwgMiBkZWxldGlvbnMoLSkKYGBgCgo6OjogdGFzawoKTGFzdGx5LCBydW4gYGdpdCBzdGF0dXNgIGFnYWluIHRvIG1ha2Ugc3VyZSB3ZSd2ZSBnb3R0ZW4gZXZlcnl0aGluZyBjbGVhbmVkIHVwLgoKOjo6CgoqKklucHV0KioKCmBgYHNoCiQgZ2l0IHN0YXR1cwpgYGAKCioqT3V0cHV0KioKCmBgYHNoCk9uIGJyYW5jaCBtYWluCm5vdGhpbmcgdG8gY29tbWl0LCB3b3JraW5nIHRyZWUgY2xlYW4KYGBgCgo6Ojogc3VjY2VzcwoKRXZlcnl0aGluZyBzZWVtcyB0byBiZSBpbiBwcm9wZXIgd29ya2luZyBvcmRlciEKCjo6OgoKCioqKgoKIyBHaXQgY2xpZW50cwoKSXQgY2FuIGJlIHRyaWNreSB0byBsZWFybiBhbGwgb2YgdGhlIGlucyBhbmQgb3V0cyBvZiBHaXQsIGVzcGVjaWFsbHkgd2hlbiB0eXBpbmcgYSBidW5jaCBvZiBjcnlwdGljIHRleHQgaW50byB0aGUgY29tbWFuZCBsaW5lLiBGb3J0dW5hdGVseSwgdGhlcmUgYXJlIHNldmVyYWwgZ3JhcGhpY2FsIHVzZXIgaW50ZXJmYWNlcyAoR1VJcykgZm9yIEdpdCB0aGF0IGhlbHAgdmlzdWFsaXplIHdoYXQgaXMgYmVpbmcgZG9uZS4gV2UnbGwgc2VlIG5leHQgdGltZSB0aGF0IFJTdHVkaW8gb2ZmZXJzIGEgcmVsYXRpdmVseSBzaW1wbGUgaW50ZXJmYWNlIHRvIEdpdCwgYnV0IHRoZXJlIGFyZSBvdGhlcnMgdGhhdCBoYXZlIG11Y2ggbW9yZSBmdW5jdGlvbmFsaXR5LiBJIHN1Z2dlc3QgcmVhZGluZyBKZW5ueSBCcnlhbidzIHRyZWF0bWVudCBvZiB0aGVtIFtoZXJlXShodHRwczovL2hhcHB5Z2l0d2l0aHIuY29tL2dpdC1jbGllbnQuaHRtbCkuCgoqKioKCiMgRW5kbm90ZQoKOjo6IHN1Y2Nlc3MKCllvdSd2ZSBub3cgZG9uZSB0aGUgZm9sbG93aW5nOgoKKiBJbml0aWFsaXplZCBhIEdpdCByZXBvc2l0b3J5CiogU3RhZ2VkIGFuZCBhZGRlZCBmaWxlcyB0byBiZSB0cmFja2VkCiogQ29tbWl0dGVkIGEgZmlsZSB0byB0aGUgR2l0IGhpc3RvcnkKKiBDb21wYXJlZCBjaGFuZ2VzIHRvIHByZXZpb3VzIHZlcnNpb25zIG9mIGEgZmlsZQoqIFJldmVydGVkIGEgZmlsZSBiYWNrIHRvIGEgcHJldmlvdXMgdmVyc2lvbgoKOjo6Cg==