Background
This document demonstrates some of the workflows we saw in class here.
All of these workflows have some pros and cons. It’s up to you and your
team as to which one you adopt. Also note that your preferences might
change, depending on the composition of your team and the task at
hand.
Centralized workflow
A centralized workflow uses a single repo for all changes to the
project. All team members pull from and push to the same repo.
Imagine Juan sits down to work on his new testing
project that Mary and Aisha have been working on as well. The first
thing Juan does is pull from the remote repository.

Everything is up to date, so Juan works on the R script for doing
some simple math operations. He adds 2 lines to the script to
demonstrate a subtraction operation, and then saves his changes.

After basking in the glow of his wonderful new code, Juan decides he
should take a break for awhile, so he commits his changes.


The last step before Juan takes a break is to push
his local commit up to the shared repo on GitHub.

Oops–that did not go as expected!
What went wrong? Git is telling us that there are some changes on the
remote repo that Juan does not have in his local copy. How did that
happen? It turns out that Mary was also working on the project at the
same time as Juan. In between the time that Juan sat down and pulled the
changes from the remote repo (there were none at the time), Mary made
some changes to the script, committed them, and pushed them to the
remote repo. In looking at the error message from Git, Juan notices that
it suggests he should pull the changes and integrate
them into his own script.
Juan goes ahead and pulls Mary’s recent changes to his local repo,
which issues another warning about a so-called merge conflict
in R/00_testing.R
that Juan will have to fix.

Merge conflicts
When Juan inspects his version of 00_testing.R
he sees
that Git has added some information to the script, which brackets the
new changes that both Juan and Mary made:
<<<<<<< HEAD
## subtraction
num - den
=======
## addition
num + demo
>>>>>>> d1ab55e3cf1979efd0a61954305f742cfbb38e11

You can think of these new lines as “conflict dividers”.
The =======
line is the center of the conflict.
Everything between <<<<<<< HEAD
and
=======
is content that exists in the local repo
to which the HEAD
ref is pointing.
Everything between =======
and
>>>>>>> d1ab55e3cf1979efd0a61954305f742cfbb38e11
is content that is present in the remote repo.
At this point, it would be a good idea for Juan to contact Mary and
find out what her plans are, so he can avoid this problem in the
future.
After confirming that Mary is done making changes for awhile, Juan
can return to resolving the current merge conflict. To do so, Juan
inspects the new changes that Mary made and decides if he wants to merge
them into his version of the file, or whether he wants to discard them.
In this case, Juan is happy with the new addition operation that Mary
made, so he accepts them by simply deleting the conflict dividers.

Now Juan can commit his resolved changes and push them to the remote
repo.


Now Juan is all set on his side, but Mary should make sure that she
pulls Juan’s changes to her local repo before she starts working on the
script again.
This scenario does not necessarily require two or more
collaborators.
For example, Mark knows from personal experience that someone can do
some work on a computer in their office, commit those changes, and then
forget to push them before heading home. Upon arriving home, they could
pull their changes to their laptop, make additional changes, commit
them, and then push them to the remote repo. Upon returning back to the
office, they can encounter problems with committing and pushing those
changes they forgot about the day before.
Feature branch workflow
The feature branch workflow is designed around multiple
branches within a repo. These branches can contain copies of
files on the main branch, and are typically used for
the development of specific features.
Create a branch
Let’s look at two different ways to create a new branch.
Review these instructions for creating a new branch from within
GitHub, but don’t follow through with them. We’ll instead use the second
approach shown below.
The first approach is from GitHub itself. To do so, navigate to the
remote repo and click on the button marked main in the
upper left. This will open a dialogue box with a line for you to find or
create a branch. Type the name of the new branch (e.g., “develop”) and
then hit “return”.

The second option for creating a new branch, which we’ll follow here,
is to do so from within RStudio.
Click on the purple button with 2 rectangles and a diamond in the
Git pane, which will bring up a dialogue window where
you can enter the name of your new branch (we’ll call it “develop”).
Press the Create button when you’re done.

At this point, you’ll see a message window from Git with the
following information:
- lines 1-2: Git created a new branch and switched over to it with
git checkout -B develop
- lines 3-10: Git pushed all of your local files to a newly created
develop
branch on the remote GitHub repo.
Git is also suggesting you create a so-called pull request
to move changes from the develop branch into the
main branch by navigating to your remote repo on
GitHub.

If you navigate back to the testing repo on GitHub
and refresh your browser, you will see that there are now 2 branches
there: main and develop.

Let’s go ahead and make a small change to our R test script (note
that the following assumes you have not already made these changes in
the above section on Centralized workflow). After doing
so, we’ll commit and push the changes on the develop
branch up to our remote repo on GitHub.
Add the following 2 lines of code to the 00_testing.R
script. Save the changes when you are finished.

Add the file to staging and commit it. Include a short but
informative commit message and click the Commit
button when ready.

Click on the green uparrow next to “Push” to push your changes to
GitHub.
RStudio will pop open a window echoing your push command and the
destination.

Pull requests
Now let’s take the advice we received earlier about creating a “pull
request” (or “PR” for short). You can think of a pull request as an
offer of support. In effect, someone who submits a pull request is
kindly requesting that the repo owner pull new changes into their
repo.
Navigate to your testing repo on GitHub.
Upon arriving there, we see a message that “develop
had recent pushes less than a minute ago”. To the right of that is a
green button marked Compare & pull request.

Click on the green Compare & pull request
button, which will take you to a page to open a pull request.
At the top you will see some information about the branches from
which and to where the changes will be merged, along with a note about
the branches being okay to merge. If you scroll down the page, you’ll
see the changes that were committed, when they were made, and who did
it.

If your pull request involves multiple files, features, etc, it’s a
good idea to include some additional information in the comment box
(this can include Markdown flavored text).
Click on the green Create pull request button,
which will take you to another page where you can review any comments
(here there are none) and merge the pull request.
In the middle of the page, you’ll see a note about This
branch has no conflicts with the base branch and a green button
labeled Merge pull request.
Go ahead and push that button.

At this point, the window will switch over to asking you to confirm
the merge.
Go ahead and click on the green Confirm merge
button.

After doing so, GitHub will now report Pull request
successfully merged and closed (you’ll also notice that the
green Open oval below the name of the pull request has
changed to a purple Merged oval). GitHub also tells you
that “You’re all set–the develop branch can be safely
deleted.”

If your branch was created solely for the purpose of working on a
specific feature, then you can go ahead and delete it. If, however, you
want to maintain a development (or other) branch, then you can just
ignore this message and keeping working on it as well.
Forking workflow
Recall that a forking workflow is commonly used when a developer is
not a member of the project/organization on GitHub. This
workflow allows the developer to work with a copy of the owner’s repo
and potentially submit a pull request for the owner to consider adopting
the changes.
Step 1: Fork the repo

To fork a repo, navigate to its location on GitHub and look for the
Fork button in the upper right. Press that button,
which will bring up a dialogue box asking you where you would like to
fork the repo. Click on the user or organization where you’d like to
fork the repo and GitHub will do the rest.

When you click on the Fork button, GitHub will open
a page that looks similar to when you create a new repo.
Click the green Create fork button to proceed.

You will now see a new forked version of the original repository with
some information in the upper left about its location and from where it
came. You’ll also see some information above the repo contents about the
current branch being up to date with the “upstream” source.

In the not so distant past, you had to use Git via the command line
to specify where the “upstream” repo of a fork was and then “fetch” any
changes. GitHub has now streamlined that process by providing a “sync
fork” button to do so (see below).

Step 2: Clone the repo

Clone the remote GitHub repo to a local repo by creating a new
project in RStudio based upon your newly forked repo. Click here
if you need a reminder as to how to do that.
Step 3: Add remote repo

At this point, your local copy of the remote repo can only pull
changes from your remote at
https://github.com/USERNAME/ex-fork
where USERNAME
is your GitHub username. Unfortunately
there is no way to update your remote repo directly from the owner’s
repo at
https://github.com/FISH549/ex-fork
.
Instead, we have to set up our local repo to pull changes from the
owner’s remote repo and then we can push those up to our remote copy. By
convention, we will refer to the owner’s repo as the
upstream
repo, but you could give it any name.
At this point you have 2 options for adding the upstream
repo.
Option 1: Command line
Click on the Terminal tab in your RStudio console
window and type (or copy/paste) the following Git command:
git remote add upstream https://github.com/FISH549/ex-fork
Option 2: RStudio
Open up your project in RStudio and click on the “New branch” button
in the Git pane (i.e., the button with the 2 purple
rectangles and a diamond).

Click on the button labeled “Add remote…”.

In the “Remote Name:” box, type upstream
.
In the “Remote URL:” box, enter the name of the
owner’s repo you forked in Step 1:
https://github.com/FISH549/ex-fork
(you can copy/paste if
you’d like).
When you are finished, click the Add
button.

