What is a version?

  • Contents of a file at a given point in time
  • Metadata (information associated with the file):
    • The author of the file
    • Location
    • Type
    • Timestamp of the last save

What is version control?

  • Version control is a group of systems and processes
    • To manage changes made to documents, programs, and directories
  • Version control is useful for anything that:
    • changes over time, or
    • needs to be shared

  • Git is a popular version control system for computer programming and other projects

  • Open source

  • Scalable (= in terms of projects, collaborators or resources)

  • Benefits of Git:

    • Git stores contents and metadata, so nothing is lost
    • Git notifies users when there is conflicting content in files
    • Git synchronizes across different people and computers

Action

  • Install Git or check whether you have it already for your respective operation system: Linux, MacOs and Windows.

In case you are Windows users, consider installing Unix shell along the way. Alternatively, look for the equivalent command in your respective shell.

Using Git

  • Git commants are run on the shell, also known as the terminal
  • The shell (Zsh, PowerShell,…)
    • is a program for executing commants (e.g., create a folder)
    • can be used to easily preview, modify, or inspect files and directories (= folders)

Action

Useful shell commands

  • Locate your current working directory - pwd
  • List all of the items in the current working directory - ls
  • Change a directory - cd <directory_name>
  • Checking Git version - git --version
  • Create or edit a file - echo

For more commands, see (e.g.) the following article.

Please note that the default command prompt on Windows uses different syntax.

  • Cloud-based hosting service
  • Allows users to store and track their work (= version control)
  • On-demand resources over the internet, such as storage

There are plenty of sites on the Internet where you can upload git repositories with code - e.g. GitLab or BitBucket.

  • Use-cases
    • Storing projects
    • Keeping track of projects and files
    • Collaborating with others
    • Social network
    • Open-source projects

GitHub enhances Git, but cannot be used without it.

Action

  • If you don’t already have a user account on github.com, go there and create one.

Clone a repository (git clone)

  • To get started, let’s try working with a repository created for the purposes of this workshop.

Action

  • Type the following command in your command line:
git clone https://github.com/VGabrhel/git-scientific-communication.git
  • A new repository will be created - a directory with the name git-scientific-communication that contains folders and files.

Action

  • You can look at the URL you used in this example in your browser. There, you’ll see a list of files and lots of links to information about the repository (for example, under “commits” is the history).

Action

  • Switch to the new directory (cd git-scientific-communication) and try looking at the history (gitk or git log). It may be short, but it’s important that there is some. You have a copy of a project on your computer that someone else created!

  • Your contribution to this project will be a write to the repository: specifically, adding a file with your name on it.

    • The name (or distinct identificator) is there to avoid clashes: we need the contributions from all the people going through this course to be different.
  • However, your post will be publicly displayed on the internet. If you don’t want to expose your real name, feel free to use a nickname, a favorite food, or a few random letters instead (be original to avoid conflicts).

    • Whatever you decide to use, it will be referred to as <your_name> further down the line.

Creating a branch

Action

  • Use git branch to find out what branch you are currently on. It should be the master / main branch.

  • This master / main branch is only good to use for commits that the whole team has already agreed on. So when you want to contribute to a project, the first step is to make a new branch for your contribution and switch to that branch. For example:

git branch <your_branch>
git checkout <your_branch>

Pushing changes (git push)

Action

  • In R, create a data file to be shared with others.
# Excplicitedly call the source package
library("datasets")

# Import the USArrests dataset from the package
data("USArrests", package = "datasets")

# Save the object as a data frame
USArrests <- as.data.frame(USArrests)

# Export the data frame as a .csv file with <your_name>
write.csv(USArrests, file = "data/USArrests_<your_name>.csv", row.names = FALSE)

Action

  • Add a file named after your name (or nickname):
git add USArrests_<your_name>.csv
  • Use the git status to observe the indicated changes:
git status
  • Commit the added file to git (git commit):
git commit -m "Add the USArrests data for the respective contributor"
  • Again, use the git status and compare the outcome with the previous status:
git status
  • Now all that’s left to do is “just” merge the change into the original shared repository. But that’s not easy: the repository you cloned cannot be changed by just anyone.
  • A lot of places on the Internet (blogs, news sites, e-shops) work in such a way that a select group of people, “editors”, have the right to change the content as they like.
    • Such editors must be trusted by the project administrator before they are allowed access.
  • With Git, a slightly different mechanism is used: you upload changes to your own shared repository, which only you have the right to change. - You then write a pull request to the owner of the original project. This could be an email saying “Hey, I have some changes at so-and-so address that you might find useful! Add them to your project!”
  • The advantage is that anyone can join the project - if it’s public. You don’t have to ask beforehand, you don’t have to prove you’re a trustworthy person, just change something and send it.
    • Whether the authors of the project like the change or not is another matter - but they can judge the change itself, not the credibility of the author.
  • Services like github.com allow you to make your own shared repository (which will be available on the web) and make it easy to incorporate changes (instead of sending an email, just press a button). Let’s see how to do it.

Action

  • Log in to GitHub and then go to the address you used for git clone. Find the “Fork” button on the top left and click it. This will create your own copy of the repository on GitHub. The address should be something like: https://github.com/<your_github_name>/git-scientific-communication.git.

Action

  • Now, how do you upload changes from your computer to GitHub? For each repository on your computer, Git remembers the addresses where you can download and push changes. The git remote -v command will show you a list of those addresses. For example:
git remote -v
origin https://github.com/VGabrhel/git-scientific-communication.git (fetch)
origin https://github.com/VGabrhel/git-scientific-communication.git (push)
  • This output means that “origin” is the address from which you cloned the repository.

Action

  • Add a similar shortcut for your own repository on GitHub. Don’t forget to replace your name with the name of the account you have on GitHub. (Note that your name appears twice in the command!)

  • git remote add <your_name> https://github.com/<your_github_name>/git-scientific-communication.git and check that it worked:

git remote -v
origin git@github.com:kpsych-fss-mu/git-scientific-communication.git.git (fetch)
origin git@github.com:kpsych-fss-mu/git-scientific-communication.git.git (push)
<your_name> https://github.com/<your_name>/git-scientific-communication (fetch)
<your_name> https://github.com/<your_name>/git-scientific-communication (push)

Action

  • So much for the setup - just do git remote add once for each repository. Then you can upload changes using:
git push --set-upstream origin <your_branch>
  • Which means: push the <your_branch> branch to the address stored under <your_name>.

Action

  • Does it work? Look at https://github.com/<your_github_name>/git-scientific-communication in your browser and make sure your changes are there.

Pull request

  • Now all you have to do is ask the authors of the original project to add the changes from your shared repository to their copy. GitHub has a mechanism for doing this called a pull request.

Action

  • Go to the original project’s page (the address you used for git clone in the beginning). There you should see a notification of your newly uploaded branch with a big green Compare & pull request button. Click on it. If you want, add/change the description of what this change entails. Then hit the next button.

  • If you don’t see the Compare & pull request button, go to the address of your copy of the repository and hit the New pull request button. Select what you want to include, add/change the label, then press Create pull request.

  • You’re done! Now it’s up to the project authors to look at the changes and accept them - or start a discussion about how to make them even better. (You can discuss on the pull request page or via email.)

  • This probably won’t happen for adding a name to the attendance list, but if you needed to work on the change a bit more before incorporating it (even after a few days of discussion), it wouldn’t be a problem. Switch to the <your_branch> branch on your machine, make further commits, and use git push to update your <your_branch> pull request.

Update (git pull)

  • Once your changes - and those of others - have been merged, you can update your local repository.
    • This is the one on your computer.

Action

  • First, switch back to the master branch. Now you won’t be working on <your_branch>; that branch is already committed.

  • This is done with git pull origin master (pull changes from the “master” branch from the address under “origin”). You can use gitk --all or git log to see how the project has evolved in the meantime.

  • It’s always a good idea to do this git pull before you start working on a new change/branch. This will ensure that the project you are changing is “fresh”.

    • Congratulations! You just went through the “round” that most programmers do every day: making a change, pushing it to colleagues for review and incorporation, and pulling changes from others.

Bug reporting (issues)

  • Occasionally, you find a bug in a GitHub project, but you don’t have the time or knowledge to fix it.
    • In this case, you’ll often find a list of reported issues on the GitHub project page under the Issues tab.
    • If you don’t find “your” bug among them, you can report it - just click on New Issue and you can post when the bug occurs, what the program is doing wrong, and what it should be doing instead.
  • Some projects don’t use Issues on GitHub. If you can’t find the Issues tab, check the project documentation to see if there’s a link to the bug list.

