<<BACK

Data repositories

Please Download:

PDF

PPT

Version Control

What is version control?

Version control is a framework by which by which you can track changes to a file, of set of files. We are essentially trying to avoid this:

And we’re aiming to nudge you along a little further than this:

But, like most XKCD comics, it contains some serious wisdom.

While there are other version control system out there, in our opinion Git & Github seem to have the best combination of features for scientists. However, if you wish to use a different version control system, go for it, many of the concepts we’re learning about here will be transferable.

First a quick clarification about the tools we are using:

  • Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
  • GitHub Online project hosting using Git. Includes source-code browser, in-line editing, wikis, and ticketing. Free for public open-source code.
  • GitHub Desktop App GitHub Desktop is a seamless way to contribute to projects on GitHub

So Git is the protocol that we are using to do the actual version control (on our computer) and we are hosting our project on GitHub (the website) so we can keep a backup in the cloud and share our work (both in terms of housing all the code, but also for hosting your own websites). Finally, we are using the GitHub Desktop App to allow us to sync our local files to the GitHub website

How does version control work?

Version control systems start with a base version of the document and then save just the changes you made at each step of the way. You can think of it as a tape: if you rewind the tape and start at the base document, then you can play back each change and end up with your latest version.

Changes Are Saved Sequentially

Once you think of changes as separate from the document itself, you can then think about “playing back” different sets of changes onto the base document and getting different versions of the document. For example, two users can make independent sets of changes based on the same document.

Different Versions Can be Saved

If there aren’t conflicts, you can even play two sets of changes onto the same base document.

Multiple Versions Can be Merged

A version control system is a tool that keeps track of these changes for us and helps us version and merge our files. It allows you to decide which changes make up the next version, called a commit, and keeps useful metadata about them. The complete history of commits for a particular project and their metadata make up a repository. Repositories can be kept in sync across different computers facilitating collaboration among different people.

How to use version control

By default git ‘watches’ not just a single file; rather, it looks for changes in any file in an entire directory (except those identified in the .gitignore). So I tend to set it up in a way that makes git watch the whole project directory (i.e. the folder that contains the .Rproj file). This ‘watched’ folder is then called a git repository (repo for short).

We can create a new repository any number of ways (git command line, GitHub Desktop App, RStudio, etc), but I’m going to show you my favorite workflow to create a whole new repository from scratch:

  1. Make a new repo on GitHub (the website)
  2. Clone that repo to your computer
  3. Create an .Rproj in RStudio
  4. Sync (pull), Edit files, commit, sync (push), repeat!

Make a new repo on GitHub (the website)

Open up GitHub (and login), then click the ‘New repository’ button

Then set the repo name, a description of the project (optional), choose whether to make the repo public or private (see more in ), check the README box (the readme is a great place to describe the project even more, add metadata, etc). I’ll explain the .gitignore option below. Finally, I usually choose the MIT license which according to GitHub: “The MIT License is a permissive license that is short and to the point. It lets people do anything they want with your code as long as they provide attribution back to you and don’t hold you liable.” (This is similar to the CC-BY licence we recommend for data)

The .gitignore is a plain text file (that you can edit as you please) that tells which files, or types of files to ignore when ‘watching’ your folder. Since I work predominantly in R, I choose to use the .gitignore for R which handily ignores things that you would normally want git to ignore while working in R.

Congrats! You have created a repository!

Clone that repo to your computer

Clone your repository to your computer so you can easily work on your files. That is hopefully a two click deal if you have already configured the GitHub Desktop App (login, etc), click on Clone or Download, then Open in Desktop, and finally choose where to put that repo.

Create an .Rproj in RStudio

Now you have a ‘project folder’ but RStudio doesn’t know about it! First, open RStudio and start a new project.

Choose Existing Directory since you already have a project folder.

Browse to where you put your repo earlier and click Create Project.

You now have a fully functional portable project folder that is easy to move and/or use for collaboration and/or is a good start towards creating a reproducible project.

Remember what I said when I talked about Readin in data, when reading/writing files, always code relative to where the the .Rproj file is (i.e. the root of your project folder).

Sync (pull), Edit files, commit, sync (push), repeat!

Let’s do a quick tour of the GitHub Desktop App before we start using it. The app has 2 maine tabs that you can toggle at the top, Changes, and History. Additionally, regardless of which tab you’re on there’s the repo menu on the left that shows you which repos the app knows about (don’t be surprised if you have less than me!) as well as the dark grey visual history of the repository.

Either way you look at it the history is very short! There is only the one commit called Initial commit where I added 3 files (the green +’s). A commit is essentially a saved version of your entire project repository. If you click on the little arrow next to each file, you can see what changes where made (green +’s for additions and red -’s for deletions). In this case I created the new files, so all the lines show up as additions.