Click on the Cancel button (don’t worry, everything
is still OK).

Now you need to verify that the remote upstream
is set
up properly. To do so, click on the Terminal tab in
your Console pane and type this:
$ git remote -v
which should return the following, where USERNAME
is
your user name.
origin https://github.com/USERNAME/ex-fork (fetch)
origin https://github.com/USERNAME/ex-fork (push)
upstream https://github.com/FISH549/ex-fork (fetch)
upstream https://github.com/FISH549/ex-fork (push)

Step 4: Make local changes

Now you are ready to make any changes you’d like to the files or
folders in your local repo.
Before doing so, make sure to pull
any changes that might have been made to the owner’s
upstream
remote.
To do so, again navigate to the Terminal tab in
RStudio and type:
$ git pull upstream main --ff-only
If nothing has changed, you’ll see a message like this:
From https://github.com/FISH549/ex-fork
* branch main -> FETCH_HEAD
* [new branch] main -> upstream/main
Already up to date.
Setting the local branch
If you examine your forked copy of the repo on GitHub, you’ll notice
that it contains 2 branches: main and
develop. However, if you inspect the local branches in
your current project in RStudio, you’ll see that only
main exists there.

To set the local branch to develop (where we’d like
to do our work), click on develop under (REMOTE:
ORIGIN), which will bring up a message box from Git informing you that
you’ve created and switched over to a new branch called
develop.


Close the window and you will see that the branch name in the
Git pane of RStudio is set to
develop.
If you again click on the develop button it will now
show that you can track the develop and
main branches on
You can also track the main branch on the remote
upstream (located at
https://github.com/FISH549/ex-fork
)

Let’s create a new file in our local repo so we have something to
commit and push to our own remote repo, and then ultimately submit it as
a pull request to the original repo’s owner (here
FISH549
).
Go ahead and make a simple R script and commit it (I’m called mine
simple_addition.R
).

When you’re happy with your script, go ahead and commit it.

Step 5: Push to GitHub

Now it’s time to push your simple script to your own remote located
at
https://github.com/USERNAME/ex-fork
Click the green uparrow to push your new script to GitHub.

Step 6: Submit a pull request

Navigate to your forked repo on GitHub where you’ll see a message
about this branch having a recent push and a new green button labeled
Compare & pull request.

Open a pull request by clicking on the green Compare &
pull request button.
This will take you to the standard page for a pull request, just as
we saw in the feature branch
workflow above. In this case, however, there is additional
information about 2 things:

It’s good practice to give your pull request an informative title and
include some additional information about the substance of the pull
request, so that the owner of the original repo has some understanding
of what you’ve done.
Give your pull request a title and description. When ready, click on
the green Create pull request button, which will take
you to a page showing the details of your pull request.