README: Information for others

  • If you’re creating a project and want others to contribute to it, you need them to know what your project does, what it’s good for, how it’s used, etc.

  • The README file is used for basic information about the project/repository. This file can include:

    • project name,
    • a brief description of the project (one or two sentences),
    • a short instruction on how to install the project,
    • short instructions on how to run the project,
    • short instructions on how to use the project, or a link to more extensive documentation,
    • if the project has tests, information on how to run them,
    • information on how to get involved in the development of the project,
    • information about the authors of the project,
    • licensing information (more on licensing later).
  • The README should be structured and shouldn’t take the user an hour to read, usually short punchy information with a possible link somewhere else is enough.

    • For example, you don’t need to explain in each project how to install Python. Just say that Python is needed (and in which version) and refer the user to the appropriate instructions.
      • You also need to take into account the inteded audience(s) or who will be reading the README.
  • GitHub (and lots of other similar services) allows you to use a markup language such as Markdown for the README. It’s then possible to use headings, images, etc.

  • And last but not least: open-source projects tend to be in English so that anyone from around the world can participate. Variable names, comments, documentation - everything is primarily in English.

License

  • To make sharing work for legal purposes, it is not enough to upload a piece of code to the Internet. You also have to officially announce that others can play with it.
    • This is because you have a copyright on your code that says others cannot use your program, let alone improve it, unless you give them permission.
      • To formally grant this permission, they use licenses written by lawyers.
  • The issue of licenses can, unfortunately, be quite complex. But if you simplify it to the minimum, you just want to ensure that everyone can use your creation, learn from it, pass it on, and improve it. In that case, choose, for example, the MIT license.
  • In addition, if you want to prevent someone from taking your code and “improving” it and profiting from it without sharing the improvements with others, try the AGPL.
  • Code is most often licensed by putting the license text into a file called LICENSE and adding it to Git. It is a good idea to mention the license in the README file as well.
  • If you want to read more about licenses, I refer you to choosealicense.com, or creativecommons.org and opensource.org.

Next: Hands-on!

Action

  • Consider a project where you want tu use Git (and GitHub; ~15 min)
    • What is the nature of the collaboration in this project?
    • Who are the collaborators?
  • Create the respective repository
  • Secure the main branch from pushing directly to it
  • Set tokens and other security elements
  • Create the README and licence files
  • Push all of the related materials to the repository and create a pull request
  • Let the collaborator review the pushed code.
  • After the changes are merged, checkout to the local main branch and pull the updated remote main branch.

Resources

  • You may find multiple resources for learning git and/or services like GitHub available for free (although sometimes you need to register).

Cheat-sheets

   

Go back to Blog.

LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIHZlcnNpb24gY29udHJvbCB3aXRoIEdpdCBmb3IgYSBtb3JlIGVmZmljaWVudCBjb2xsYWJvcmF0aW9uIgphdXRob3I6ICJWaXQgR2FicmhlbCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lCiAgICBjc3M6ICcvVXNlcnMvdml0Z2FicmhlbC9EZXNrdG9wL0dpdC9QZXJzb25hbC9kYXRhbXVzdGZsb3cvcHVibGljL2Nzcy9jb2Rlci5taW4uYTRmMzMyMjEzYTIxY2U4ZWI1MjE2NzBjNjE0NDcwYzU4OTIzYWFhZjM4NWUyYTczOTgyYzMxZGQ3NjQyZGVjYi5jc3MnCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgojIyAqKldoYXQgaXMgYSB2ZXJzaW9uPyoqCi0gPHU+Q29udGVudHMgb2YgYSBmaWxlIGF0IGEgZ2l2ZW4gcG9pbnQgaW4gdGltZTwvdT4KLSAqKk1ldGFkYXRhKiogKGluZm9ybWF0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgZmlsZSk6CiAgLSAqVGhlIGF1dGhvciBvZiB0aGUgZmlsZSoKICAtICpMb2NhdGlvbioKICAtICpUeXBlKgogIC0gKlRpbWVzdGFtcCBvZiB0aGUgbGFzdCBzYXZlKgogIAojIyAqKldoYXQgaXMgdmVyc2lvbiBjb250cm9sPyoqCi0gKipWZXJzaW9uIGNvbnRyb2wqKiBpcyBhIDx1Pmdyb3VwIG9mIHN5c3RlbXMgYW5kIHByb2Nlc3NlczwvdT4KICAtIFRvIG1hbmFnZSBjaGFuZ2VzIG1hZGUgdG8gZG9jdW1lbnRzLCBwcm9ncmFtcywgYW5kIGRpcmVjdG9yaWVzCi0gVmVyc2lvbiBjb250cm9sIGlzICoqdXNlZnVsKiogZm9yIGFueXRoaW5nIHRoYXQ6CiAgLSAqKmNoYW5nZXMgb3ZlciB0aW1lKiosIG9yCiAgLSAqKm5lZWRzIHRvIGJlIHNoYXJlZCoqIAoKPGltZyBzcmM9InZpei9naXQtbG9nby5wbmciIHdpZHRoPSI0MDAiIGNsYXNzPSJjZW50ZXIiPgoKLSBbR2l0XShodHRwczovL2dpdC1zY20uY29tLykgaXMgYSBwb3B1bGFyICoqdmVyc2lvbiBjb250cm9sIHN5c3RlbSoqIGZvciBjb21wdXRlciBwcm9ncmFtbWluZyBhbmQgb3RoZXIgcHJvamVjdHMgCi0gWyoqT3BlbiBzb3VyY2UqKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvT3Blbi1zb3VyY2Vfc29mdHdhcmUpCi0gKipTY2FsYWJsZSoqICg9IGluIHRlcm1zIG9mIHByb2plY3RzLCBjb2xsYWJvcmF0b3JzIG9yIHJlc291cmNlcykKCi0gKipCZW5lZml0cyoqIG9mIEdpdDoKICAtIEdpdCAqKnN0b3JlcyBjb250ZW50cyBhbmQgbWV0YWRhdGEqKiwgc28gbm90aGluZyBpcyBsb3N0CiAgLSBHaXQgKipub3RpZmllcyoqIHVzZXJzIHdoZW4gdGhlcmUgaXMgKipjb25mbGljdGluZyBjb250ZW50KiogaW4gZmlsZXMKICAtIEdpdCAqKnN5bmNocm9uaXplcyoqIGFjcm9zcyBkaWZmZXJlbnQgcGVvcGxlIGFuZCBjb21wdXRlcnMKCj4gKipBY3Rpb24qKgoKLSBJbnN0YWxsIEdpdCBvciBjaGVjayB3aGV0aGVyIHlvdSBoYXZlIGl0IGFscmVhZHkgZm9yIHlvdXIgcmVzcGVjdGl2ZSBvcGVyYXRpb24gc3lzdGVtOgpbTGludXhdKGh0dHBzOi8vZ2l0aHViLmNvbS9naXQtZ3VpZGVzL2luc3RhbGwtZ2l0P2ZiY2xpZD1Jd0FSMWtpaGhFanoyOTVMUTZzNjVCbEl6eGRUYW1UaFFCY1Z6Qm5CczFaRFEwcEtUNEhPSkxaRjlhV1Q4I2luc3RhbGwtZ2l0LW9uLWxpbnV4KSwgW01hY09zXShodHRwczovL2dpdGh1Yi5jb20vZ2l0LWd1aWRlcy9pbnN0YWxsLWdpdD9mYmNsaWQ9SXdBUjFraWhoRWp6Mjk1TFE2czY1QmxJenhkVGFtVGhRQmNWekJuQnMxWkRRMHBLVDRIT0pMWkY5YVdUOCNpbnN0YWxsLWdpdC1vbi13aW5kb3dzKSBhbmQgW1dpbmRvd3NdKGh0dHBzOi8vZ2l0aHViLmNvbS9naXQtZ3VpZGVzL2luc3RhbGwtZ2l0P2ZiY2xpZD1Jd0FSMWtpaGhFanoyOTVMUTZzNjVCbEl6eGRUYW1UaFFCY1Z6Qm5CczFaRFEwcEtUNEhPSkxaRjlhV1Q4I2luc3RhbGwtZ2l0LW9uLXdpbmRvd3MpLgoKSW4gY2FzZSB5b3UgYXJlICoqV2luZG93cyoqIHVzZXJzLCAqKmNvbnNpZGVyIGluc3RhbGxpbmcgVW5peCBzaGVsbCoqIGFsb25nIHRoZSB3YXkuIEFsdGVybmF0aXZlbHksIGxvb2sgZm9yIHRoZSBbZXF1aXZhbGVudCBjb21tYW5kXShodHRwczovL2dpc3QuZ2l0aHViLmNvbS9qb25sYWJlbGxlL2U4YmE5NGNkMjliOGY2M2ZkN2RkM2M0Zjk1YzFkMjEwKSBpbiB5b3VyIHJlc3BlY3RpdmUgc2hlbGwuCgojIyAqKlVzaW5nIEdpdCoqCi0gR2l0IGNvbW1hbnRzIGFyZSBydW4gb24gdGhlICoqc2hlbGwqKiwgYWxzbyBrbm93biBhcyB0aGUgKip0ZXJtaW5hbCoqCi0gVGhlICoqc2hlbGwqKiAoKlpzaCosICpQb3dlclNoZWxsKiwuLi4pCiAgLSBpcyBhICoqcHJvZ3JhbSBmb3IgZXhlY3V0aW5nIGNvbW1hbnRzKiogKGUuZy4sIGNyZWF0ZSBhIGZvbGRlcikKICAtIGNhbiBiZSB1c2VkIHRvIGVhc2lseSA8dT5wcmV2aWV3LCBtb2RpZnksIG9yIGluc3BlY3QgZmlsZXMgYW5kIGRpcmVjdG9yaWVzPC91PiAoPSBmb2xkZXJzKQogIAo+ICoqQWN0aW9uKioKCi0gT3BlbiB5b3VyIHRlcm1pbmFsIC0gZWl0aGVyIGluc2lkZSBhbm90aGVyIHRvb2wgbGlrZSBbUlN0dWRpb10oaHR0cHM6Ly9zdXBwb3J0LnBvc2l0LmNvL2hjL2VuLXVzL2FydGljbGVzLzExNTAxMDczNzE0OC1Vc2luZy10aGUtUlN0dWRpby1UZXJtaW5hbCkgb3IgYXMgYSBbc3RhbmRhbG9uZSBhcHBdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9hLXF1aWNrLWd1aWRlLXRvLXVzaW5nLWNvbW1hbmQtbGluZS10ZXJtaW5hbC05NjgxNWI5N2I5NTUpLgogIAojIyAqKlVzZWZ1bCBzaGVsbCBjb21tYW5kcyoqCgotICpMb2NhdGUgeW91ciBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5KiAtIGBwd2RgCi0gKkxpc3QgYWxsIG9mIHRoZSBpdGVtcyBpbiB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSogLSBgbHNgCi0gKkNoYW5nZSBhIGRpcmVjdG9yeSogLSBgY2QgPGRpcmVjdG9yeV9uYW1lPmAKLSAqQ2hlY2tpbmcgR2l0IHZlcnNpb24qIC0gYGdpdCAtLXZlcnNpb25gCi0gKkNyZWF0ZSBvciBlZGl0IGEgZmlsZSogLSBgZWNob2AKCkZvciBtb3JlIGNvbW1hbmRzLCBzZWUgKGUuZy4pIHRoZSBmb2xsb3dpbmcgW2FydGljbGVdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9ob3ctdG8tYmVjb21lLWEtY29tbWFuZC1saW5lLXdpemFyZC01ZDc4ZDc1ZmJmMGMpLgoKUGxlYXNlIG5vdGUgdGhhdCB0aGUgWyoqZGVmYXVsdCBjb21tYW5kIHByb21wdCoqXShodHRwczovL3d3dy5tYWtldXNlb2YuY29tL3RhZy9hLWJlZ2lubmVycy1ndWlkZS10by10aGUtd2luZG93cy1jb21tYW5kLWxpbmUpIG9uICoqV2luZG93cyB1c2VzIGRpZmZlcmVudCBzeW50YXgqKi4gCgo8aW1nIHNyYz0idml6L2dpdGh1Yi5wbmciIGFsaWFzPSAiI2dpdGh1YiIgd2lkdGg9IjQwMCIgY2xhc3M9ImNlbnRlciI+CgotIENsb3VkLWJhc2VkIGhvc3RpbmcgKipzZXJ2aWNlKioKLSBBbGxvd3MgdXNlcnMgdG8gc3RvcmUgYW5kIHRyYWNrIHRoZWlyIHdvcmsgKD0gdmVyc2lvbiBjb250cm9sKQotICoqT24tZGVtYW5kIHJlc291cmNlcyoqIG92ZXIgdGhlIGludGVybmV0LCBzdWNoIGFzICoqc3RvcmFnZSoqCgpUaGVyZSBhcmUgcGxlbnR5IG9mIHNpdGVzIG9uIHRoZSBJbnRlcm5ldCB3aGVyZSB5b3UgY2FuIHVwbG9hZCBnaXQgcmVwb3NpdG9yaWVzIHdpdGggY29kZSAtIGUuZy4gW0dpdExhYl0oaHR0cHM6Ly9hYm91dC5naXRsYWIuY29tLykgb3IgW0JpdEJ1Y2tldF0oaHR0cHM6Ly9iaXRidWNrZXQub3JnL3Byb2R1Y3QpLgoKLSA8dT5Vc2UtY2FzZXM8L3U+CiAgLSAqU3RvcmluZyBwcm9qZWN0cyoKICAtICpLZWVwaW5nIHRyYWNrIG9mIHByb2plY3RzIGFuZCBmaWxlcyoKICAtICpDb2xsYWJvcmF0aW5nIHdpdGggb3RoZXJzKgogIC0gKlNvY2lhbCBuZXR3b3JrKgogIC0gKk9wZW4tc291cmNlIHByb2plY3RzKgoKKipHaXRIdWIgZW5oYW5jZXMgR2l0LCBidXQgY2Fubm90IGJlIHVzZWQgd2l0aG91dCBpdC4qKgoKPiAqKkFjdGlvbioqCgotIElmIHlvdSBkb24ndCBhbHJlYWR5IGhhdmUgYSB1c2VyIGFjY291bnQgb24gZ2l0aHViLmNvbSwgZ28gdGhlcmUgYW5kIGNyZWF0ZSBvbmUuCgojIyAqKkNsb25lIGEgcmVwb3NpdG9yeSoqIChgZ2l0IGNsb25lYCkKLSBUbyBnZXQgc3RhcnRlZCwgbGV0J3MgdHJ5IHdvcmtpbmcgd2l0aCBhIHJlcG9zaXRvcnkgY3JlYXRlZCBmb3IgdGhlIHB1cnBvc2VzIG9mIHRoaXMgd29ya3Nob3AuIAoKPiAqKkFjdGlvbioqCgotIFR5cGUgdGhlIGZvbGxvd2luZyBjb21tYW5kIGluIHlvdXIgY29tbWFuZCBsaW5lOgpgYGAKZ2l0IGNsb25lIGh0dHBzOi8vZ2l0aHViLmNvbS9WR2FicmhlbC9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uLmdpdApgYGAKCi0gQSBuZXcgcmVwb3NpdG9yeSB3aWxsIGJlIGNyZWF0ZWQgLSBhIGRpcmVjdG9yeSB3aXRoIHRoZSBuYW1lIGBnaXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uYCB0aGF0IGNvbnRhaW5zIGZvbGRlcnMgYW5kIGZpbGVzLgoKPiAqKkFjdGlvbioqCgotIFlvdSBjYW4gbG9vayBhdCB0aGUgKipVUkwqKiB5b3UgdXNlZCBpbiB0aGlzIGV4YW1wbGUgaW4geW91ciAqKmJyb3dzZXIqKi4gVGhlcmUsIHlvdSdsbCBzZWUgYSAqKmxpc3Qgb2YgZmlsZXMqKiBhbmQgbG90cyBvZiAqKmxpbmtzKiogdG8gaW5mb3JtYXRpb24gYWJvdXQgdGhlIHJlcG9zaXRvcnkgKGZvciBleGFtcGxlLCB1bmRlciAqKiJjb21taXRzIioqIGlzIHRoZSBoaXN0b3J5KS4KCj4gKipBY3Rpb24qKgoKLSBTd2l0Y2ggdG8gdGhlIG5ldyBkaXJlY3RvcnkgKGBjZCBnaXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uYCkgYW5kIHRyeSBsb29raW5nIGF0IHRoZSBoaXN0b3J5IChgZ2l0a2Agb3IgYGdpdCBsb2dgKS4gSXQgbWF5IGJlIHNob3J0LCBidXQgaXQncyBpbXBvcnRhbnQgdGhhdCB0aGVyZSBpcyBzb21lLiBZb3UgaGF2ZSBhIGNvcHkgb2YgYSBwcm9qZWN0IG9uIHlvdXIgY29tcHV0ZXIgdGhhdCBzb21lb25lIGVsc2UgY3JlYXRlZCEKCi0gKipZb3VyIGNvbnRyaWJ1dGlvbiB0byB0aGlzIHByb2plY3QqKiB3aWxsIGJlIGEgKip3cml0ZSB0byB0aGUgcmVwb3NpdG9yeSoqOiBzcGVjaWZpY2FsbHksIDx1PmFkZGluZyBhIGZpbGUgd2l0aCB5b3VyIG5hbWUgb24gaXQ8L3U+LiAKICAtIFRoZSAqKm5hbWUqKiAob3IgZGlzdGluY3QgaWRlbnRpZmljYXRvcikgaXMgdGhlcmUgKip0byBhdm9pZCBjbGFzaGVzKio6IHdlIG5lZWQgdGhlIGNvbnRyaWJ1dGlvbnMgZnJvbSBhbGwgdGhlIHBlb3BsZSBnb2luZyB0aHJvdWdoIHRoaXMgY291cnNlIHRvIGJlIGRpZmZlcmVudC4KCi0gSG93ZXZlciwgeW91ciBwb3N0IHdpbGwgYmUgKipwdWJsaWNseSBkaXNwbGF5ZWQgb24gdGhlIGludGVybmV0KiouIElmIHlvdSBkb24ndCB3YW50IHRvIGV4cG9zZSB5b3VyIHJlYWwgbmFtZSwgZmVlbCBmcmVlIHRvIHVzZSBhICoqbmlja25hbWUqKiwgYSBmYXZvcml0ZSBmb29kLCBvciBhIGZldyByYW5kb20gbGV0dGVycyBpbnN0ZWFkIChiZSBvcmlnaW5hbCB0byBhdm9pZCBjb25mbGljdHMpLiAKICAtIFdoYXRldmVyIHlvdSBkZWNpZGUgdG8gdXNlLCBpdCB3aWxsIGJlIHJlZmVycmVkIHRvIGFzIGA8eW91cl9uYW1lPmAgZnVydGhlciBkb3duIHRoZSBsaW5lLgoKIyMgKipDcmVhdGluZyBhIGJyYW5jaCoqCgo8aW1nIHNyYz0idml6L29jdG9wdXMuanBlZyIgd2lkdGg9IjYwMCIgY2xhc3M9ImNlbnRlciI+Cgo+ICoqQWN0aW9uKiogCgotIFVzZSBgZ2l0IGJyYW5jaGAgdG8gZmluZCBvdXQgd2hhdCBicmFuY2ggeW91IGFyZSBjdXJyZW50bHkgb24uIEl0IHNob3VsZCBiZSB0aGUgYG1hc3RlcmAgLyBgbWFpbmAgW2JyYW5jaF0oaHR0cHM6Ly93d3cudGhlc2VydmVyc2lkZS5jb20vZmVhdHVyZS9XaHktR2l0SHViLXJlbmFtZWQtaXRzLW1hc3Rlci1icmFuY2gtdG8tbWFpbikuCgotIFRoaXMgYG1hc3RlcmAgLyBgbWFpbmAgYnJhbmNoIGlzIG9ubHkgZ29vZCB0byB1c2UgZm9yIGNvbW1pdHMgdGhhdCB0aGUgd2hvbGUgdGVhbSBoYXMgYWxyZWFkeSAqKmFncmVlZCoqIG9uLiBTbyB3aGVuIHlvdSB3YW50IHRvIGNvbnRyaWJ1dGUgdG8gYSBwcm9qZWN0LCB0aGUgPHU+Zmlyc3Qgc3RlcCBpcyB0byBtYWtlIGEgbmV3IGJyYW5jaCBmb3IgeW91ciBjb250cmlidXRpb24gYW5kIHN3aXRjaCB0byB0aGF0IGJyYW5jaDwvdT4uIEZvciBleGFtcGxlOgpgYGAKZ2l0IGJyYW5jaCA8eW91cl9icmFuY2g+CmdpdCBjaGVja291dCA8eW91cl9icmFuY2g+CmBgYAoKIyMgKipQdXNoaW5nIGNoYW5nZXMqKiAoYGdpdCBwdXNoYCkKPiAqKkFjdGlvbioqCgotIEluIFIsIGNyZWF0ZSBhIGRhdGEgZmlsZSB0byBiZSBzaGFyZWQgd2l0aCBvdGhlcnMuCgpgYGAKIyBFeGNwbGljaXRlZGx5IGNhbGwgdGhlIHNvdXJjZSBwYWNrYWdlCmxpYnJhcnkoImRhdGFzZXRzIikKCiMgSW1wb3J0IHRoZSBVU0FycmVzdHMgZGF0YXNldCBmcm9tIHRoZSBwYWNrYWdlCmRhdGEoIlVTQXJyZXN0cyIsIHBhY2thZ2UgPSAiZGF0YXNldHMiKQoKIyBTYXZlIHRoZSBvYmplY3QgYXMgYSBkYXRhIGZyYW1lClVTQXJyZXN0cyA8LSBhcy5kYXRhLmZyYW1lKFVTQXJyZXN0cykKCiMgRXhwb3J0IHRoZSBkYXRhIGZyYW1lIGFzIGEgLmNzdiBmaWxlIHdpdGggPHlvdXJfbmFtZT4Kd3JpdGUuY3N2KFVTQXJyZXN0cywgZmlsZSA9ICJkYXRhL1VTQXJyZXN0c188eW91cl9uYW1lPi5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgo+ICoqQWN0aW9uKioKCi0gQWRkIGEgZmlsZSBuYW1lZCBhZnRlciB5b3VyIG5hbWUgKG9yIG5pY2tuYW1lKToKYGBgCmdpdCBhZGQgVVNBcnJlc3RzXzx5b3VyX25hbWU+LmNzdgpgYGAKCi0gVXNlIHRoZSBgZ2l0IHN0YXR1c2AgdG8gb2JzZXJ2ZSB0aGUgaW5kaWNhdGVkIGNoYW5nZXM6CmBgYApnaXQgc3RhdHVzCmBgYAoKLSBDb21taXQgdGhlIGFkZGVkIGZpbGUgdG8gZ2l0IChgZ2l0IGNvbW1pdGApOgpgYGAKZ2l0IGNvbW1pdCAtbSAiQWRkIHRoZSBVU0FycmVzdHMgZGF0YSBmb3IgdGhlIHJlc3BlY3RpdmUgY29udHJpYnV0b3IiCmBgYAoKLSBBZ2FpbiwgdXNlIHRoZSBgZ2l0IHN0YXR1c2AgYW5kIGNvbXBhcmUgdGhlIG91dGNvbWUgd2l0aCB0aGUgcHJldmlvdXMgc3RhdHVzOgpgYGAKZ2l0IHN0YXR1cwpgYGAKCi0gTm93IGFsbCB0aGF0J3MgbGVmdCB0byBkbyBpcyAianVzdCIgKiptZXJnZSB0aGUgY2hhbmdlIGludG8gdGhlIG9yaWdpbmFsKiogc2hhcmVkIHJlcG9zaXRvcnkuIEJ1dCB0aGF0J3Mgbm90IGVhc3k6IHRoZSByZXBvc2l0b3J5IHlvdSBjbG9uZWQgW2Nhbm5vdCBiZSBjaGFuZ2VkXShodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9yZXBvc2l0b3JpZXMvY29uZmlndXJpbmctYnJhbmNoZXMtYW5kLW1lcmdlcy1pbi15b3VyLXJlcG9zaXRvcnkvZGVmaW5pbmctdGhlLW1lcmdlYWJpbGl0eS1vZi1wdWxsLXJlcXVlc3RzL21hbmFnaW5nLWEtYnJhbmNoLXByb3RlY3Rpb24tcnVsZSkgYnkganVzdCBhbnlvbmUuCi0gQSBsb3Qgb2YgcGxhY2VzIG9uIHRoZSBJbnRlcm5ldCAoKipibG9ncywgbmV3cyBzaXRlcywgZS1zaG9wcyoqKSB3b3JrIGluIHN1Y2ggYSB3YXkgdGhhdCBhICoqc2VsZWN0IGdyb3VwIG9mIHBlb3BsKiplLCAiZWRpdG9ycyIsIGhhdmUgdGhlICoqcmlnaHQgdG8gY2hhbmdlIHRoZSBjb250ZW50KiogYXMgdGhleSBsaWtlLiAKICAtIFN1Y2ggZWRpdG9ycyBtdXN0IGJlICoqdHJ1c3RlZCBieSB0aGUgcHJvamVjdCBhZG1pbmlzdHJhdG9yKiogYmVmb3JlIHRoZXkgYXJlIGFsbG93ZWQgYWNjZXNzLgotIFdpdGggKipHaXQqKiwgYSBzbGlnaHRseSAqKmRpZmZlcmVudCBtZWNoYW5pc20qKiBpcyB1c2VkOiB5b3UgKip1cGxvYWQgY2hhbmdlcyB0byB5b3VyIG93biBzaGFyZWQgcmVwb3NpdG9yeSoqLCB3aGljaCBvbmx5IHlvdSBoYXZlIHRoZSByaWdodCB0byBjaGFuZ2UuICAgLSBZb3UgdGhlbiAqKndyaXRlIGEgcHVsbCByZXF1ZXN0KiogdG8gdGhlICoqb3duZXIgb2YgdGhlIG9yaWdpbmFsIHByb2plY3QqKi4gVGhpcyBjb3VsZCBiZSBhbiBlbWFpbCBzYXlpbmcgKiJIZXksIEkgaGF2ZSBzb21lIGNoYW5nZXMgYXQgc28tYW5kLXNvIGFkZHJlc3MgdGhhdCB5b3UgbWlnaHQgZmluZCB1c2VmdWwhIEFkZCB0aGVtIHRvIHlvdXIgcHJvamVjdCEiKgotIFRoZSBhZHZhbnRhZ2UgaXMgdGhhdCAqKmFueW9uZSBjYW4qKiBqb2luIHRoZSBwcm9qZWN0IC0gaWYgaXQncyBbKipwdWJsaWMqKl0oaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vcmVwb3NpdG9yaWVzL2NyZWF0aW5nLWFuZC1tYW5hZ2luZy1yZXBvc2l0b3JpZXMvYWJvdXQtcmVwb3NpdG9yaWVzKS4gKipZb3UgZG9uJ3QgaGF2ZSB0byBhc2sgYmVmb3JlaGFuZCoqLCB5b3UgZG9uJ3QgaGF2ZSB0byBwcm92ZSB5b3UncmUgYSB0cnVzdHdvcnRoeSBwZXJzb24sIGp1c3QgY2hhbmdlIHNvbWV0aGluZyBhbmQgc2VuZCBpdC4gCiAgLSA8dT5XaGV0aGVyIHRoZSBhdXRob3JzIG9mIHRoZSBwcm9qZWN0IGxpa2UgdGhlIGNoYW5nZSBvciBub3QgaXMgYW5vdGhlciBtYXR0ZXI8L3U+IC0gYnV0IHRoZXkgY2FuIGp1ZGdlIHRoZSBjaGFuZ2UgaXRzZWxmLCBub3QgdGhlIGNyZWRpYmlsaXR5IG9mIHRoZSBhdXRob3IuCi0gKipTZXJ2aWNlcyoqIGxpa2UgZ2l0aHViLmNvbSBhbGxvdyB5b3UgdG8gbWFrZSB5b3VyIG93biAqKnNoYXJlZCByZXBvc2l0b3J5KiogKHdoaWNoIHdpbGwgYmUgKiphdmFpbGFibGUgb24gdGhlIHdlYioqKSBhbmQgbWFrZSBpdCBlYXN5IHRvICoqaW5jb3Jwb3JhdGUgY2hhbmdlcyoqIChpbnN0ZWFkIG9mIHNlbmRpbmcgYW4gZW1haWwsIGp1c3QgcHJlc3MgYSBidXR0b24pLiBMZXQncyBzZWUgaG93IHRvIGRvIGl0LgoKPiAqKkFjdGlvbioqCgotICoqTG9nIGluIHRvIEdpdEh1YioqIGFuZCB0aGVuIGdvIHRvIHRoZSAqKmFkZHJlc3MqKiB5b3UgdXNlZCBmb3IgYGdpdCBjbG9uZWAuIEZpbmQgdGhlICoqIkZvcmsiKiogYnV0dG9uIG9uIHRoZSB0b3AgbGVmdCBhbmQgY2xpY2sgaXQuIFRoaXMgd2lsbCBjcmVhdGUgeW91ciBvd24gY29weSBvZiB0aGUgcmVwb3NpdG9yeSBvbiBHaXRIdWIuIFRoZSBhZGRyZXNzIHNob3VsZCBiZSBzb21ldGhpbmcgbGlrZTogYGh0dHBzOi8vZ2l0aHViLmNvbS88eW91cl9naXRodWJfbmFtZT4vZ2l0LXNjaWVudGlmaWMtY29tbXVuaWNhdGlvbi5naXRgLgoKPiAqKkFjdGlvbioqCgotIE5vdywgaG93IGRvIHlvdSA8dT51cGxvYWQgY2hhbmdlcyBmcm9tIHlvdXIgY29tcHV0ZXIgdG8gR2l0SHViPC91Pj8gRm9yIGVhY2ggcmVwb3NpdG9yeSBvbiB5b3VyIGNvbXB1dGVyLCBHaXQgcmVtZW1iZXJzIHRoZSBhZGRyZXNzZXMgd2hlcmUgeW91IGNhbiBkb3dubG9hZCBhbmQgcHVzaCBjaGFuZ2VzLiBUaGUgYGdpdCByZW1vdGUgLXYgY29tbWFuZGAgd2lsbCBzaG93IHlvdSBhIGxpc3Qgb2YgdGhvc2UgYWRkcmVzc2VzLiBGb3IgZXhhbXBsZToKYGBgCmdpdCByZW1vdGUgLXYKb3JpZ2luIGh0dHBzOi8vZ2l0aHViLmNvbS9WR2FicmhlbC9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uLmdpdCAoZmV0Y2gpCm9yaWdpbiBodHRwczovL2dpdGh1Yi5jb20vVkdhYnJoZWwvZ2l0LXNjaWVudGlmaWMtY29tbXVuaWNhdGlvbi5naXQgKHB1c2gpCmBgYAotIFRoaXMgb3V0cHV0IG1lYW5zIHRoYXQgIm9yaWdpbiIgaXMgdGhlIGFkZHJlc3MgZnJvbSB3aGljaCB5b3UgY2xvbmVkIHRoZSByZXBvc2l0b3J5LgoKPiAqKkFjdGlvbioqCgotIEFkZCBhIHNpbWlsYXIgc2hvcnRjdXQgZm9yIHlvdXIgb3duIHJlcG9zaXRvcnkgb24gR2l0SHViLiBEb24ndCBmb3JnZXQgdG8gcmVwbGFjZSB5b3VyIG5hbWUgd2l0aCB0aGUgbmFtZSBvZiB0aGUgYWNjb3VudCB5b3UgaGF2ZSBvbiBHaXRIdWIuIChOb3RlIHRoYXQgeW91ciBuYW1lIGFwcGVhcnMgdHdpY2UgaW4gdGhlIGNvbW1hbmQhKQoKLSBgZ2l0IHJlbW90ZSBhZGQgPHlvdXJfbmFtZT4gaHR0cHM6Ly9naXRodWIuY29tLzx5b3VyX2dpdGh1Yl9uYW1lPi9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uLmdpdGAgYW5kIGNoZWNrIHRoYXQgaXQgd29ya2VkOgpgYGAKZ2l0IHJlbW90ZSAtdgpvcmlnaW4gZ2l0QGdpdGh1Yi5jb206a3BzeWNoLWZzcy1tdS9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uLmdpdC5naXQgKGZldGNoKQpvcmlnaW4gZ2l0QGdpdGh1Yi5jb206a3BzeWNoLWZzcy1tdS9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uLmdpdC5naXQgKHB1c2gpCjx5b3VyX25hbWU+IGh0dHBzOi8vZ2l0aHViLmNvbS88eW91cl9uYW1lPi9naXQtc2NpZW50aWZpYy1jb21tdW5pY2F0aW9uIChmZXRjaCkKPHlvdXJfbmFtZT4gaHR0cHM6Ly9naXRodWIuY29tLzx5b3VyX25hbWU+L2dpdC1zY2llbnRpZmljLWNvbW11bmljYXRpb24gKHB1c2gpCmBgYAoKPiAqKkFjdGlvbioqCgotIFNvIG11Y2ggZm9yIHRoZSBzZXR1cCAtIGp1c3QgZG8gZ2l0IHJlbW90ZSBhZGQgb25jZSBmb3IgZWFjaCByZXBvc2l0b3J5LiBUaGVuIHlvdSBjYW4gdXBsb2FkIGNoYW5nZXMgdXNpbmc6CmBgYApnaXQgcHVzaCAtLXNldC11cHN0cmVhbSBvcmlnaW4gPHlvdXJfYnJhbmNoPgpgYGAKCi0gV2hpY2ggbWVhbnM6IHB1c2ggdGhlPC91PiBgPHlvdXJfYnJhbmNoPmAgPHU+YnJhbmNoIHRvIHRoZSBhZGRyZXNzIHN0b3JlZCB1bmRlcjwvdT4gYDx5b3VyX25hbWU+YC4KCj4gKipBY3Rpb24qKgoKLSBEb2VzIGl0IHdvcms/IExvb2sgYXQgYGh0dHBzOi8vZ2l0aHViLmNvbS88eW91cl9naXRodWJfbmFtZT4vZ2l0LXNjaWVudGlmaWMtY29tbXVuaWNhdGlvbmAgaW4geW91ciBicm93c2VyIGFuZCBtYWtlIHN1cmUgeW91ciBjaGFuZ2VzIGFyZSB0aGVyZS4KCiMjICoqUHVsbCByZXF1ZXN0KioKCi0gTm93IGFsbCB5b3UgaGF2ZSB0byBkbyBpcyA8dT5hc2sgdGhlIGF1dGhvcnMgb2YgdGhlIG9yaWdpbmFsIHByb2plY3QgdG8gYWRkIHRoZSBjaGFuZ2VzIGZyb20geW91ciBzaGFyZWQgcmVwb3NpdG9yeSB0byB0aGVpciBjb3B5PC91Pi4gR2l0SHViIGhhcyBhIG1lY2hhbmlzbSBmb3IgZG9pbmcgdGhpcyBjYWxsZWQgYSBbKipwdWxsIHJlcXVlc3QqKl0oaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vcHVsbC1yZXF1ZXN0cy9jb2xsYWJvcmF0aW5nLXdpdGgtcHVsbC1yZXF1ZXN0cy9wcm9wb3NpbmctY2hhbmdlcy10by15b3VyLXdvcmstd2l0aC1wdWxsLXJlcXVlc3RzL2Fib3V0LXB1bGwtcmVxdWVzdHMpLgoKPiAqKkFjdGlvbioqCgotIEdvIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0J3MgcGFnZSAodGhlIGFkZHJlc3MgeW91IHVzZWQgZm9yIGBnaXQgY2xvbmVgIGluIHRoZSBiZWdpbm5pbmcpLiBUaGVyZSB5b3Ugc2hvdWxkIHNlZSBhIG5vdGlmaWNhdGlvbiBvZiB5b3VyIG5ld2x5IHVwbG9hZGVkIGJyYW5jaCB3aXRoIGEgYmlnIGdyZWVuICoqQ29tcGFyZSAmIHB1bGwgcmVxdWVzdCBidXR0b24qKi4gKipDbGljayoqIG9uIGl0LiBJZiB5b3Ugd2FudCwgKiphZGQvY2hhbmdlIHRoZSBkZXNjcmlwdGlvbioqIG9mIHdoYXQgdGhpcyBjaGFuZ2UgZW50YWlscy4gVGhlbiBoaXQgdGhlIG5leHQgYnV0dG9uLgoKLSBJZiB5b3UgZG9uJ3Qgc2VlIHRoZSBDb21wYXJlICYgcHVsbCByZXF1ZXN0IGJ1dHRvbiwgZ28gdG8gdGhlICoqYWRkcmVzcyBvZiB5b3VyIGNvcHkgb2YgdGhlIHJlcG9zaXRvcnkqKiBhbmQgaGl0IHRoZSAqKk5ldyBwdWxsIHJlcXVlc3QqKiBidXR0b24uICoqU2VsZWN0Kiogd2hhdCB5b3Ugd2FudCB0byBpbmNsdWRlLCAqKmFkZC9jaGFuZ2UqKiB0aGUgbGFiZWwsIHRoZW4gcHJlc3MgKipDcmVhdGUgcHVsbCByZXF1ZXN0KiouCi0gKipZb3UncmUgZG9uZSoqISBOb3cgaXQncyB1cCB0byB0aGUgKipwcm9qZWN0IGF1dGhvcnMqKiB0byBsb29rIGF0IHRoZSBjaGFuZ2VzIGFuZCAqKmFjY2VwdCoqIHRoZW0gLSBvciBzdGFydCBhICoqZGlzY3Vzc2lvbioqIGFib3V0IGhvdyB0byBtYWtlIHRoZW0gZXZlbiBiZXR0ZXIuIChZb3UgY2FuIGRpc2N1c3Mgb24gdGhlIHB1bGwgcmVxdWVzdCBwYWdlIG9yIHZpYSBlbWFpbC4pCi0gVGhpcyBwcm9iYWJseSB3b24ndCBoYXBwZW4gZm9yIGFkZGluZyBhIG5hbWUgdG8gdGhlIGF0dGVuZGFuY2UgbGlzdCwgYnV0IGlmIHlvdSBuZWVkZWQgdG8gd29yayBvbiB0aGUgY2hhbmdlIGEgYml0IG1vcmUgYmVmb3JlIGluY29ycG9yYXRpbmcgaXQgKGV2ZW4gYWZ0ZXIgYSBmZXcgZGF5cyBvZiBkaXNjdXNzaW9uKSwgaXQgd291bGRuJ3QgYmUgYSBwcm9ibGVtLiAqKlN3aXRjaCB0byB0aGUqKiBgPHlvdXJfYnJhbmNoPmAgKipicmFuY2ggb24geW91ciBtYWNoaW5lKiosIG1ha2UgKipmdXJ0aGVyIGNvbW1pdHMqKiwgYW5kIHVzZSAqKmdpdCBwdXNoIHRvIHVwZGF0ZSoqIHlvdXIgYDx5b3VyX2JyYW5jaD5gICoqcHVsbCByZXF1ZXN0KiouCgojIyAqKlVwZGF0ZSoqIChgZ2l0IHB1bGxgKQotIE9uY2UgeW91ciAqKmNoYW5nZXMqKiAtIGFuZCB0aG9zZSBvZiBvdGhlcnMgLSBoYXZlIGJlZW4gKiptZXJnZWQqKiwgeW91IGNhbiAqKnVwZGF0ZSB5b3VyIGxvY2FsIHJlcG9zaXRvcnkqKi4KICAtIFRoaXMgaXMgdGhlICoqb25lIG9uIHlvdXIgY29tcHV0ZXIqKi4KCj4gKipBY3Rpb24qKiAKCi0gRmlyc3QsICoqc3dpdGNoIGJhY2sqKiB0byB0aGUgYG1hc3RlcmAgYnJhbmNoLiBOb3cgeW91IHdvbid0IGJlIHdvcmtpbmcgb24gYDx5b3VyX2JyYW5jaD5gOyB0aGF0IGJyYW5jaCBpcyBhbHJlYWR5IGNvbW1pdHRlZC4KLSBUaGlzIGlzIGRvbmUgd2l0aCBgZ2l0IHB1bGwgb3JpZ2luIG1hc3RlcmAgKHB1bGwgY2hhbmdlcyBmcm9tIHRoZSAibWFzdGVyIiBicmFuY2ggZnJvbSB0aGUgYWRkcmVzcyB1bmRlciAib3JpZ2luIikuIFlvdSBjYW4gdXNlIGBnaXRrIC0tYWxsYCBvciBgZ2l0IGxvZ2AgdG8gc2VlIGhvdyB0aGUgcHJvamVjdCBoYXMgZXZvbHZlZCBpbiB0aGUgbWVhbnRpbWUuCgotIEl0J3MgYWx3YXlzIGEgZ29vZCBpZGVhIHRvIGRvIHRoaXMgYGdpdCBwdWxsYCAqKmJlZm9yZSB5b3Ugc3RhcnQgd29ya2luZyBvbiBhIG5ldyBjaGFuZ2UvYnJhbmNoKiouIFRoaXMgd2lsbCBlbnN1cmUgdGhhdCB0aGUgcHJvamVjdCB5b3UgYXJlIGNoYW5naW5nIGlzICoqImZyZXNoIioqLgogIC0gQ29uZ3JhdHVsYXRpb25zISBZb3UganVzdCB3ZW50IHRocm91Z2ggdGhlICJyb3VuZCIgdGhhdCBtb3N0IHByb2dyYW1tZXJzIGRvIGV2ZXJ5IGRheTogbWFraW5nIGEgY2hhbmdlLCBwdXNoaW5nIGl0IHRvIGNvbGxlYWd1ZXMgZm9yIHJldmlldyBhbmQgaW5jb3Jwb3JhdGlvbiwgYW5kIHB1bGxpbmcgY2hhbmdlcyBmcm9tIG90aGVycy4KICAKPGltZyBzcmM9InZpei9naXQtd29ya2Zsb3cucG5nIiB3aWR0aD0iNjAwIiBjbGFzcz0iY2VudGVyIj4KCiMjICoqQnVnIHJlcG9ydGluZyoqIChpc3N1ZXMpCgotIE9jY2FzaW9uYWxseSwgeW91ICoqZmluZCBhIGJ1ZyoqIGluIGEgR2l0SHViIHByb2plY3QsIGJ1dCB5b3UgKipkb24ndCBoYXZlIHRoZSB0aW1lIG9yIGtub3dsZWRnZSB0byBmaXggaXQqKi4gCiAgLSBJbiB0aGlzIGNhc2UsIHlvdSdsbCBvZnRlbiBmaW5kIGEgbGlzdCBvZiByZXBvcnRlZCBbKippc3N1ZXMqKl0oaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vaXNzdWVzL3RyYWNraW5nLXlvdXItd29yay13aXRoLWlzc3Vlcy9hYm91dC1pc3N1ZXMpIG9uIHRoZSBHaXRIdWIgcHJvamVjdCBwYWdlIHVuZGVyIHRoZSAqKklzc3VlcyB0YWIqKi4gCiAgLSBJZiB5b3UgZG9uJ3QgZmluZCAieW91ciIgYnVnIGFtb25nIHRoZW0sIHlvdSBjYW4gcmVwb3J0IGl0IC0ganVzdCBjbGljayBvbiAqKk5ldyBJc3N1ZSoqIGFuZCB5b3UgY2FuIDx1PnBvc3Qgd2hlbiB0aGUgYnVnIG9jY3Vycywgd2hhdCB0aGUgcHJvZ3JhbSBpcyBkb2luZyB3cm9uZywgYW5kIHdoYXQgaXQgc2hvdWxkIGJlIGRvaW5nIGluc3RlYWQ8L3U+LgotIFNvbWUgcHJvamVjdHMgZG9uJ3QgdXNlIElzc3VlcyBvbiBHaXRIdWIuIElmIHlvdSBjYW4ndCBmaW5kIHRoZSBJc3N1ZXMgdGFiLCBjaGVjayB0aGUgcHJvamVjdCBkb2N1bWVudGF0aW9uIHRvIHNlZSBpZiB0aGVyZSdzIGEgbGluayB0byB0aGUgYnVnIGxpc3QuCgojIyAqKlJFQURNRSoqOiBJbmZvcm1hdGlvbiBmb3Igb3RoZXJzCi0gPHU+SWYgeW91J3JlIGNyZWF0aW5nIGEgcHJvamVjdCBhbmQgd2FudCBvdGhlcnMgdG8gY29udHJpYnV0ZSB0byBpdCwgeW91IG5lZWQgdGhlbSB0byBrbm93IHdoYXQgeW91ciBwcm9qZWN0IGRvZXMsIHdoYXQgaXQncyBnb29kIGZvciwgaG93IGl0J3MgdXNlZDwvdT4sIGV0Yy4KCi0gVGhlIFsqKlJFQURNRSoqXShodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9yZXBvc2l0b3JpZXMvbWFuYWdpbmcteW91ci1yZXBvc2l0b3J5cy1zZXR0aW5ncy1hbmQtZmVhdHVyZXMvY3VzdG9taXppbmcteW91ci1yZXBvc2l0b3J5L2Fib3V0LXJlYWRtZXMpIGZpbGUgaXMgdXNlZCBmb3IgKipiYXNpYyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcHJvamVjdC9yZXBvc2l0b3J5KiouIFRoaXMgZmlsZSBjYW4gaW5jbHVkZToKICAtICpwcm9qZWN0IG5hbWUqLAogIC0gKmEgYnJpZWYgZGVzY3JpcHRpb24gb2YgdGhlIHByb2plY3QgKG9uZSBvciB0d28gc2VudGVuY2VzKSosCiAgLSAqYSBzaG9ydCBpbnN0cnVjdGlvbiBvbiBob3cgdG8gaW5zdGFsbCB0aGUgcHJvamVjdCosCiAgLSAqc2hvcnQgaW5zdHJ1Y3Rpb25zIG9uIGhvdyB0byBydW4gdGhlIHByb2plY3QqLAogIC0gKnNob3J0IGluc3RydWN0aW9ucyBvbiBob3cgdG8gdXNlIHRoZSBwcm9qZWN0LCBvciBhIGxpbmsgdG8gbW9yZSBleHRlbnNpdmUgZG9jdW1lbnRhdGlvbiosCiAgLSAqaWYgdGhlIHByb2plY3QgaGFzIHRlc3RzLCBpbmZvcm1hdGlvbiBvbiBob3cgdG8gcnVuIHRoZW0qLAogIC0gKmluZm9ybWF0aW9uIG9uIGhvdyB0byBnZXQgaW52b2x2ZWQgaW4gdGhlIGRldmVsb3BtZW50IG9mIHRoZSBwcm9qZWN0KiwKICAtICppbmZvcm1hdGlvbiBhYm91dCB0aGUgYXV0aG9ycyBvZiB0aGUgcHJvamVjdCosCiAgLSAqbGljZW5zaW5nIGluZm9ybWF0aW9uIChtb3JlIG9uIGxpY2Vuc2luZyBsYXRlcikqLgoKLSBUaGUgUkVBRE1FIHNob3VsZCBiZSAqKnN0cnVjdHVyZWQqKiBhbmQgc2hvdWxkbid0IHRha2UgdGhlIHVzZXIgYW4gaG91ciB0byByZWFkLCAqKnVzdWFsbHkgc2hvcnQgcHVuY2h5IGluZm9ybWF0aW9uIHdpdGggYSBwb3NzaWJsZSBsaW5rIHNvbWV3aGVyZSBlbHNlIGlzIGVub3VnaCoqLiAKICAtIEZvciBleGFtcGxlLCB5b3UgZG9uJ3QgbmVlZCB0byBleHBsYWluIGluIGVhY2ggcHJvamVjdCBob3cgdG8gaW5zdGFsbCBQeXRob24uIEp1c3Qgc2F5IHRoYXQgUHl0aG9uIGlzIG5lZWRlZCAoYW5kIGluIHdoaWNoIHZlcnNpb24pIGFuZCByZWZlciB0aGUgdXNlciB0byB0aGUgYXBwcm9wcmlhdGUgaW5zdHJ1Y3Rpb25zLiAKICAgIC0gWW91IGFsc28gbmVlZCB0byB0YWtlIGludG8gYWNjb3VudCB0aGUgKippbnRlZGVkIGF1ZGllbmNlKHMpKiogb3IgKip3aG8gd2lsbCBiZSByZWFkaW5nKiogdGhlIFJFQURNRS4KLSBHaXRIdWIgKGFuZCBsb3RzIG9mIG90aGVyIHNpbWlsYXIgc2VydmljZXMpIGFsbG93cyB5b3UgdG8gKip1c2UgYSBtYXJrdXAgbGFuZ3VhZ2UqKiBzdWNoIGFzICoqTWFya2Rvd24qKiBmb3IgdGhlIFJFQURNRS4gSXQncyB0aGVuIHBvc3NpYmxlIHRvIHVzZSBoZWFkaW5ncywgaW1hZ2VzLCBldGMuCi0gQW5kIGxhc3QgYnV0IG5vdCBsZWFzdDogKipvcGVuLXNvdXJjZSBwcm9qZWN0cyB0ZW5kIHRvIGJlIGluIEVuZ2xpc2gqKiBzbyB0aGF0IGFueW9uZSBmcm9tIGFyb3VuZCB0aGUgd29ybGQgY2FuIHBhcnRpY2lwYXRlLiAqKlZhcmlhYmxlIG5hbWVzLCBjb21tZW50cywgZG9jdW1lbnRhdGlvbioqIC0gZXZlcnl0aGluZyBpcyAqKnByaW1hcmlseSBpbiBFbmdsaXNoKiouCgojIyAqKkxpY2Vuc2UqKgotIFRvIG1ha2UgKipzaGFyaW5nIHdvcmsgZm9yIGxlZ2FsIHB1cnBvc2VzKiosIGl0IGlzICoqbm90IGVub3VnaCB0byB1cGxvYWQgYSBwaWVjZSBvZiBjb2RlIHRvIHRoZSBJbnRlcm5ldCoqLiBZb3UgYWxzbyBoYXZlIHRvICoqb2ZmaWNpYWxseSBhbm5vdW5jZSoqIHRoYXQgb3RoZXJzIGNhbiBwbGF5IHdpdGggaXQuIAogIC0gVGhpcyBpcyBiZWNhdXNlICoqeW91IGhhdmUgYSBjb3B5cmlnaHQqKiBvbiB5b3VyIGNvZGUgdGhhdCBzYXlzICoqb3RoZXJzIGNhbm5vdCB1c2UgeW91ciBwcm9ncmFtKiosIGxldCBhbG9uZSBpbXByb3ZlIGl0LCAqKnVubGVzcyB5b3UgZ2l2ZSB0aGVtIHBlcm1pc3Npb24uKiogCiAgICAtIDx1PlRvIGZvcm1hbGx5IGdyYW50IHRoaXMgcGVybWlzc2lvbiwgdGhleSB1c2UgbGljZW5zZXMgd3JpdHRlbiBieSBsYXd5ZXJzPC91Pi4KLSBUaGUgaXNzdWUgb2YgbGljZW5zZXMgY2FuLCB1bmZvcnR1bmF0ZWx5LCBiZSBxdWl0ZSBjb21wbGV4LiBCdXQgaWYgeW91IHNpbXBsaWZ5IGl0IHRvIHRoZSBtaW5pbXVtLCB5b3UganVzdCB3YW50IHRvIGVuc3VyZSB0aGF0IGV2ZXJ5b25lIGNhbiB1c2UgeW91ciBjcmVhdGlvbiwgbGVhcm4gZnJvbSBpdCwgcGFzcyBpdCBvbiwgYW5kIGltcHJvdmUgaXQuIEluIHRoYXQgY2FzZSwgY2hvb3NlLCBmb3IgZXhhbXBsZSwgdGhlIFsqTUlUIGxpY2Vuc2UqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NSVRfTGljZW5zZSkuCi0gSW4gYWRkaXRpb24sIGlmIHlvdSB3YW50IHRvIHByZXZlbnQgc29tZW9uZSBmcm9tIHRha2luZyB5b3VyIGNvZGUgYW5kICJpbXByb3ZpbmciIGl0IGFuZCBwcm9maXRpbmcgZnJvbSBpdCB3aXRob3V0IHNoYXJpbmcgdGhlIGltcHJvdmVtZW50cyB3aXRoIG90aGVycywgdHJ5IHRoZSBbKkFHUEwqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BZmZlcm9fR2VuZXJhbF9QdWJsaWNfTGljZW5zZSkuCi0gQ29kZSBpcyBtb3N0IG9mdGVuIGxpY2Vuc2VkIGJ5IHB1dHRpbmcgdGhlIGxpY2Vuc2UgdGV4dCBpbnRvIGEgZmlsZSBjYWxsZWQgYExJQ0VOU0VgIGFuZCBhZGRpbmcgaXQgdG8gR2l0LiBJdCBpcyBhIGdvb2QgaWRlYSB0byBtZW50aW9uIHRoZSBsaWNlbnNlIGluIHRoZSBgUkVBRE1FYCBmaWxlIGFzIHdlbGwuCi0gSWYgeW91IHdhbnQgdG8gcmVhZCBtb3JlIGFib3V0IGxpY2Vuc2VzLCBJIHJlZmVyIHlvdSB0byBjaG9vc2VhbGljZW5zZS5jb20sIG9yIGNyZWF0aXZlY29tbW9ucy5vcmcgYW5kIG9wZW5zb3VyY2Uub3JnLgoKIyMgKipOZXh0OiBIYW5kcy1vbiEqKgoKPiAqKkFjdGlvbioqCgotICoqQ29uc2lkZXIgYSBwcm9qZWN0Kiogd2hlcmUgeW91IHdhbnQgdHUgdXNlIEdpdCAoYW5kIEdpdEh1YjsgKn4xNSBtaW4qKQogIC0gV2hhdCBpcyB0aGUgKipuYXR1cmUgb2YgdGhlIGNvbGxhYm9yYXRpb24qKiBpbiB0aGlzIHByb2plY3Q/IAogIC0gV2hvIGFyZSB0aGUgKipjb2xsYWJvcmF0b3JzKio/CiAgCi0gKipDcmVhdGUqKiB0aGUgcmVzcGVjdGl2ZSAqKnJlcG9zaXRvcnkqKgogLSBTZWN1cmUgdGhlIG1haW4gYnJhbmNoIGZyb20gcHVzaGluZyBkaXJlY3RseSB0byBpdAogLSBTZXQgKip0b2tlbnMqKiBhbmQgb3RoZXIgKipzZWN1cml0eSoqIGVsZW1lbnRzCiAtICoqQ3JlYXRlKiogdGhlICoqUkVBRE1FKiogYW5kICoqbGljZW5jZSoqIGZpbGVzCiAtICoqUHVzaCoqIGFsbCBvZiB0aGUgcmVsYXRlZCAqKm1hdGVyaWFscyB0byB0aGUgcmVwb3NpdG9yeSoqIGFuZCAqKmNyZWF0ZSBhIHB1bGwgcmVxdWVzdCoqCiAtIExldCB0aGUgKipjb2xsYWJvcmF0b3IgcmV2aWV3KiogdGhlIHB1c2hlZCBjb2RlLgogLSAqKkFmdGVyKiogdGhlIGNoYW5nZXMgYXJlICoqbWVyZ2VkKiosIDx1PmNoZWNrb3V0IHRvIHRoZSBsb2NhbCBtYWluIGJyYW5jaCBhbmQgcHVsbCB0aGUgdXBkYXRlZCByZW1vdGUgbWFpbiBicmFuY2g8L3U+LgoKCiMjICoqUmVzb3VyY2VzKioKCi0gWW91IG1heSBmaW5kIG11bHRpcGxlIHJlc291cmNlcyBmb3IgbGVhcm5pbmcgZ2l0IGFuZC9vciBzZXJ2aWNlcyBsaWtlIEdpdEh1YiBhdmFpbGFibGUgZm9yIGZyZWUgKGFsdGhvdWdoIHNvbWV0aW1lcyB5b3UgbmVlZCB0byByZWdpc3RlcikuCgojIyMgKipDb3Vyc2VzKioKCi0gW0ludHJvZHVjdGlvbiB0byBWZXJzaW9uIENvbnRyb2wgd2l0aCBHaXRdKGh0dHBzOi8vYXBwLmRhdGFjYW1wLmNvbS9sZWFybi9jb3Vyc2VzL2ludHJvZHVjdGlvbi10by12ZXJzaW9uLWNvbnRyb2wtd2l0aC1naXQpCi0gW0ludHJvZHVjdGlvbiB0byBHaXRdKGh0dHBzOi8vYXBwLmRhdGFjYW1wLmNvbS9sZWFybi9jb3Vyc2VzL2ludHJvZHVjdGlvbi10by1naXQpCi0gW0dpdEh1YiBDb25jZXB0c10oaHR0cHM6Ly9hcHAuZGF0YWNhbXAuY29tL2xlYXJuL2NvdXJzZXMvZ2l0aHViLWNvbmNlcHRzKQotIFtHaXQ6IEJlY29tZSBhbiBFeHBlcnQgaW4gR2l0ICYgR2l0SHViIGluIDQgSG91cnNdKGh0dHBzOi8vd3d3LnVkZW15LmNvbS9jb3Vyc2UvZ2l0LWV4cGVydC00LWhvdXJzKQotIFtJbnRyb2R1Y3Rpb24gdG8gR2l0IGFuZCBHaXRIdWJdKGh0dHBzOi8vd3d3LmNvdXJzZXJhLm9yZy9sZWFybi9pbnRyb2R1Y3Rpb24tZ2l0LWdpdGh1YikKLSBbU3BvbHVwcsOhY2UgYSBPcGVuLVNvdXJjZV0oaHR0cHM6Ly9uYXVjc2UucHl0aG9uLmN6L2NvdXJzZS9weWxhZGllcy9zZXNzaW9ucy9mb3NzLykgKEN6ZWNoKQoKCiMjIyAqKkRvY3VtZW50YXRpb24qKgoKLSBbR2l0IC0gRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9naXQtc2NtLmNvbS9kb2MpCi0gW0dpdEh1YiBEb2NzXShodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbikKCiMjIyAqKkNoZWF0LXNoZWV0cyoqCgotIFtnaXRdKGh0dHBzOi8vcHl2ZWMuZ2l0aHViLmlvL2NoZWF0c2hlZXRzL2Jhc2ljLWdpdC9iYXNpYy1naXQtY3MucGRmKSAoQ3plY2gpCi0gW01hcmtkb3duXShodHRwczovL3d3dy5tYXJrZG93bmd1aWRlLm9yZy9jaGVhdC1zaGVldC8pCgombmJzcDsKJm5ic3A7Cgo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PGI+R28gYmFjayB0byA8YSBocmVmPSIvcG9zdCI+QmxvZzwvYj48L2E+LjwvcD4=