The Changes tab shows you what changes you have made since your last commit. Let’s commit the changes we made by creating the .Rproj file. Fill in the Summary box with something descriptive of the changes you just made.

That’s all there is to it!

Pro-tip Now the order of operations “Sync (pull), Edit files, commit, sync (push), repeat” is really important. Before you start working, you want to make sure you are working on the latest version of your repo (less relevant if you are the only one working on your repo on only one computer, but still a good habit), so you are going to want to pull down (or sync) the latest changes from GitHub (the website) before you start working. You also will want to commit those changes before pulling down (or syncing) again since un-commited changes can be lost if they are overwritten by a changed file on Github. Finally, don’t forget to push (sync) your changes to GitHub so that your collaborators can see/use them.

Putting it all together

I want you to build something like this

Once you have knitted your html file, go to your repository settings on GitHub.

And set your master branch as the source.

Become a GitHub power user!

Branches and Forks are treated very differently most, but I see them as almost identical. The only real difference

Using the Issues tab on GitHub as your ‘to-do’ list

Archiving your code with Zenodo

Student developer pack and Educational discount

GitHub has put together a suite of free tools for students called the Student developer pack, the most important of which is the option to have unlimited free private repositories on GitHub!

Even as a non-student, you can ask for an educational discount if you involved in education/research which usually grants those same free private repos!

<<BACK