No you just have to wait for the repo’s owner to review the pull
request and either accept it as is, or come back to you with additional
comments or requests for changes.
LS0tCnRpdGxlOiAiRXhhbXBsZXMgb2YgY29sbGFib3JhdGl2ZSB3b3JrZmxvd3MiCmRhdGU6ICIyNCBKYW51YXJ5IDIwMjUiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlCiAgICBjc3M6IC4uL2xlY3R1cmVfaW5zdC5jc3MKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCjxicj4KCiMgQmFja2dyb3VuZAoKVGhpcyBkb2N1bWVudCBkZW1vbnN0cmF0ZXMgc29tZSBvZiB0aGUgd29ya2Zsb3dzIHdlIHNhdyBpbiBjbGFzcyBbaGVyZV0oaHR0cHM6Ly9maXNoNTQ5LmdpdGh1Yi5pby93ZWJzaXRlL2xlY3R1cmVzL3dlZWtfMDMvbGVjXzA4X3dvcmtmbG93cy5odG1sKS4gQWxsIG9mIHRoZXNlIHdvcmtmbG93cyBoYXZlIHNvbWUgcHJvcyBhbmQgY29ucy4gSXQncyB1cCB0byB5b3UgYW5kIHlvdXIgdGVhbSBhcyB0byB3aGljaCBvbmUgeW91IGFkb3B0LiBBbHNvIG5vdGUgdGhhdCB5b3VyIHByZWZlcmVuY2VzIG1pZ2h0IGNoYW5nZSwgZGVwZW5kaW5nIG9uIHRoZSBjb21wb3NpdGlvbiBvZiB5b3VyIHRlYW0gYW5kIHRoZSB0YXNrIGF0IGhhbmQuCgoqKioKCiMgQ2VudHJhbGl6ZWQgd29ya2Zsb3cKCkEgY2VudHJhbGl6ZWQgd29ya2Zsb3cgdXNlcyBhIHNpbmdsZSByZXBvIGZvciBhbGwgY2hhbmdlcyB0byB0aGUgcHJvamVjdC4gQWxsIHRlYW0gbWVtYmVycyBwdWxsIGZyb20gYW5kIHB1c2ggdG8gdGhlIHNhbWUgcmVwby4KCkltYWdpbmUgSnVhbiBzaXRzIGRvd24gdG8gd29yayBvbiBoaXMgbmV3ICoqdGVzdGluZyoqIHByb2plY3QgdGhhdCBNYXJ5IGFuZCBBaXNoYSBoYXZlIGJlZW4gd29ya2luZyBvbiBhcyB3ZWxsLiBUaGUgZmlyc3QgdGhpbmcgSnVhbiBkb2VzIGlzICoqcHVsbCoqIGZyb20gdGhlIHJlbW90ZSByZXBvc2l0b3J5LgoKPGJyPgoKIVtdKGltYWdlcy9jZW50cmFsX2dpdF9wdWxsLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgpFdmVyeXRoaW5nIGlzIHVwIHRvIGRhdGUsIHNvIEp1YW4gd29ya3Mgb24gdGhlIFIgc2NyaXB0IGZvciBkb2luZyBzb21lIHNpbXBsZSBtYXRoIG9wZXJhdGlvbnMuIEhlIGFkZHMgMiBsaW5lcyB0byB0aGUgc2NyaXB0IHRvIGRlbW9uc3RyYXRlIGEgc3VidHJhY3Rpb24gb3BlcmF0aW9uLCBhbmQgdGhlbiBzYXZlcyBoaXMgY2hhbmdlcy4KCjxicj4KCiFbXShpbWFnZXMvY2VudHJhbF9uZXdfbGluZXNfY29kZS5wbmcpeyB3aWR0aD03MCUgfQoKPGJyPgoKQWZ0ZXIgYmFza2luZyBpbiB0aGUgZ2xvdyBvZiBoaXMgd29uZGVyZnVsIG5ldyBjb2RlLCBKdWFuIGRlY2lkZXMgaGUgc2hvdWxkIHRha2UgYSBicmVhayBmb3IgYXdoaWxlLCBzbyBoZSBjb21taXRzIGhpcyBjaGFuZ2VzLgoKPGJyPgoKIVtdKGltYWdlcy9jZW50cmFsX2NvbW1pdF8xLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgohW10oaW1hZ2VzL2NlbnRyYWxfY29tbWl0XzIucG5nKXsgd2lkdGg9NzAlIH0KCjxicj4KClRoZSBsYXN0IHN0ZXAgYmVmb3JlIEp1YW4gdGFrZXMgYSBicmVhayBpcyB0byAqKnB1c2gqKiBoaXMgbG9jYWwgY29tbWl0IHVwIHRvIHRoZSBzaGFyZWQgcmVwbyBvbiBHaXRIdWIuCgo8YnI+CgohW10oaW1hZ2VzL2NlbnRyYWxfcHVzaF9mYWlsLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgpPb3BzLS10aGF0IGRpZCBub3QgZ28gYXMgZXhwZWN0ZWQhCgpXaGF0IHdlbnQgd3Jvbmc/IEdpdCBpcyB0ZWxsaW5nIHVzIHRoYXQgdGhlcmUgYXJlIHNvbWUgY2hhbmdlcyBvbiB0aGUgcmVtb3RlIHJlcG8gdGhhdCBKdWFuIGRvZXMgbm90IGhhdmUgaW4gaGlzIGxvY2FsIGNvcHkuIEhvdyBkaWQgdGhhdCBoYXBwZW4/IEl0IHR1cm5zIG91dCB0aGF0IE1hcnkgd2FzIGFsc28gd29ya2luZyBvbiB0aGUgcHJvamVjdCBhdCB0aGUgc2FtZSB0aW1lIGFzIEp1YW4uIEluIGJldHdlZW4gdGhlIHRpbWUgdGhhdCBKdWFuIHNhdCBkb3duIGFuZCBwdWxsZWQgdGhlIGNoYW5nZXMgZnJvbSB0aGUgcmVtb3RlIHJlcG8gKHRoZXJlIHdlcmUgbm9uZSBhdCB0aGUgdGltZSksIE1hcnkgbWFkZSBzb21lIGNoYW5nZXMgdG8gdGhlIHNjcmlwdCwgY29tbWl0dGVkIHRoZW0sIGFuZCBwdXNoZWQgdGhlbSB0byB0aGUgcmVtb3RlIHJlcG8uIEluIGxvb2tpbmcgYXQgdGhlIGVycm9yIG1lc3NhZ2UgZnJvbSBHaXQsIEp1YW4gbm90aWNlcyB0aGF0IGl0IHN1Z2dlc3RzIGhlIHNob3VsZCAqKnB1bGwqKiB0aGUgY2hhbmdlcyBhbmQgaW50ZWdyYXRlIHRoZW0gaW50byBoaXMgb3duIHNjcmlwdC4KCkp1YW4gZ29lcyBhaGVhZCBhbmQgcHVsbHMgTWFyeSdzIHJlY2VudCBjaGFuZ2VzIHRvIGhpcyBsb2NhbCByZXBvLCB3aGljaCBpc3N1ZXMgYW5vdGhlciB3YXJuaW5nIGFib3V0IGEgc28tY2FsbGVkICptZXJnZSBjb25mbGljdCogaW4gYFIvMDBfdGVzdGluZy5SYCB0aGF0IEp1YW4gd2lsbCBoYXZlIHRvIGZpeC4KCjxicj4KCiFbXShpbWFnZXMvY2VudHJhbF9wdWxsX2Vycm9yLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgojIyBNZXJnZSBjb25mbGljdHMKCldoZW4gSnVhbiBpbnNwZWN0cyBoaXMgdmVyc2lvbiBvZiBgMDBfdGVzdGluZy5SYCBoZSBzZWVzIHRoYXQgR2l0IGhhcyBhZGRlZCBzb21lIGluZm9ybWF0aW9uIHRvIHRoZSBzY3JpcHQsIHdoaWNoIGJyYWNrZXRzIHRoZSBuZXcgY2hhbmdlcyB0aGF0IGJvdGggSnVhbiBhbmQgTWFyeSBtYWRlOgoKYGBge3IgZXZhbCA9IEZBTFNFfQo8PDw8PDw8IEhFQUQKIyMgc3VidHJhY3Rpb24KbnVtIC0gZGVuCj09PT09PT0KIyMgYWRkaXRpb24KbnVtICsgZGVtbwo+Pj4+Pj4+IGQxYWI1NWUzY2YxOTc5ZWZkMGE2MTk1NDMwNWY3NDJjZmJiMzhlMTEKYGBgCgo8YnI+CgohW10oaW1hZ2VzL2NlbnRyYWxfbWVyZ2VfY29uZmxpY3QucG5nKXsgd2lkdGg9NzAlIH0KCjo6OiB0aXAKCllvdSBjYW4gdGhpbmsgb2YgdGhlc2UgbmV3IGxpbmVzIGFzICJjb25mbGljdCBkaXZpZGVycyIuCgo6OjoKClRoZSBgPT09PT09PWAgbGluZSBpcyB0aGUgY2VudGVyIG9mIHRoZSBjb25mbGljdC4KCkV2ZXJ5dGhpbmcgYmV0d2VlbiBgPDw8PDw8PCBIRUFEYCBhbmQgYD09PT09PT1gIGlzIGNvbnRlbnQgdGhhdCBleGlzdHMgaW4gdGhlICpsb2NhbCogcmVwbyB0byB3aGljaCB0aGUgYEhFQURgIHJlZiBpcyBwb2ludGluZy4KCkV2ZXJ5dGhpbmcgYmV0d2VlbiBgPT09PT09PWAgYW5kIGA+Pj4+Pj4+IGQxYWI1NWUzY2YxOTc5ZWZkMGE2MTk1NDMwNWY3NDJjZmJiMzhlMTFgIGlzIGNvbnRlbnQgdGhhdCBpcyBwcmVzZW50IGluIHRoZSAqcmVtb3RlKiByZXBvLgoKOjo6IHRpcAoKQXQgdGhpcyBwb2ludCwgaXQgd291bGQgYmUgYSBnb29kIGlkZWEgZm9yIEp1YW4gdG8gY29udGFjdCBNYXJ5IGFuZCBmaW5kIG91dCB3aGF0IGhlciBwbGFucyBhcmUsIHNvIGhlIGNhbiBhdm9pZCB0aGlzIHByb2JsZW0gaW4gdGhlIGZ1dHVyZS4KCjo6OgoKQWZ0ZXIgY29uZmlybWluZyB0aGF0IE1hcnkgaXMgZG9uZSBtYWtpbmcgY2hhbmdlcyBmb3IgYXdoaWxlLCBKdWFuIGNhbiByZXR1cm4gdG8gcmVzb2x2aW5nIHRoZSBjdXJyZW50IG1lcmdlIGNvbmZsaWN0LiBUbyBkbyBzbywgSnVhbiBpbnNwZWN0cyB0aGUgbmV3IGNoYW5nZXMgdGhhdCBNYXJ5IG1hZGUgYW5kIGRlY2lkZXMgaWYgaGUgd2FudHMgdG8gbWVyZ2UgdGhlbSBpbnRvIGhpcyB2ZXJzaW9uIG9mIHRoZSBmaWxlLCBvciB3aGV0aGVyIGhlIHdhbnRzIHRvIGRpc2NhcmQgdGhlbS4gSW4gdGhpcyBjYXNlLCBKdWFuIGlzIGhhcHB5IHdpdGggdGhlIG5ldyBhZGRpdGlvbiBvcGVyYXRpb24gdGhhdCBNYXJ5IG1hZGUsIHNvIGhlIGFjY2VwdHMgdGhlbSBieSBzaW1wbHkgZGVsZXRpbmcgdGhlIGNvbmZsaWN0IGRpdmlkZXJzLgoKPGJyPgoKIVtdKGltYWdlcy9jZW50cmFsX21lcmdlX3Jlc29sdmUucG5nKXsgd2lkdGg9NzAlIH0KCjxicj4KCk5vdyBKdWFuIGNhbiBjb21taXQgaGlzIHJlc29sdmVkIGNoYW5nZXMgYW5kIHB1c2ggdGhlbSB0byB0aGUgcmVtb3RlIHJlcG8uCgo8YnI+CgohW10oaW1hZ2VzL2NlbnRyYWxfcmVzb2x2ZWRfY29tbWl0LnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgohW10oaW1hZ2VzL2NlbnRyYWxfcHVzaF9zdWNjZWVkLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgpOb3cgSnVhbiBpcyBhbGwgc2V0IG9uIGhpcyBzaWRlLCBidXQgTWFyeSBzaG91bGQgbWFrZSBzdXJlIHRoYXQgc2hlIHB1bGxzIEp1YW4ncyBjaGFuZ2VzIHRvIGhlciBsb2NhbCByZXBvIGJlZm9yZSBzaGUgc3RhcnRzIHdvcmtpbmcgb24gdGhlIHNjcmlwdCBhZ2Fpbi4KCjo6OiBub3RlCgpUaGlzIHNjZW5hcmlvIGRvZXMgbm90IG5lY2Vzc2FyaWx5IHJlcXVpcmUgdHdvIG9yIG1vcmUgY29sbGFib3JhdG9ycy4gCgpGb3IgZXhhbXBsZSwgTWFyayBrbm93cyBmcm9tIHBlcnNvbmFsIGV4cGVyaWVuY2UgdGhhdCBzb21lb25lIGNhbiBkbyBzb21lIHdvcmsgb24gYSBjb21wdXRlciBpbiB0aGVpciBvZmZpY2UsIGNvbW1pdCB0aG9zZSBjaGFuZ2VzLCBhbmQgdGhlbiBmb3JnZXQgdG8gcHVzaCB0aGVtIGJlZm9yZSBoZWFkaW5nIGhvbWUuIFVwb24gYXJyaXZpbmcgaG9tZSwgdGhleSBjb3VsZCBwdWxsIHRoZWlyIGNoYW5nZXMgdG8gdGhlaXIgbGFwdG9wLCBtYWtlIGFkZGl0aW9uYWwgY2hhbmdlcywgY29tbWl0IHRoZW0sIGFuZCB0aGVuIHB1c2ggdGhlbSB0byB0aGUgcmVtb3RlIHJlcG8uIFVwb24gcmV0dXJuaW5nIGJhY2sgdG8gdGhlIG9mZmljZSwgdGhleSBjYW4gZW5jb3VudGVyIHByb2JsZW1zIHdpdGggY29tbWl0dGluZyBhbmQgcHVzaGluZyB0aG9zZSBjaGFuZ2VzIHRoZXkgZm9yZ290IGFib3V0IHRoZSBkYXkgYmVmb3JlLgoKOjo6CgoqKioKCiMgRmVhdHVyZSBicmFuY2ggd29ya2Zsb3cKClRoZSBmZWF0dXJlIGJyYW5jaCB3b3JrZmxvdyBpcyBkZXNpZ25lZCBhcm91bmQgbXVsdGlwbGUgKmJyYW5jaGVzKiB3aXRoaW4gYSByZXBvLiBUaGVzZSBicmFuY2hlcyBjYW4gY29udGFpbiBjb3BpZXMgb2YgZmlsZXMgb24gdGhlICoqbWFpbioqIGJyYW5jaCwgYW5kIGFyZSB0eXBpY2FsbHkgdXNlZCBmb3IgdGhlIGRldmVsb3BtZW50IG9mIHNwZWNpZmljIGZlYXR1cmVzLgoKIyBDcmVhdGUgYSBicmFuY2gKCkxldCdzIGxvb2sgYXQgdHdvIGRpZmZlcmVudCB3YXlzIHRvIGNyZWF0ZSBhIG5ldyBicmFuY2guCgo6OjogdGFzawoKUmV2aWV3IHRoZXNlIGluc3RydWN0aW9ucyBmb3IgY3JlYXRpbmcgYSBuZXcgYnJhbmNoIGZyb20gd2l0aGluIEdpdEh1YiwgYnV0IGRvbid0IGZvbGxvdyB0aHJvdWdoIHdpdGggdGhlbS4gV2UnbGwgaW5zdGVhZCB1c2UgdGhlIHNlY29uZCBhcHByb2FjaCBzaG93biBiZWxvdy4KCjo6OgoKVGhlIGZpcnN0IGFwcHJvYWNoIGlzIGZyb20gR2l0SHViIGl0c2VsZi4gVG8gZG8gc28sIG5hdmlnYXRlIHRvIHRoZSByZW1vdGUgcmVwbyBhbmQgY2xpY2sgb24gdGhlIGJ1dHRvbiBtYXJrZWQgKiptYWluKiogaW4gdGhlIHVwcGVyIGxlZnQuIFRoaXMgd2lsbCBvcGVuIGEgZGlhbG9ndWUgYm94IHdpdGggYSBsaW5lIGZvciB5b3UgdG8gZmluZCBvciBjcmVhdGUgYSBicmFuY2guIFR5cGUgdGhlIG5hbWUgb2YgdGhlIG5ldyBicmFuY2ggKGUuZy4sICJkZXZlbG9wIikgYW5kIHRoZW4gaGl0ICJyZXR1cm4iLgoKPGJyPgoKPGltZyBzcmM9ImltYWdlcy9mZWF0dXJlX25ld19icmFuY2gucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKPGJyPgoKVGhlIHNlY29uZCBvcHRpb24gZm9yIGNyZWF0aW5nIGEgbmV3IGJyYW5jaCwgd2hpY2ggd2UnbGwgZm9sbG93IGhlcmUsIGlzIHRvIGRvIHNvIGZyb20gd2l0aGluIFJTdHVkaW8uCgo6OjogdGFzawoKQ2xpY2sgb24gdGhlIHB1cnBsZSBidXR0b24gd2l0aCAyIHJlY3RhbmdsZXMgYW5kIGEgZGlhbW9uZCBpbiB0aGUgKipHaXQqKiBwYW5lLCB3aGljaCB3aWxsIGJyaW5nIHVwIGEgZGlhbG9ndWUgd2luZG93IHdoZXJlIHlvdSBjYW4gZW50ZXIgdGhlIG5hbWUgb2YgeW91ciBuZXcgYnJhbmNoICh3ZSdsbCBjYWxsIGl0ICJkZXZlbG9wIikuIFByZXNzIHRoZSAqKkNyZWF0ZSoqIGJ1dHRvbiB3aGVuIHlvdSdyZSBkb25lLgoKOjo6CgohW10oaW1hZ2VzL2ZlYXR1cmVfbmV3X2JyYW5jaF9yc3R1ZGlvLnBuZyl7IHdpZHRoPTUwJSB9Cgo8YnI+Cgo6Ojogbm90ZQoKQXQgdGhpcyBwb2ludCwgeW91J2xsIHNlZSBhIG1lc3NhZ2Ugd2luZG93IGZyb20gR2l0IHdpdGggdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjoKCiogbGluZXMgMS0yOiBHaXQgY3JlYXRlZCBhIG5ldyBicmFuY2ggYW5kIHN3aXRjaGVkIG92ZXIgdG8gaXQgd2l0aCBgZ2l0IGNoZWNrb3V0IC1CIGRldmVsb3BgCiogbGluZXMgMy0xMDogR2l0IHB1c2hlZCBhbGwgb2YgeW91ciBsb2NhbCBmaWxlcyB0byBhIG5ld2x5IGNyZWF0ZWQgYGRldmVsb3BgIGJyYW5jaCBvbiB0aGUgcmVtb3RlIEdpdEh1YiByZXBvLgoKR2l0IGlzIGFsc28gc3VnZ2VzdGluZyB5b3UgY3JlYXRlIGEgc28tY2FsbGVkICpwdWxsIHJlcXVlc3QqIHRvIG1vdmUgY2hhbmdlcyBmcm9tIHRoZSAqKmRldmVsb3AqKiBicmFuY2ggaW50byB0aGUgKiptYWluKiogYnJhbmNoIGJ5IG5hdmlnYXRpbmcgdG8geW91ciByZW1vdGUgcmVwbyBvbiBHaXRIdWIuCgo6OjoKCiFbXShpbWFnZXMvZmVhdHVyZV9uZXdfYnJhbmNoX3JzdHVkaW9fd2luZG93LnBuZyl7IHdpZHRoPTcwJSB9Cgo6OjogdGlwCgpJZiB5b3UgbmF2aWdhdGUgYmFjayB0byB0aGUgKip0ZXN0aW5nKiogcmVwbyBvbiBHaXRIdWIgYW5kIHJlZnJlc2ggeW91ciBicm93c2VyLCB5b3Ugd2lsbCBzZWUgdGhhdCB0aGVyZSBhcmUgbm93IDIgYnJhbmNoZXMgdGhlcmU6IG1haW4gYW5kIGRldmVsb3AuCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZ2hfcmVwb19ib3RoX2JyYW5jaGVzLnBuZyIgY2xhc3M9Im5vYm9yZGVyIj4KCgo8YnI+CgpMZXQncyBnbyBhaGVhZCBhbmQgbWFrZSBhIHNtYWxsIGNoYW5nZSB0byBvdXIgUiB0ZXN0IHNjcmlwdCAobm90ZSB0aGF0IHRoZSBmb2xsb3dpbmcgYXNzdW1lcyB5b3UgaGF2ZSBub3QgYWxyZWFkeSBtYWRlIHRoZXNlIGNoYW5nZXMgaW4gdGhlIGFib3ZlIHNlY3Rpb24gb24gKipDZW50cmFsaXplZCB3b3JrZmxvdyoqKS4gQWZ0ZXIgZG9pbmcgc28sIHdlJ2xsIGNvbW1pdCBhbmQgcHVzaCB0aGUgY2hhbmdlcyBvbiB0aGUgKipkZXZlbG9wKiogYnJhbmNoIHVwIHRvIG91ciByZW1vdGUgcmVwbyBvbiBHaXRIdWIuCgo6OjogdGFzawoKQWRkIHRoZSBmb2xsb3dpbmcgMiBsaW5lcyBvZiBjb2RlIHRvIHRoZSBgMDBfdGVzdGluZy5SYCBzY3JpcHQuIFNhdmUgdGhlIGNoYW5nZXMgd2hlbiB5b3UgYXJlIGZpbmlzaGVkLgoKOjo6CgohW10oaW1hZ2VzL2ZlYXR1cmVfbmV3X2xpbmVzX2luX3Rlc3RpbmcucG5nKXsgd2lkdGg9NzAlIH0KCgo6OjogdGFzawoKQWRkIHRoZSBmaWxlIHRvIHN0YWdpbmcgYW5kIGNvbW1pdCBpdC4gSW5jbHVkZSBhIF9zaG9ydCBidXQgaW5mb3JtYXRpdmVfIGNvbW1pdCBtZXNzYWdlIGFuZCBjbGljayB0aGUgKipDb21taXQqKiBidXR0b24gd2hlbiByZWFkeS4KCjo6OgoKPGltZyBzcmM9ImltYWdlcy9mZWF0dXJlX25ld19jb21taXQucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKOjo6IHRhc2sKCkNsaWNrIG9uIHRoZSBncmVlbiB1cGFycm93IG5leHQgdG8gIlB1c2giIHRvIHB1c2ggeW91ciBjaGFuZ2VzIHRvIEdpdEh1Yi4KCjo6OgoKOjo6IG5vdGUKClJTdHVkaW8gd2lsbCBwb3Agb3BlbiBhIHdpbmRvdyBlY2hvaW5nIHlvdXIgcHVzaCBjb21tYW5kIGFuZCB0aGUgZGVzdGluYXRpb24uCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZmVhdHVyZV9uZXdfY29tbWl0X3B1c2gucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKPGJyPgoKIyMgUHVsbCByZXF1ZXN0cwoKTm93IGxldCdzIHRha2UgdGhlIGFkdmljZSB3ZSByZWNlaXZlZCBlYXJsaWVyIGFib3V0IGNyZWF0aW5nIGEgInB1bGwgcmVxdWVzdCIgKG9yICJQUiIgZm9yIHNob3J0KS4gWW91IGNhbiB0aGluayBvZiBhIHB1bGwgcmVxdWVzdCBhcyBhbiBvZmZlciBvZiBzdXBwb3J0LiBJbiBlZmZlY3QsIHNvbWVvbmUgd2hvIHN1Ym1pdHMgYSBwdWxsIHJlcXVlc3QgaXMga2luZGx5IHJlcXVlc3RpbmcgdGhhdCB0aGUgcmVwbyBvd25lciBwdWxsIG5ldyBjaGFuZ2VzIGludG8gdGhlaXIgcmVwby4KCjo6OiB0YXNrCgpOYXZpZ2F0ZSB0byB5b3VyIHRlc3RpbmcgcmVwbyBvbiBHaXRIdWIuCgo6OjoKCjo6OiBub3RlCgpVcG9uIGFycml2aW5nIHRoZXJlLCB3ZSBzZWUgYSBtZXNzYWdlIHRoYXQgIioqZGV2ZWxvcCoqIGhhZCByZWNlbnQgcHVzaGVzIGxlc3MgdGhhbiBhIG1pbnV0ZSBhZ28iLiBUbyB0aGUgcmlnaHQgb2YgdGhhdCBpcyBhIGdyZWVuIGJ1dHRvbiBtYXJrZWQgKipDb21wYXJlICYgcHVsbCByZXF1ZXN0KiouCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZmVhdHVyZV9naF9wcl9ub3RpY2UucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKCgo6OjogdGFzawoKQ2xpY2sgb24gdGhlIGdyZWVuICoqQ29tcGFyZSAmIHB1bGwgcmVxdWVzdCoqIGJ1dHRvbiwgd2hpY2ggd2lsbCB0YWtlIHlvdSB0byBhIHBhZ2UgdG8gb3BlbiBhIHB1bGwgcmVxdWVzdC4KCjo6OgoKOjo6IHRpcAoKQXQgdGhlIHRvcCB5b3Ugd2lsbCBzZWUgc29tZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgYnJhbmNoZXMgZnJvbSB3aGljaCBhbmQgdG8gd2hlcmUgdGhlIGNoYW5nZXMgd2lsbCBiZSBtZXJnZWQsIGFsb25nIHdpdGggYSBub3RlIGFib3V0IHRoZSBicmFuY2hlcyBiZWluZyBva2F5IHRvIG1lcmdlLiBJZiB5b3Ugc2Nyb2xsIGRvd24gdGhlIHBhZ2UsIHlvdSdsbCBzZWUgdGhlIGNoYW5nZXMgdGhhdCB3ZXJlIGNvbW1pdHRlZCwgd2hlbiB0aGV5IHdlcmUgbWFkZSwgYW5kIHdobyBkaWQgaXQuCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZmVhdHVyZV9naF9wcl9wYWdlLnBuZyIgY2xhc3M9Im5vYm9yZGVyIj4KCgo6OjogdGlwCgpJZiB5b3VyIHB1bGwgcmVxdWVzdCBpbnZvbHZlcyBtdWx0aXBsZSBmaWxlcywgZmVhdHVyZXMsIGV0YywgaXQncyBhIGdvb2QgaWRlYSB0byBpbmNsdWRlIHNvbWUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBpbiB0aGUgY29tbWVudCBib3ggKHRoaXMgY2FuIGluY2x1ZGUgTWFya2Rvd24gZmxhdm9yZWQgdGV4dCkuCgo6OjoKCjo6OiB0YXNrCgoqIENsaWNrIG9uIHRoZSBncmVlbiAqKkNyZWF0ZSBwdWxsIHJlcXVlc3QqKiBidXR0b24sIHdoaWNoIHdpbGwgdGFrZSB5b3UgdG8gYW5vdGhlciBwYWdlIHdoZXJlIHlvdSBjYW4gcmV2aWV3IGFueSBjb21tZW50cyAoaGVyZSB0aGVyZSBhcmUgbm9uZSkgYW5kIG1lcmdlIHRoZSBwdWxsIHJlcXVlc3QuCgoqIEluIHRoZSBtaWRkbGUgb2YgdGhlIHBhZ2UsIHlvdSdsbCBzZWUgYSBub3RlIGFib3V0ICoqVGhpcyBicmFuY2ggaGFzIG5vIGNvbmZsaWN0cyB3aXRoIHRoZSBiYXNlIGJyYW5jaCoqIGFuZCBhIGdyZWVuIGJ1dHRvbiBsYWJlbGVkICoqTWVyZ2UgcHVsbCByZXF1ZXN0KiouCgoqIEdvIGFoZWFkIGFuZCBwdXNoIHRoYXQgYnV0dG9uLgoKOjo6CgoKPGltZyBzcmM9ImltYWdlcy9mZWF0dXJlX2doK3ByX21lcmdlLnBuZyIgY2xhc3M9Im5vYm9yZGVyIj4KCgo8YnI+CgpBdCB0aGlzIHBvaW50LCB0aGUgd2luZG93IHdpbGwgc3dpdGNoIG92ZXIgdG8gYXNraW5nIHlvdSB0byBjb25maXJtIHRoZSBtZXJnZS4KCjo6OiB0YXNrCgpHbyBhaGVhZCBhbmQgY2xpY2sgb24gdGhlIGdyZWVuICoqQ29uZmlybSBtZXJnZSoqIGJ1dHRvbi4KCjo6OgoKPGltZyBzcmM9ImltYWdlcy9mZWF0dXJlX2doX3ByX21lcmdlX2NvbmZpcm0ucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKCjxicj4KCkFmdGVyIGRvaW5nIHNvLCBHaXRIdWIgd2lsbCBub3cgcmVwb3J0ICoqUHVsbCByZXF1ZXN0IHN1Y2Nlc3NmdWxseSBtZXJnZWQgYW5kIGNsb3NlZCoqICh5b3UnbGwgYWxzbyBub3RpY2UgdGhhdCB0aGUgZ3JlZW4gKipPcGVuKiogb3ZhbCBiZWxvdyB0aGUgbmFtZSBvZiB0aGUgcHVsbCByZXF1ZXN0IGhhcyBjaGFuZ2VkIHRvIGEgcHVycGxlICoqTWVyZ2VkKiogb3ZhbCkuIEdpdEh1YiBhbHNvIHRlbGxzIHlvdSB0aGF0ICJZb3XigJlyZSBhbGwgc2V0LS10aGUgKipkZXZlbG9wKiogYnJhbmNoIGNhbiBiZSBzYWZlbHkgZGVsZXRlZC4iCgo8aW1nIHNyYz0iaW1hZ2VzL2ZlYXR1cmVfZ2hfcHJfbWVyZ2Vfc3VjY2Vzcy5wbmciIGNsYXNzPSJub2JvcmRlciI+CgoKOjo6IHRpcAoKSWYgeW91ciBicmFuY2ggd2FzIGNyZWF0ZWQgc29sZWx5IGZvciB0aGUgcHVycG9zZSBvZiB3b3JraW5nIG9uIGEgc3BlY2lmaWMgZmVhdHVyZSwgdGhlbiB5b3UgY2FuIGdvIGFoZWFkIGFuZCBkZWxldGUgaXQuIElmLCBob3dldmVyLCB5b3Ugd2FudCB0byBtYWludGFpbiBhIGRldmVsb3BtZW50IChvciBvdGhlcikgYnJhbmNoLCB0aGVuIHlvdSBjYW4ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlIGFuZCBrZWVwaW5nIHdvcmtpbmcgb24gaXQgYXMgd2VsbC4KCjo6OgoKKioqCgojIEZvcmtpbmcgd29ya2Zsb3cKClJlY2FsbCB0aGF0IGEgZm9ya2luZyB3b3JrZmxvdyBpcyBjb21tb25seSB1c2VkIHdoZW4gYSBkZXZlbG9wZXIgaXMgKm5vdCogYSBtZW1iZXIgb2YgdGhlIHByb2plY3Qvb3JnYW5pemF0aW9uIG9uIEdpdEh1Yi4gVGhpcyB3b3JrZmxvdyBhbGxvd3MgdGhlIGRldmVsb3BlciB0byB3b3JrIHdpdGggYSBjb3B5IG9mIHRoZSBvd25lcidzIHJlcG8gYW5kIHBvdGVudGlhbGx5IHN1Ym1pdCBhIHB1bGwgcmVxdWVzdCBmb3IgdGhlIG93bmVyIHRvIGNvbnNpZGVyIGFkb3B0aW5nIHRoZSBjaGFuZ2VzLgoKIyMgU3RlcCAxOiBGb3JrIHRoZSByZXBvCgo8YnI+CgohW10oaW1hZ2VzL2doX2ZvcmtfMS5wbmcpeyB3aWR0aD03MCUgfQoKPGJyPgoKVG8gZm9yayBhIHJlcG8sIG5hdmlnYXRlIHRvIGl0cyBsb2NhdGlvbiBvbiBHaXRIdWIgYW5kIGxvb2sgZm9yIHRoZSAqKkZvcmsqKiBidXR0b24gaW4gdGhlIHVwcGVyIHJpZ2h0LiBQcmVzcyB0aGF0IGJ1dHRvbiwgd2hpY2ggd2lsbCBicmluZyB1cCBhIGRpYWxvZ3VlIGJveCBhc2tpbmcgeW91IHdoZXJlIHlvdSB3b3VsZCBsaWtlIHRvIGZvcmsgdGhlIHJlcG8uIENsaWNrIG9uIHRoZSB1c2VyIG9yIG9yZ2FuaXphdGlvbiB3aGVyZSB5b3UnZCBsaWtlIHRvIGZvcmsgdGhlIHJlcG8gYW5kIEdpdEh1YiB3aWxsIGRvIHRoZSByZXN0LgoKPGltZyBzcmM9ImltYWdlcy9naF9mb3JrX29yaWdfcmVwby5wbmciIGNsYXNzPSJub2JvcmRlciI+CgoKOjo6IG5vdGUKCldoZW4geW91IGNsaWNrIG9uIHRoZSAqKkZvcmsqKiBidXR0b24sIEdpdEh1YiB3aWxsIG9wZW4gYSBwYWdlIHRoYXQgbG9va3Mgc2ltaWxhciB0byB3aGVuIHlvdSBjcmVhdGUgYSBuZXcgcmVwby4KCjo6OgoKOjo6IHRhc2sKCkNsaWNrIHRoZSBncmVlbiAqKkNyZWF0ZSBmb3JrKiogYnV0dG9uIHRvIHByb2NlZWQuCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZ2hfZm9ya19jcmVhdGUucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKCjxicj4KCllvdSB3aWxsIG5vdyBzZWUgYSBuZXcgZm9ya2VkIHZlcnNpb24gb2YgdGhlIG9yaWdpbmFsIHJlcG9zaXRvcnkgd2l0aCBzb21lIGluZm9ybWF0aW9uIGluIHRoZSB1cHBlciBsZWZ0IGFib3V0IGl0cyBsb2NhdGlvbiBhbmQgZnJvbSB3aGVyZSBpdCBjYW1lLiBZb3UnbGwgYWxzbyBzZWUgc29tZSBpbmZvcm1hdGlvbiBhYm92ZSB0aGUgcmVwbyBjb250ZW50cyBhYm91dCB0aGUgY3VycmVudCBicmFuY2ggYmVpbmcgdXAgdG8gZGF0ZSB3aXRoIHRoZSAidXBzdHJlYW0iIHNvdXJjZS4KCjxpbWcgc3JjPSJpbWFnZXMvZ2hfZm9ya19yZXBvX2ZvcmtlZC5wbmciIGNsYXNzPSJub2JvcmRlciI+CgoKCjo6OiBub3RlCgpJbiB0aGUgbm90IHNvIGRpc3RhbnQgcGFzdCwgeW91IGhhZCB0byB1c2UgR2l0IHZpYSB0aGUgY29tbWFuZCBsaW5lIHRvIHNwZWNpZnkgd2hlcmUgdGhlICJ1cHN0cmVhbSIgcmVwbyBvZiBhIGZvcmsgd2FzIGFuZCB0aGVuICJmZXRjaCIgYW55IGNoYW5nZXMuIEdpdEh1YiBoYXMgbm93IHN0cmVhbWxpbmVkIHRoYXQgcHJvY2VzcyBieSBwcm92aWRpbmcgYSAic3luYyBmb3JrIiBidXR0b24gdG8gZG8gc28gKHNlZSBiZWxvdykuCgo6OjoKCjxpbWcgc3JjPSJpbWFnZXMvZ2hfZm9ya19zeW5jLnBuZyIgY2xhc3M9Im5vYm9yZGVyIj4KCgo8YnI+CgoKIyMgU3RlcCAyOiBDbG9uZSB0aGUgcmVwbwoKPGJyPgoKIVtdKGltYWdlcy9naF9mb3JrXzIucG5nKXsgd2lkdGg9NzAlIH0KCgo6OjogdGFzawoKQ2xvbmUgdGhlIHJlbW90ZSBHaXRIdWIgcmVwbyB0byBhIGxvY2FsIHJlcG8gYnkgY3JlYXRpbmcgYSBuZXcgcHJvamVjdCBpbiBSU3R1ZGlvIGJhc2VkIHVwb24geW91ciBuZXdseSBmb3JrZWQgcmVwby4gQ2xpY2sgW2hlcmVdKGh0dHBzOi8vZmlzaDU0OS5naXRodWIuaW8vd2Vic2l0ZS9sZWN0dXJlcy93ZWVrXzAyL2xlY18wNl9naXRfcmVtb3Rlcy5odG1sKSBpZiB5b3UgbmVlZCBhIHJlbWluZGVyIGFzIHRvIGhvdyB0byBkbyB0aGF0LgoKOjo6Cgo8YnI+CgojIyBTdGVwIDM6IEFkZCByZW1vdGUgcmVwbwoKPGJyPgoKIVtdKGltYWdlcy9naF9mb3JrXzMucG5nKXsgd2lkdGg9NzAlIH0KCjxicj4KCkF0IHRoaXMgcG9pbnQsIHlvdXIgbG9jYWwgY29weSBvZiB0aGUgcmVtb3RlIHJlcG8gY2FuIG9ubHkgcHVsbCBjaGFuZ2VzIGZyb20geW91ciByZW1vdGUgYXQgCgpgaHR0cHM6Ly9naXRodWIuY29tL1VTRVJOQU1FL2V4LWZvcmtgCgp3aGVyZSBgVVNFUk5BTUVgIGlzIHlvdXIgR2l0SHViIHVzZXJuYW1lLiBVbmZvcnR1bmF0ZWx5IHRoZXJlIGlzIG5vIHdheSB0byB1cGRhdGUgeW91ciByZW1vdGUgcmVwbyBkaXJlY3RseSBmcm9tIHRoZSBvd25lcidzIHJlcG8gYXQKCmBodHRwczovL2dpdGh1Yi5jb20vRklTSDU0OS9leC1mb3JrYC4KCkluc3RlYWQsIHdlIGhhdmUgdG8gc2V0IHVwIG91ciBsb2NhbCByZXBvIHRvIHB1bGwgY2hhbmdlcyBmcm9tIHRoZSBvd25lcidzIHJlbW90ZSByZXBvIGFuZCB0aGVuIHdlIGNhbiBwdXNoIHRob3NlIHVwIHRvIG91ciByZW1vdGUgY29weS4gQnkgY29udmVudGlvbiwgd2Ugd2lsbCByZWZlciB0byB0aGUgb3duZXIncyByZXBvIGFzIHRoZSBgdXBzdHJlYW1gIHJlcG8sIGJ1dCB5b3UgY291bGQgZ2l2ZSBpdCBhbnkgbmFtZS4KCkF0IHRoaXMgcG9pbnQgeW91IGhhdmUgMiBvcHRpb25zIGZvciBhZGRpbmcgdGhlIGB1cHN0cmVhbWAgcmVwby4KCiMjIyBPcHRpb24gMTogQ29tbWFuZCBsaW5lCgo6OjogdGFzawoKQ2xpY2sgb24gdGhlICoqVGVybWluYWwqKiB0YWIgaW4geW91ciBSU3R1ZGlvIGNvbnNvbGUgd2luZG93IGFuZCB0eXBlIChvciBjb3B5L3Bhc3RlKSB0aGUgZm9sbG93aW5nIEdpdCBjb21tYW5kOgoKOjo6CgpgYGBzaApnaXQgcmVtb3RlIGFkZCB1cHN0cmVhbSBodHRwczovL2dpdGh1Yi5jb20vRklTSDU0OS9leC1mb3JrCmBgYAoKIyMjIE9wdGlvbiAyOiBSU3R1ZGlvCgo6OjogdGFzawoKT3BlbiB1cCB5b3VyIHByb2plY3QgaW4gUlN0dWRpbyBhbmQgY2xpY2sgb24gdGhlICJOZXcgYnJhbmNoIiBidXR0b24gaW4gdGhlICoqR2l0KiogcGFuZSAoaS5lLiwgdGhlIGJ1dHRvbiB3aXRoIHRoZSAyIHB1cnBsZSByZWN0YW5nbGVzIGFuZCBhIGRpYW1vbmQpLgoKOjo6CgohW10oaW1hZ2VzL2doX2ZvcmtfcnNfYWRkX3JlbW90ZV8xLnBuZyl7IHdpZHRoPTcwJSB9CgoKOjo6IHRhc2sKCkNsaWNrIG9uIHRoZSBidXR0b24gbGFiZWxlZCAiQWRkIHJlbW90ZS4uLiIuCgo6OjoKCiFbXShpbWFnZXMvZ2hfZm9ya19yc19hZGRfcmVtb3RlXzIucG5nKXsgd2lkdGg9NzAlIH0KCjo6OiB0YXNrCgoqIEluIHRoZSAiUmVtb3RlIE5hbWU6IiBib3gsIHR5cGUgYHVwc3RyZWFtYC4KCiogSW4gdGhlICJSZW1vdGUgVVJMOiIgYm94LCBlbnRlciB0aGUgbmFtZSBvZiB0aGUgKipvd25lcidzKiogcmVwbyB5b3UgZm9ya2VkIGluIFN0ZXAgMTogYGh0dHBzOi8vZ2l0aHViLmNvbS9GSVNINTQ5L2V4LWZvcmtgICh5b3UgY2FuIGNvcHkvcGFzdGUgaWYgeW91J2QgbGlrZSkuCgoqIFdoZW4geW91IGFyZSBmaW5pc2hlZCwgY2xpY2sgdGhlICoqQWRkKiogYnV0dG9uLgoKOjo6CgohW10oaW1hZ2VzL2doX2ZvcmtfcnNfYWRkX3JlbW90ZV8zLnBuZyl7IHdpZHRoPTcwJSB9CgoKOjo6IHRhc2sKCkNsaWNrIG9uIHRoZSAqKkNhbmNlbCoqIGJ1dHRvbiAoZG9uJ3Qgd29ycnksIGV2ZXJ5dGhpbmcgaXMgc3RpbGwgT0spLgoKOjo6CgoKIVtdKGltYWdlcy9naF9mb3JrX3JzX2FkZF9yZW1vdGVfNC5wbmcpeyB3aWR0aD03MCUgfQoKCjo6OiB0YXNrCgpOb3cgeW91IG5lZWQgdG8gdmVyaWZ5IHRoYXQgdGhlIHJlbW90ZSBgdXBzdHJlYW1gIGlzIHNldCB1cCBwcm9wZXJseS4gVG8gZG8gc28sIGNsaWNrIG9uIHRoZSAqKlRlcm1pbmFsKiogdGFiIGluIHlvdXIgQ29uc29sZSBwYW5lIGFuZCB0eXBlIHRoaXM6Cgo6OjoKCmBgYHNoCiQgZ2l0IHJlbW90ZSAtdgpgYGAKCndoaWNoIHNob3VsZCByZXR1cm4gdGhlIGZvbGxvd2luZywgd2hlcmUgYFVTRVJOQU1FYCBpcyB5b3VyIHVzZXIgbmFtZS4KCmBgYHNoCm9yaWdpbiAgaHR0cHM6Ly9naXRodWIuY29tL1VTRVJOQU1FL2V4LWZvcmsgKGZldGNoKQpvcmlnaW4gIGh0dHBzOi8vZ2l0aHViLmNvbS9VU0VSTkFNRS9leC1mb3JrIChwdXNoKQp1cHN0cmVhbSAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL0ZJU0g1NDkvZXgtZm9yayAoZmV0Y2gpCnVwc3RyZWFtICAgICAgICBodHRwczovL2dpdGh1Yi5jb20vRklTSDU0OS9leC1mb3JrIChwdXNoKQpgYGAKCjxicj4KCiFbXShpbWFnZXMvZ2hfZm9ya19yc19hZGRfcmVtb3RlXzUucG5nKXsgd2lkdGg9NzAlIH0KCjxicj4KCiMjIFN0ZXAgNDogTWFrZSBsb2NhbCBjaGFuZ2VzCgo8YnI+CgohW10oaW1hZ2VzL2doX2ZvcmtfNC5wbmcpeyB3aWR0aD03MCUgfQoKPGJyPgoKTm93IHlvdSBhcmUgcmVhZHkgdG8gbWFrZSBhbnkgY2hhbmdlcyB5b3UnZCBsaWtlIHRvIHRoZSBmaWxlcyBvciBmb2xkZXJzIGluIHlvdXIgbG9jYWwgcmVwby4gIAoKOjo6IHRpcAoKKipCZWZvcmUgZG9pbmcgc28qKiwgbWFrZSBzdXJlIHRvICoqcHVsbCoqIGFueSBjaGFuZ2VzIHRoYXQgbWlnaHQgaGF2ZSBiZWVuIG1hZGUgdG8gdGhlIG93bmVyJ3MgYHVwc3RyZWFtYCByZW1vdGUuCgo6OjoKCjo6OiB0YXNrCgpUbyBkbyBzbywgYWdhaW4gbmF2aWdhdGUgdG8gdGhlICoqVGVybWluYWwqKiB0YWIgaW4gUlN0dWRpbyBhbmQgdHlwZToKCjo6OgoKYGBgc2gKJCBnaXQgcHVsbCB1cHN0cmVhbSBtYWluIC0tZmYtb25seQpgYGAKCklmIG5vdGhpbmcgaGFzIGNoYW5nZWQsIHlvdSdsbCBzZWUgYSBtZXNzYWdlIGxpa2UgdGhpczoKCmBgYApGcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9GSVNINTQ5L2V4LWZvcmsKICogYnJhbmNoICAgICAgICAgICAgbWFpbiAgICAgICAtPiBGRVRDSF9IRUFECiAqIFtuZXcgYnJhbmNoXSAgICAgIG1haW4gICAgICAgLT4gdXBzdHJlYW0vbWFpbgpBbHJlYWR5IHVwIHRvIGRhdGUuCmBgYAoKIyMjIFNldHRpbmcgdGhlIGxvY2FsIGJyYW5jaAoKSWYgeW91IGV4YW1pbmUgeW91ciBmb3JrZWQgY29weSBvZiB0aGUgcmVwbyBvbiBHaXRIdWIsIHlvdSdsbCBub3RpY2UgdGhhdCBpdCBjb250YWlucyAyIGJyYW5jaGVzOiAqKm1haW4qKiBhbmQgKipkZXZlbG9wKiouIEhvd2V2ZXIsIGlmIHlvdSBpbnNwZWN0IHRoZSBsb2NhbCBicmFuY2hlcyBpbiB5b3VyIGN1cnJlbnQgcHJvamVjdCBpbiBSU3R1ZGlvLCB5b3UnbGwgc2VlIHRoYXQgb25seSAqKm1haW4qKiBleGlzdHMgdGhlcmUuCgohW10oaW1hZ2VzL2doX2ZvcmtfYnJhbmNoX3ZpZXdfMS5wbmcpeyB3aWR0aD03MCUgfQoKCjo6OiB0aXAKClRvIHNldCB0aGUgbG9jYWwgYnJhbmNoIHRvICoqZGV2ZWxvcCoqICh3aGVyZSB3ZSdkIGxpa2UgdG8gZG8gb3VyIHdvcmspLCBjbGljayBvbiAqKmRldmVsb3AqKiB1bmRlciAoUkVNT1RFOiBPUklHSU4pLCB3aGljaCB3aWxsIGJyaW5nIHVwIGEgbWVzc2FnZSBib3ggZnJvbSBHaXQgaW5mb3JtaW5nIHlvdSB0aGF0IHlvdSd2ZSBjcmVhdGVkIGFuZCBzd2l0Y2hlZCBvdmVyIHRvIGEgbmV3IGJyYW5jaCBjYWxsZWQgKipkZXZlbG9wKiouCgo6OjoKCiFbXShpbWFnZXMvZ2hfZm9ya19icmFuY2hfdmlld18yLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgohW10oaW1hZ2VzL2doX2ZvcmtfYnJhbmNoX3N3aXRjaC5wbmcpeyB3aWR0aD03MCUgfQoKCjo6OiB0YXNrCgpDbG9zZSB0aGUgd2luZG93IGFuZCB5b3Ugd2lsbCBzZWUgdGhhdCB0aGUgYnJhbmNoIG5hbWUgaW4gdGhlICoqR2l0KiogcGFuZSBvZiBSU3R1ZGlvIGlzIHNldCB0byAqKmRldmVsb3AqKi4gCgo6OjoKCjo6OiB0aXAKCklmIHlvdSBhZ2FpbiBjbGljayBvbiB0aGUgKipkZXZlbG9wKiogYnV0dG9uIGl0IHdpbGwgbm93IHNob3cgdGhhdCB5b3UgY2FuIHRyYWNrIHRoZSAqKmRldmVsb3AqKiBhbmQgKiptYWluKiogYnJhbmNoZXMgb24KCiogeW91ciBsb2NhbCByZXBvCgoqIHlvdXIgcmVtb3RlIG9yaWdpbiAobG9jYXRlZCBhdCBgaHR0cHM6Ly9naXRodWIuY29tL1VTRVJOQU1FL2V4LWZvcmtgKQoKWW91IGNhbiBhbHNvIHRyYWNrIHRoZSAqKm1haW4gYnJhbmNoKiogb24gdGhlIHJlbW90ZSB1cHN0cmVhbSAobG9jYXRlZCBhdCBgaHR0cHM6Ly9naXRodWIuY29tL0ZJU0g1NDkvZXgtZm9ya2ApCgo6OjoKCiFbXShpbWFnZXMvZ2hfZm9ya19icmFuY2hfdmlld18zLnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgpMZXQncyBjcmVhdGUgYSBuZXcgZmlsZSBpbiBvdXIgbG9jYWwgcmVwbyBzbyB3ZSBoYXZlIHNvbWV0aGluZyB0byBjb21taXQgYW5kIHB1c2ggdG8gb3VyIG93biByZW1vdGUgcmVwbywgYW5kIHRoZW4gdWx0aW1hdGVseSBzdWJtaXQgaXQgYXMgYSBwdWxsIHJlcXVlc3QgdG8gdGhlIG9yaWdpbmFsIHJlcG8ncyBvd25lciAoaGVyZSBgRklTSDU0OWApLgoKOjo6IHRhc2sKCkdvIGFoZWFkIGFuZCBtYWtlIGEgc2ltcGxlIFIgc2NyaXB0IGFuZCBjb21taXQgaXQgKEknbSBjYWxsZWQgbWluZSBgc2ltcGxlX2FkZGl0aW9uLlJgKS4KCjo6OgoKIVtdKGltYWdlcy9naF9mb3JrX2V4X3NjcmlwdC5wbmcpeyB3aWR0aD03MCUgfQoKOjo6IHRhc2sKCldoZW4geW91J3JlIGhhcHB5IHdpdGggeW91ciBzY3JpcHQsIGdvIGFoZWFkIGFuZCBjb21taXQgaXQuCgo6OjoKCiFbXShpbWFnZXMvZ2hfZm9ya19leF9jb21taXQucG5nKXsgd2lkdGg9NzAlIH0KCjxicj4KCiMjIFN0ZXAgNTogUHVzaCB0byBHaXRIdWIKCjxicj4KCiFbXShpbWFnZXMvZ2hfZm9ya181LnBuZyl7IHdpZHRoPTcwJSB9Cgo8YnI+CgpOb3cgaXQncyB0aW1lIHRvIHB1c2ggeW91ciBzaW1wbGUgc2NyaXB0IHRvIHlvdXIgb3duIHJlbW90ZSBsb2NhdGVkIGF0CgpgaHR0cHM6Ly9naXRodWIuY29tL1VTRVJOQU1FL2V4LWZvcmtgCgo6OjogdGFzawoKQ2xpY2sgdGhlIGdyZWVuIHVwYXJyb3cgdG8gcHVzaCB5b3VyIG5ldyBzY3JpcHQgdG8gR2l0SHViLgoKOjo6CgohW10oaW1hZ2VzL2doX2ZvcmtfZXhfcHVzaC5wbmcpeyB3aWR0aD03MCUgfQoKPGJyPgoKIyMgU3RlcCA2OiBTdWJtaXQgYSBwdWxsIHJlcXVlc3QKCjxicj4KCiFbXShpbWFnZXMvZ2hfZm9ya182LnBuZyl7IHdpZHRoPTcwJSB9Cgo6OjogdGFzawoKTmF2aWdhdGUgdG8geW91ciBmb3JrZWQgcmVwbyBvbiBHaXRIdWIgd2hlcmUgeW91J2xsIHNlZSBhIG1lc3NhZ2UgYWJvdXQgdGhpcyBicmFuY2ggaGF2aW5nIGEgcmVjZW50IHB1c2ggYW5kIGEgbmV3IGdyZWVuIGJ1dHRvbiBsYWJlbGVkICoqQ29tcGFyZSAmIHB1bGwgcmVxdWVzdCoqLgoKOjo6Cgo8aW1nIHNyYz0iaW1hZ2VzL2doX2ZvcmtfcmVtb3RlX2FoZWFkLnBuZyIgY2xhc3M9Im5vYm9yZGVyIj4KCgo6OjogdGFzawoKT3BlbiBhIHB1bGwgcmVxdWVzdCBieSBjbGlja2luZyBvbiB0aGUgZ3JlZW4gKipDb21wYXJlICYgcHVsbCByZXF1ZXN0KiogYnV0dG9uLgoKOjo6CiAKOjo6IG5vdGUKClRoaXMgd2lsbCB0YWtlIHlvdSB0byB0aGUgc3RhbmRhcmQgcGFnZSBmb3IgYSBwdWxsIHJlcXVlc3QsIGp1c3QgYXMgd2Ugc2F3IGluIHRoZSBbZmVhdHVyZSBicmFuY2ggd29ya2Zsb3ddKCNmZWF0dXJlLWJyYW5jaC13b3JrZmxvdykgYWJvdmUuIEluIHRoaXMgY2FzZSwgaG93ZXZlciwgdGhlcmUgaXMgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCAyIHRoaW5nczoKCiogdGhlIGxvY2F0aW9uIG9mIHRoZSB1cHN0cmVhbSByZXBvICAoaGVyZSBpdCdzIGBodHRwczovL2dpdGh1Yi5jb20vRklTSDU0OS9leC1mb3JrYCkKCiogdGhlICpsb2NhdGlvbnMqIGFuZCAqYnJhbmNoZXMqIChoZXJlICoqZGV2ZWxvcCoqKSBvZiB0aGUgYmFzZSBhbmQgaGVhZCByZXBvc2l0b3JpZXMKCjo6OgoKPGltZyBzcmM9ImltYWdlcy9naF9mb3JrX3N1Ym1pdF9wci5wbmciIGNsYXNzPSJub2JvcmRlciI+CgoKOjo6IHRpcAoKSXQncyBnb29kIHByYWN0aWNlIHRvIGdpdmUgeW91ciBwdWxsIHJlcXVlc3QgYW4gaW5mb3JtYXRpdmUgdGl0bGUgYW5kIGluY2x1ZGUgc29tZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzdWJzdGFuY2Ugb2YgdGhlIHB1bGwgcmVxdWVzdCwgc28gdGhhdCB0aGUgb3duZXIgb2YgdGhlIG9yaWdpbmFsIHJlcG8gaGFzIHNvbWUgdW5kZXJzdGFuZGluZyBvZiB3aGF0IHlvdSd2ZSBkb25lLgoKOjo6Cgo6OjogdGFzawoKR2l2ZSB5b3VyIHB1bGwgcmVxdWVzdCBhIHRpdGxlIGFuZCBkZXNjcmlwdGlvbi4gV2hlbiByZWFkeSwgY2xpY2sgb24gdGhlIGdyZWVuICoqQ3JlYXRlIHB1bGwgcmVxdWVzdCoqIGJ1dHRvbiwgd2hpY2ggd2lsbCB0YWtlIHlvdSB0byBhIHBhZ2Ugc2hvd2luZyB0aGUgZGV0YWlscyBvZiB5b3VyIHB1bGwgcmVxdWVzdC4KCjo6OgogCjxpbWcgc3JjPSJpbWFnZXMvZ2hfZm9ya19zdW1iaXRfcHJfMi5wbmciIGNsYXNzPSJub2JvcmRlciI+CgoKPGJyPgoKPGltZyBzcmM9ImltYWdlcy9naF9mb3JrX3ByX2NyZWF0ZWQucG5nIiBjbGFzcz0ibm9ib3JkZXIiPgoKCjo6OiBzdWNjZXNzCgpObyB5b3UganVzdCBoYXZlIHRvIHdhaXQgZm9yIHRoZSByZXBvJ3Mgb3duZXIgdG8gcmV2aWV3IHRoZSBwdWxsIHJlcXVlc3QgYW5kIGVpdGhlciBhY2NlcHQgaXQgYXMgaXMsIG9yIGNvbWUgYmFjayB0byB5b3Ugd2l0aCBhZGRpdGlvbmFsIGNvbW1lbnRzIG9yIHJlcXVlc3RzIGZvciBjaGFuZ2VzLgoKOjo6Cgo=