LS0tDQp0aXRsZTogIkRhdGEgQXJjaGl2aW5nICYgdmVyc2lvbiBjb250cm9sIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0NCls8PEJBQ0tdKGh0dHBzOi8vcmVtaS1kYWlnbGUuZ2l0aHViLmlvLzIwMTctQ0hPTmUtRGF0YS8pDQoNCiMgRGF0YSByZXBvc2l0b3JpZXMNCg0KUGxlYXNlIERvd25sb2FkOg0KDQpbUERGXShodHRwczovL2dpdGh1Yi5jb20vcmVtaS1kYWlnbGUvMjAxNy1DSE9OZS1EYXRhL3Jhdy9naC1wYWdlcy9BbmdlbGEvRGF0YVdvcmtzaG9wX1NoYXJpbmcucGRmKQ0KDQpbUFBUXShodHRwczovL2dpdGh1Yi5jb20vcmVtaS1kYWlnbGUvMjAxNy1DSE9OZS1EYXRhL3Jhdy9naC1wYWdlcy9BbmdlbGEvRGF0YVdvcmtzaG9wX1NoYXJpbmcucHB0eCkNCg0KIyBWZXJzaW9uIENvbnRyb2wNCg0KIyMgV2hhdCBpcyB2ZXJzaW9uIGNvbnRyb2w/DQoNClZlcnNpb24gY29udHJvbCBpcyBhIGZyYW1ld29yayBieSB3aGljaCBieSB3aGljaCB5b3UgY2FuIHRyYWNrIGNoYW5nZXMgdG8gYSBmaWxlLCBvZiBzZXQgb2YgZmlsZXMuIFdlIGFyZSBlc3NlbnRpYWxseSB0cnlpbmcgdG8gYXZvaWQgdGhpczoNCg0KIVt2aWEgUGhEIGNvbWljcyAoaHR0cDovL3BoZGNvbWljcy5jb20vY29taWNzL2FyY2hpdmUucGhwP2NvbWljaWQ9MTUzMSldKGh0dHA6Ly93d3cucGhkY29taWNzLmNvbS9jb21pY3MvYXJjaGl2ZS9waGQxMDEyMTJzLmdpZikNCg0KQW5kIHdlJ3JlIGFpbWluZyB0byBudWRnZSB5b3UgYWxvbmcgYSBsaXR0bGUgZnVydGhlciB0aGFuIHRoaXM6DQoNCiFbdmlhIFhLQ0QgKGh0dHBzOi8veGtjZC5jb20vMTU5Ny8pXShodHRwczovL2ltZ3MueGtjZC5jb20vY29taWNzL2dpdC5wbmcpDQoNCkJ1dCwgbGlrZSBtb3N0IFhLQ0QgY29taWNzLCBpdCBjb250YWlucyBzb21lIHNlcmlvdXMgd2lzZG9tLg0KDQpXaGlsZSB0aGVyZSBhcmUgb3RoZXIgdmVyc2lvbiBjb250cm9sIHN5c3RlbSBvdXQgdGhlcmUsIGluIG91ciBvcGluaW9uIEdpdCAmIEdpdGh1YiBzZWVtIHRvIGhhdmUgdGhlIGJlc3QgY29tYmluYXRpb24gb2YgZmVhdHVyZXMgZm9yIHNjaWVudGlzdHMuIEhvd2V2ZXIsIGlmIHlvdSB3aXNoIHRvIHVzZSBhIGRpZmZlcmVudCB2ZXJzaW9uIGNvbnRyb2wgc3lzdGVtLCBnbyBmb3IgaXQsIG1hbnkgb2YgdGhlIGNvbmNlcHRzIHdlJ3JlIGxlYXJuaW5nIGFib3V0IGhlcmUgd2lsbCBiZSB0cmFuc2ZlcmFibGUuDQoNCkZpcnN0IGEgcXVpY2sgY2xhcmlmaWNhdGlvbiBhYm91dCB0aGUgdG9vbHMgd2UgYXJlIHVzaW5nOg0KDQotIFtHaXRdKGh0dHBzOi8vZ2l0LXNjbS5jb20vKSBpcyBhIGZyZWUgYW5kIG9wZW4gc291cmNlIGRpc3RyaWJ1dGVkIHZlcnNpb24gY29udHJvbCBzeXN0ZW0gZGVzaWduZWQgdG8gaGFuZGxlIGV2ZXJ5dGhpbmcgZnJvbSBzbWFsbCB0byB2ZXJ5IGxhcmdlIHByb2plY3RzIHdpdGggc3BlZWQgYW5kIGVmZmljaWVuY3kuDQotIFtHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS8pIE9ubGluZSBwcm9qZWN0IGhvc3RpbmcgdXNpbmcgR2l0LiBJbmNsdWRlcyBzb3VyY2UtY29kZSBicm93c2VyLCBpbi1saW5lIGVkaXRpbmcsIHdpa2lzLCBhbmQgdGlja2V0aW5nLiBGcmVlIGZvciBwdWJsaWMgb3Blbi1zb3VyY2UgY29kZS4NCi0gW0dpdEh1YiBEZXNrdG9wIEFwcF0oaHR0cHM6Ly9kZXNrdG9wLmdpdGh1Yi5jb20vKSBHaXRIdWIgRGVza3RvcCBpcyBhIHNlYW1sZXNzIHdheSB0byBjb250cmlidXRlIHRvIHByb2plY3RzIG9uIEdpdEh1Yg0KDQpTbyBHaXQgaXMgdGhlIHByb3RvY29sIHRoYXQgd2UgYXJlIHVzaW5nIHRvIGRvIHRoZSBhY3R1YWwgdmVyc2lvbiBjb250cm9sIChvbiBvdXIgY29tcHV0ZXIpIGFuZCB3ZSBhcmUgaG9zdGluZyBvdXIgcHJvamVjdCBvbiBHaXRIdWIgKHRoZSB3ZWJzaXRlKSBzbyB3ZSBjYW4ga2VlcCBhIGJhY2t1cCBpbiB0aGUgY2xvdWQgYW5kIHNoYXJlIG91ciB3b3JrIChib3RoIGluIHRlcm1zIG9mIGhvdXNpbmcgYWxsIHRoZSBjb2RlLCBidXQgYWxzbyBmb3IgaG9zdGluZyB5b3VyIG93biB3ZWJzaXRlcykuIEZpbmFsbHksIHdlIGFyZSB1c2luZyB0aGUgR2l0SHViIERlc2t0b3AgQXBwIHRvIGFsbG93IHVzIHRvIHN5bmMgb3VyIGxvY2FsIGZpbGVzIHRvIHRoZSBHaXRIdWIgd2Vic2l0ZQ0KDQojIyBIb3cgZG9lcyB2ZXJzaW9uIGNvbnRyb2wgd29yaz8NCg0KVmVyc2lvbiBjb250cm9sIHN5c3RlbXMgc3RhcnQgd2l0aCBhIGJhc2UgdmVyc2lvbiBvZiB0aGUgZG9jdW1lbnQgYW5kIHRoZW4gc2F2ZSBqdXN0IHRoZSBjaGFuZ2VzIHlvdSBtYWRlIGF0IGVhY2ggc3RlcCBvZiB0aGUgd2F5LiBZb3UgY2FuIHRoaW5rIG9mIGl0IGFzIGEgdGFwZTogaWYgeW91IHJld2luZCB0aGUgdGFwZSBhbmQgc3RhcnQgYXQgdGhlIGJhc2UgZG9jdW1lbnQsIHRoZW4geW91IGNhbiBwbGF5IGJhY2sgZWFjaCBjaGFuZ2UgYW5kIGVuZCB1cCB3aXRoIHlvdXIgbGF0ZXN0IHZlcnNpb24uDQoNCltDaGFuZ2VzIEFyZSBTYXZlZCBTZXF1ZW50aWFsbHldKGh0dHA6Ly9zd2NhcnBlbnRyeS5naXRodWIuaW8vZ2l0LW5vdmljZS9maWcvcGxheS1jaGFuZ2VzLnN2ZykNCg0KT25jZSB5b3UgdGhpbmsgb2YgY2hhbmdlcyBhcyBzZXBhcmF0ZSBmcm9tIHRoZSBkb2N1bWVudCBpdHNlbGYsIHlvdSBjYW4gdGhlbiB0aGluayBhYm91dCDigJxwbGF5aW5nIGJhY2vigJ0gZGlmZmVyZW50IHNldHMgb2YgY2hhbmdlcyBvbnRvIHRoZSBiYXNlIGRvY3VtZW50IGFuZCBnZXR0aW5nIGRpZmZlcmVudCB2ZXJzaW9ucyBvZiB0aGUgZG9jdW1lbnQuIEZvciBleGFtcGxlLCB0d28gdXNlcnMgY2FuIG1ha2UgaW5kZXBlbmRlbnQgc2V0cyBvZiBjaGFuZ2VzIGJhc2VkIG9uIHRoZSBzYW1lIGRvY3VtZW50Lg0KDQpbRGlmZmVyZW50IFZlcnNpb25zIENhbiBiZSBTYXZlZF0oaHR0cDovL3N3Y2FycGVudHJ5LmdpdGh1Yi5pby9naXQtbm92aWNlL2ZpZy92ZXJzaW9ucy5zdmcpDQoNCklmIHRoZXJlIGFyZW7igJl0IGNvbmZsaWN0cywgeW91IGNhbiBldmVuIHBsYXkgdHdvIHNldHMgb2YgY2hhbmdlcyBvbnRvIHRoZSBzYW1lIGJhc2UgZG9jdW1lbnQuDQoNCltNdWx0aXBsZSBWZXJzaW9ucyBDYW4gYmUgTWVyZ2VkXShodHRwOi8vc3djYXJwZW50cnkuZ2l0aHViLmlvL2dpdC1ub3ZpY2UvZmlnL21lcmdlLnN2ZykNCg0KQSB2ZXJzaW9uIGNvbnRyb2wgc3lzdGVtIGlzIGEgdG9vbCB0aGF0IGtlZXBzIHRyYWNrIG9mIHRoZXNlIGNoYW5nZXMgZm9yIHVzIGFuZCBoZWxwcyB1cyB2ZXJzaW9uIGFuZCBtZXJnZSBvdXIgZmlsZXMuIEl0IGFsbG93cyB5b3UgdG8gZGVjaWRlIHdoaWNoIGNoYW5nZXMgbWFrZSB1cCB0aGUgbmV4dCB2ZXJzaW9uLCBjYWxsZWQgYSBjb21taXQsIGFuZCBrZWVwcyB1c2VmdWwgbWV0YWRhdGEgYWJvdXQgdGhlbS4gVGhlIGNvbXBsZXRlIGhpc3Rvcnkgb2YgY29tbWl0cyBmb3IgYSBwYXJ0aWN1bGFyIHByb2plY3QgYW5kIHRoZWlyIG1ldGFkYXRhIG1ha2UgdXAgYSByZXBvc2l0b3J5LiBSZXBvc2l0b3JpZXMgY2FuIGJlIGtlcHQgaW4gc3luYyBhY3Jvc3MgZGlmZmVyZW50IGNvbXB1dGVycyBmYWNpbGl0YXRpbmcgY29sbGFib3JhdGlvbiBhbW9uZyBkaWZmZXJlbnQgcGVvcGxlLg0KDQojIyBIb3cgdG8gdXNlIHZlcnNpb24gY29udHJvbA0KDQpCeSBkZWZhdWx0IGdpdCAnd2F0Y2hlcycgbm90IGp1c3QgYSBzaW5nbGUgZmlsZTsgcmF0aGVyLCBpdCBsb29rcyBmb3IgY2hhbmdlcyBpbiBhbnkgZmlsZSBpbiBhbiBlbnRpcmUgZGlyZWN0b3J5IChleGNlcHQgdGhvc2UgaWRlbnRpZmllZCBpbiB0aGUgYC5naXRpZ25vcmVgKS4gU28gSSB0ZW5kIHRvIHNldCBpdCB1cCBpbiBhIHdheSB0aGF0IG1ha2VzIGdpdCB3YXRjaCB0aGUgd2hvbGUgcHJvamVjdCBkaXJlY3RvcnkgKGkuZS4gdGhlIGZvbGRlciB0aGF0IGNvbnRhaW5zIHRoZSAuUnByb2ogZmlsZSkuIFRoaXMgJ3dhdGNoZWQnIGZvbGRlciBpcyB0aGVuIGNhbGxlZCBhIGdpdCByZXBvc2l0b3J5IChyZXBvIGZvciBzaG9ydCkuDQoNCldlIGNhbiBjcmVhdGUgYSBuZXcgcmVwb3NpdG9yeSBhbnkgbnVtYmVyIG9mIHdheXMgKGdpdCBjb21tYW5kIGxpbmUsIEdpdEh1YiBEZXNrdG9wIEFwcCwgUlN0dWRpbywgZXRjKSwgYnV0IEknbSBnb2luZyB0byBzaG93IHlvdSBteSBmYXZvcml0ZSB3b3JrZmxvdyB0byBjcmVhdGUgYSB3aG9sZSBuZXcgcmVwb3NpdG9yeSBmcm9tIHNjcmF0Y2g6DQoNCjEuIE1ha2UgYSBuZXcgcmVwbyBvbiBHaXRIdWIgKHRoZSB3ZWJzaXRlKQ0KMi4gQ2xvbmUgdGhhdCByZXBvIHRvIHlvdXIgY29tcHV0ZXINCjMuIENyZWF0ZSBhbiAuUnByb2ogaW4gUlN0dWRpbw0KNC4gU3luYyAocHVsbCksIEVkaXQgZmlsZXMsIGNvbW1pdCwgc3luYyAocHVzaCksIHJlcGVhdCENCg0KIyMjIE1ha2UgYSBuZXcgcmVwbyBvbiBHaXRIdWIgKHRoZSB3ZWJzaXRlKQ0KDQpPcGVuIHVwIEdpdEh1YiAoYW5kIGxvZ2luKSwgdGhlbiBjbGljayB0aGUgJ05ldyByZXBvc2l0b3J5JyBidXR0b24NCg0KIVtdKHBpY3R1cmVzL25ld3JlcG9zaXRvcnkucG5nKQ0KDQpUaGVuIHNldCB0aGUgcmVwbyBuYW1lLCBhIGRlc2NyaXB0aW9uIG9mIHRoZSBwcm9qZWN0IChvcHRpb25hbCksIGNob29zZSB3aGV0aGVyIHRvIG1ha2UgdGhlIHJlcG8gcHVibGljIG9yIHByaXZhdGUgKHNlZSBtb3JlIGluICksIGNoZWNrIHRoZSBSRUFETUUgYm94ICh0aGUgcmVhZG1lIGlzIGEgZ3JlYXQgcGxhY2UgdG8gZGVzY3JpYmUgdGhlIHByb2plY3QgZXZlbiBtb3JlLCBhZGQgbWV0YWRhdGEsIGV0YykuIEknbGwgZXhwbGFpbiB0aGUgYC5naXRpZ25vcmVgIG9wdGlvbiBiZWxvdy4gRmluYWxseSwgSSB1c3VhbGx5IGNob29zZSB0aGUgYE1JVGAgbGljZW5zZSB3aGljaCBhY2NvcmRpbmcgdG8gR2l0SHViOiAiVGhlIE1JVCBMaWNlbnNlIGlzIGEgcGVybWlzc2l2ZSBsaWNlbnNlIHRoYXQgaXMgc2hvcnQgYW5kIHRvIHRoZSBwb2ludC4gSXQgbGV0cyBwZW9wbGUgZG8gYW55dGhpbmcgdGhleSB3YW50IHdpdGggeW91ciBjb2RlIGFzIGxvbmcgYXMgdGhleSBwcm92aWRlIGF0dHJpYnV0aW9uIGJhY2sgdG8geW91IGFuZCBkb27igJl0IGhvbGQgeW91IGxpYWJsZS4iIChUaGlzIGlzIHNpbWlsYXIgdG8gdGhlIENDLUJZIGxpY2VuY2Ugd2UgcmVjb21tZW5kIGZvciBkYXRhKQ0KDQohW10ocGljdHVyZXMvbmV3cmVwby5wbmcpDQoNClRoZSBgLmdpdGlnbm9yZWAgaXMgYSBwbGFpbiB0ZXh0IGZpbGUgKHRoYXQgeW91IGNhbiBlZGl0IGFzIHlvdSBwbGVhc2UpIHRoYXQgdGVsbHMgd2hpY2ggZmlsZXMsIG9yIHR5cGVzIG9mIGZpbGVzIHRvIGlnbm9yZSB3aGVuICd3YXRjaGluZycgeW91ciBmb2xkZXIuIFNpbmNlIEkgd29yayBwcmVkb21pbmFudGx5IGluIFIsIEkgY2hvb3NlIHRvIHVzZSB0aGUgYC5naXRpZ25vcmVgIGZvciBSIHdoaWNoIGhhbmRpbHkgaWdub3JlcyB0aGluZ3MgdGhhdCB5b3Ugd291bGQgbm9ybWFsbHkgd2FudCBnaXQgdG8gaWdub3JlIHdoaWxlIHdvcmtpbmcgaW4gUi4NCg0KIVtdKHBpY3R1cmVzL2dpdGlnbm9yZS5wbmcpDQoNCkNvbmdyYXRzISBZb3UgaGF2ZSBjcmVhdGVkIGEgcmVwb3NpdG9yeSENCg0KIyMjIENsb25lIHRoYXQgcmVwbyB0byB5b3VyIGNvbXB1dGVyDQoNCkNsb25lIHlvdXIgcmVwb3NpdG9yeSB0byB5b3VyIGNvbXB1dGVyIHNvIHlvdSBjYW4gZWFzaWx5IHdvcmsgb24geW91ciBmaWxlcy4gVGhhdCBpcyBob3BlZnVsbHkgYSB0d28gY2xpY2sgZGVhbCBpZiB5b3UgaGF2ZSBhbHJlYWR5IGNvbmZpZ3VyZWQgdGhlIEdpdEh1YiBEZXNrdG9wIEFwcCAobG9naW4sIGV0YyksIGNsaWNrIG9uIGBDbG9uZSBvciBEb3dubG9hZGAsIHRoZW4gYE9wZW4gaW4gRGVza3RvcGAsIGFuZCBmaW5hbGx5IGNob29zZSB3aGVyZSB0byBwdXQgdGhhdCByZXBvLg0KDQohW10ocGljdHVyZXMvY2xvbmUucG5nKQ0KDQojIyMgQ3JlYXRlIGFuIC5ScHJvaiBpbiBSU3R1ZGlvDQoNCk5vdyB5b3UgaGF2ZSBhICdwcm9qZWN0IGZvbGRlcicgYnV0IFJTdHVkaW8gZG9lc24ndCBrbm93IGFib3V0IGl0ISBGaXJzdCwgb3BlbiBSU3R1ZGlvIGFuZCBzdGFydCBhIG5ldyBwcm9qZWN0Lg0KDQohW10ocGljdHVyZXMvbmV3UnByb2oucG5nKQ0KDQpDaG9vc2UgYEV4aXN0aW5nIERpcmVjdG9yeWAgc2luY2UgeW91IGFscmVhZHkgaGF2ZSBhIHByb2plY3QgZm9sZGVyLg0KDQohW10ocGljdHVyZXMvZXhpc3RpbmcucG5nKQ0KDQpCcm93c2UgdG8gd2hlcmUgeW91IHB1dCB5b3VyIHJlcG8gZWFybGllciBhbmQgY2xpY2sgYENyZWF0ZSBQcm9qZWN0YC4NCg0KIVtdKHBpY3R1cmVzL2Jyb3dzZS5wbmcpDQoNCllvdSBub3cgaGF2ZSBhIGZ1bGx5IGZ1bmN0aW9uYWwgcG9ydGFibGUgcHJvamVjdCBmb2xkZXIgdGhhdCBpcyBlYXN5IHRvIG1vdmUgYW5kL29yIHVzZSBmb3IgY29sbGFib3JhdGlvbiBhbmQvb3IgaXMgYSBnb29kIHN0YXJ0IHRvd2FyZHMgY3JlYXRpbmcgYSByZXByb2R1Y2libGUgcHJvamVjdC4NCg0KUmVtZW1iZXIgd2hhdCBJIHNhaWQgd2hlbiBJIHRhbGtlZCBhYm91dCBbUmVhZGluIGluIGRhdGFdKGh0dHBzOi8vcmVtaS1kYWlnbGUuZ2l0aHViLmlvLzIwMTctQ0hPTmUtRGF0YS9jbGVhbmluZy5odG1sI3JlYWRpbmdfaW5fZGF0YSksIHdoZW4gcmVhZGluZy93cml0aW5nIGZpbGVzLCBhbHdheXMgY29kZSByZWxhdGl2ZSB0byB3aGVyZSB0aGUgdGhlIGAuUnByb2pgIGZpbGUgaXMgKGkuZS4gdGhlIHJvb3Qgb2YgeW91ciBwcm9qZWN0IGZvbGRlcikuIA0KDQojIyMgU3luYyAocHVsbCksIEVkaXQgZmlsZXMsIGNvbW1pdCwgc3luYyAocHVzaCksIHJlcGVhdCENCg0KTGV0J3MgZG8gYSBxdWljayB0b3VyIG9mIHRoZSBHaXRIdWIgRGVza3RvcCBBcHAgYmVmb3JlIHdlIHN0YXJ0IHVzaW5nIGl0LiBUaGUgYXBwIGhhcyAyIG1haW5lIHRhYnMgdGhhdCB5b3UgY2FuIHRvZ2dsZSBhdCB0aGUgdG9wLCBgQ2hhbmdlc2AsIGFuZCBgSGlzdG9yeWAuIEFkZGl0aW9uYWxseSwgcmVnYXJkbGVzcyBvZiB3aGljaCB0YWIgeW91J3JlIG9uIHRoZXJlJ3MgdGhlIHJlcG8gbWVudSBvbiB0aGUgbGVmdCB0aGF0IHNob3dzIHlvdSB3aGljaCByZXBvcyB0aGUgYXBwIGtub3dzIGFib3V0IChkb24ndCBiZSBzdXJwcmlzZWQgaWYgeW91IGhhdmUgbGVzcyB0aGFuIG1lISkgYXMgd2VsbCBhcyB0aGUgZGFyayBncmV5IHZpc3VhbCBoaXN0b3J5IG9mIHRoZSByZXBvc2l0b3J5Lg0KDQohW10ocGljdHVyZXMvaGlzdG9yeS5wbmcpDQoNCkVpdGhlciB3YXkgeW91IGxvb2sgYXQgaXQgdGhlIGhpc3RvcnkgaXMgdmVyeSBzaG9ydCEgVGhlcmUgaXMgb25seSB0aGUgb25lIGNvbW1pdCBjYWxsZWQgYEluaXRpYWwgY29tbWl0YCB3aGVyZSBJIGFkZGVkIDMgZmlsZXMgKHRoZSBncmVlbiArJ3MpLiBBIGNvbW1pdCBpcyBlc3NlbnRpYWxseSBhIHNhdmVkIHZlcnNpb24gb2YgeW91ciBlbnRpcmUgcHJvamVjdCByZXBvc2l0b3J5LiBJZiB5b3UgY2xpY2sgb24gdGhlIGxpdHRsZSBhcnJvdyBuZXh0IHRvIGVhY2ggZmlsZSwgeW91IGNhbiBzZWUgd2hhdCBjaGFuZ2VzIHdoZXJlIG1hZGUgKGdyZWVuICsncyBmb3IgYWRkaXRpb25zIGFuZCByZWQgLSdzIGZvciBkZWxldGlvbnMpLiBJbiB0aGlzIGNhc2UgSSBjcmVhdGVkIHRoZSBuZXcgZmlsZXMsIHNvIGFsbCB0aGUgbGluZXMgc2hvdyB1cCBhcyBhZGRpdGlvbnMuDQoNCiFbXShwaWN0dXJlcy9jaGFuZ2VzLnBuZykNCg0KVGhlIGBDaGFuZ2VzYCB0YWIgc2hvd3MgeW91IHdoYXQgY2hhbmdlcyB5b3UgaGF2ZSBtYWRlIHNpbmNlIHlvdXIgbGFzdCBjb21taXQuIExldCdzIGNvbW1pdCB0aGUgY2hhbmdlcyB3ZSBtYWRlIGJ5IGNyZWF0aW5nIHRoZSBgLlJwcm9qYCBmaWxlLiBGaWxsIGluIHRoZSBgU3VtbWFyeWAgYm94ICB3aXRoICoqc29tZXRoaW5nIGRlc2NyaXB0aXZlKiogb2YgdGhlIGNoYW5nZXMgeW91IGp1c3QgbWFkZS4NCg0KIVt2aWEgWEtDRCAoaHR0cHM6Ly94a2NkLmNvbS8xMjk2LyldKGh0dHBzOi8vaW1ncy54a2NkLmNvbS9jb21pY3MvZ2l0X2NvbW1pdC5wbmcpDQoNClRoYXQncyBhbGwgdGhlcmUgaXMgdG8gaXQhDQoNCj4gKipQcm8tdGlwKioNCj4gTm93IHRoZSBvcmRlciBvZiBvcGVyYXRpb25zICJTeW5jIChwdWxsKSwgRWRpdCBmaWxlcywgY29tbWl0LCBzeW5jIChwdXNoKSwgcmVwZWF0IiBpcyByZWFsbHkgaW1wb3J0YW50LiBCZWZvcmUgeW91IHN0YXJ0IHdvcmtpbmcsIHlvdSB3YW50IHRvIG1ha2Ugc3VyZSB5b3UgYXJlIHdvcmtpbmcgb24gdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIHlvdXIgcmVwbyAobGVzcyByZWxldmFudCBpZiB5b3UgYXJlIHRoZSBvbmx5IG9uZSB3b3JraW5nIG9uIHlvdXIgcmVwbyBvbiBvbmx5IG9uZSBjb21wdXRlciwgYnV0IHN0aWxsIGEgZ29vZCBoYWJpdCksIHNvIHlvdSBhcmUgZ29pbmcgdG8gd2FudCB0byBwdWxsIGRvd24gKG9yIHN5bmMpIHRoZSBsYXRlc3QgY2hhbmdlcyBmcm9tIEdpdEh1YiAodGhlIHdlYnNpdGUpIGJlZm9yZSB5b3Ugc3RhcnQgd29ya2luZy4gWW91IGFsc28gd2lsbCB3YW50IHRvIGNvbW1pdCB0aG9zZSBjaGFuZ2VzIGJlZm9yZSBwdWxsaW5nIGRvd24gKG9yIHN5bmNpbmcpIGFnYWluIHNpbmNlIHVuLWNvbW1pdGVkIGNoYW5nZXMgY2FuIGJlIGxvc3QgaWYgdGhleSBhcmUgb3ZlcndyaXR0ZW4gYnkgYSBjaGFuZ2VkIGZpbGUgb24gR2l0aHViLiBGaW5hbGx5LCBkb24ndCBmb3JnZXQgdG8gcHVzaCAoc3luYykgeW91ciBjaGFuZ2VzIHRvIEdpdEh1YiBzbyB0aGF0IHlvdXIgY29sbGFib3JhdG9ycyBjYW4gc2VlL3VzZSB0aGVtLg0KDQojIFB1dHRpbmcgaXQgYWxsIHRvZ2V0aGVyDQoNCkkgd2FudCB5b3UgdG8gYnVpbGQgc29tZXRoaW5nIGxpa2UgW3RoaXNdKGh0dHBzOi8vcmVtaS1kYWlnbGUuZ2l0aHViLmlvL0NIT05FLWRlbW8vaW5kZXgubmIuaHRtbCkNCg0KT25jZSB5b3UgaGF2ZSBrbml0dGVkIHlvdXIgaHRtbCBmaWxlLCBnbyB0byB5b3VyIHJlcG9zaXRvcnkgc2V0dGluZ3Mgb24gR2l0SHViLg0KDQohW10ocGljdHVyZXMvc2V0dGluZ3MucG5nKQ0KDQpBbmQgc2V0IHlvdXIgbWFzdGVyIGJyYW5jaCBhcyB0aGUgc291cmNlLg0KDQohW10ocGljdHVyZXMvcGFnZXMucG5nKQ0KDQojIEJlY29tZSBhIEdpdEh1YiBwb3dlciB1c2VyIQ0KDQpbQnJhbmNoZXNdKGh0dHBzOi8vZ3VpZGVzLmdpdGh1Yi5jb20vaW50cm9kdWN0aW9uL2Zsb3cvKSBhbmQgW0ZvcmtzXShodHRwczovL2d1aWRlcy5naXRodWIuY29tL2FjdGl2aXRpZXMvZm9ya2luZy8pIGFyZSB0cmVhdGVkIHZlcnkgZGlmZmVyZW50bHkgbW9zdCwgYnV0IEkgc2VlIHRoZW0gYXMgYWxtb3N0IGlkZW50aWNhbC4gVGhlIG9ubHkgcmVhbCBkaWZmZXJlbmNlDQoNClVzaW5nIHRoZSBbSXNzdWVzXShodHRwczovL2d1aWRlcy5naXRodWIuY29tL2ZlYXR1cmVzL2lzc3Vlcy8pIHRhYiBvbiBHaXRIdWIgYXMgeW91ciAndG8tZG8nIGxpc3QNCg0KQXJjaGl2aW5nIHlvdXIgY29kZSB3aXRoIFtaZW5vZG9dKGh0dHBzOi8vZ3VpZGVzLmdpdGh1Yi5jb20vYWN0aXZpdGllcy9jaXRhYmxlLWNvZGUvKQ0KDQojIFN0dWRlbnQgZGV2ZWxvcGVyIHBhY2sgYW5kIEVkdWNhdGlvbmFsIGRpc2NvdW50DQoNCkdpdEh1YiBoYXMgcHV0IHRvZ2V0aGVyIGEgc3VpdGUgb2YgZnJlZSB0b29scyBmb3Igc3R1ZGVudHMgY2FsbGVkIHRoZSBbU3R1ZGVudCBkZXZlbG9wZXIgcGFja10oaHR0cHM6Ly9lZHVjYXRpb24uZ2l0aHViLmNvbS9wYWNrKSwgdGhlIG1vc3QgaW1wb3J0YW50IG9mIHdoaWNoIGlzIHRoZSBvcHRpb24gdG8gaGF2ZSB1bmxpbWl0ZWQgZnJlZSBwcml2YXRlIHJlcG9zaXRvcmllcyBvbiBHaXRIdWIhDQoNCkV2ZW4gYXMgYSBub24tc3R1ZGVudCwgeW91IGNhbiBhc2sgZm9yIGFuIFtlZHVjYXRpb25hbCBkaXNjb3VudF0oaHR0cHM6Ly9lZHVjYXRpb24uZ2l0aHViLmNvbS9kaXNjb3VudF9yZXF1ZXN0cy9uZXcpIGlmIHlvdSBpbnZvbHZlZCBpbiBlZHVjYXRpb24vcmVzZWFyY2ggd2hpY2ggdXN1YWxseSBncmFudHMgdGhvc2Ugc2FtZSBmcmVlIHByaXZhdGUgcmVwb3MhDQoNCls8PEJBQ0tdKGh0dHBzOi8vcmVtaS1kYWlnbGUuZ2l0aHViLmlvLzIwMTctQ0hPTmUtRGF0YS8pDQo=