For code below, Open Git (or Powershell, Terminal, Command Prompt, etc.) in directory of repository and use the relevant code.

1 Why It is Important to Use Git/Version Control

There are many reasons why it is important to use git/version control:

  • It (GitHub/GitLab) provides backups of all files in the cloud
  • It (GitHub/GitLab) allows you to access the files in the cloud from any computer with access to the internet, even if you are away from your local computer
  • Version control provides history of all (committed) changes made to all files
  • If you make a mistake in your code, you can easily revert to a prior version because you took snapshots (commits) of your files!
    • You don’t need to keep all the “commented out” lines of code
      • This allows you to write cleaner code, because you can remove commented out lines of code, knowing that you can easily recover them in your commit history
    • You don’t have to keep files or folders named “project_old” or whatever
      • This allows you to keep cleaner file/folder directories for your projects
  • Git keeps all files for the project self-contained, which helps increase reproducibility
  • It (GitHub/GitLab) allows easier collaboration with others on the project
  • It (GitHub/GitLab) allows easier sharing with outside researchers

2 How to Use

2.1 To begin

  1. Install git (https://git-scm.com/downloads)
  2. Install GitHub Desktop app (https://desktop.github.com)
  3. Create a Personal Access Token (https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html, archived at https://perma.cc/6ZH8-JNZC; or https://research-git.uiowa.edu/-/profile/personal_access_tokens, archived at https://perma.cc/7JPU-WDBS) on the UI GitLab instance (https://research-git.uiowa.edu) to access UI GitLab repositories from GitHub Desktop.
    • For application name, put “GitHub”
    • For expiration date, leave it blank (or set it for as late an expiration date as possible)
    • For scopes, select everything
  4. When cloning a repository from UI’s GitLab instance using GitHub Desktop, GitHub Desktop will ask for your username and password. Enter your HawkID as your username and your UI GitLab Personal Access Token as your password.

2.2 Best practices working with version control

  • Create a new repository (repo) whenever you start a new project
  • Follow the Petersen Lab template for how to structure your repo (folder structure, .gitignore file, etc.):
  • To collaborate with others:
    • Navigate to the repo on the UI GitLab website
    • When in the repo, click “Members”
    • Add the Collaborator
  • Each time you want to work on the files in the repo, follow this cycle:
    1. Using the GitHub Desktop app, sync the repo files from the cloud to the repo on your local computer (i.e., fetch any repo updates to your local machine from the cloud)
      • Make sure to do this before many code changes so you are working with the latest version of files
    2. Do your work on the repo: make any code/file/folder additions, changes, or deletions
    3. Using the GitHub Desktop app, commit the changes
      • Commit changes to the cloud early and often; when deciding what to commit and when, try to group “similar changes” into the same commit (“like goes with like”)
      • Use a separate “commit” for each separable “functional unit” changed
    4. Using the GitHub Desktop app, sync the repo files from your local computer to the repo on the cloud (i.e., push all of your committed changes to the cloud)
      • Never leave file changes uncommitted or unsynced when you stop working on the repo for the day!

2.4 How to create a repo on local computer

  1. Create repository on UI GitLab website (https://research-git.uiowa.edu)
  2. Open GitHub Desktop app
  3. Clone repository
  4. Add .gitignore file (from Template project: https://research-git.uiowa.edu/petersenlab/Template/blob/master/.gitignore) to the root of the cloned project folder
  5. Follow the Petersen Lab template for how to structure your repo (folder structure, .gitignore file, etc.): https://research-git.uiowa.edu/PetersenLab/Template
    • Note that a folder will not be synced if there are no files in them (i.e., if the folder is empty)
  6. Sync file changes using GitHub Desktop (“Fetch origin”, “Push origin”)

2.5 How to add a pre-existing repo from the lab drive (RDSS/network share) to your computer

For example, the SRS-DataProcessing repo lives on the lab drive.

  1. Make sure Dr. Petersen has given you collaborator access to the repo
  2. Open GitHub Desktop app
  3. Navigate to the folder location of the repo on the lab drive
  4. Drag the .git folder within the repo to the GitHub Desktop app

2.6 How to clone a repo from GitLab to local

  1. Navigate to relevant repo on GitLab (https://research-git.uiowa.edu)
  2. Click Clone in right-hand corner, select Clone with HTTPS
  3. Open GitHub Desktop App and click File, Clone Repository
  4. Click the URL tab
  5. Paste in the URL
  6. Navigate to where you want to save it
    • The recommended location for your repos is to create a folder titled GitHub in your Documents folder, and to put repos in the GitHub folder (by default: PC: C:/Users/[USERNAME]/Documents/GitHub/; Mac: /Users/[user]/Documents/GitHub/) because various lab scripts try to read the lab functions from this location; it is NOT recommended to put git repos in a OneDrive folder because git files tend not to play nice with syncing services (e.g., OneDrive, Dropbox)
  7. Click Clone
  8. Enter your GitLab username as your username and your Personal Access Token as your password

2.7 How to add, modify, or delete files in a repo

  1. Open relevant repo in GitHub Desktop app
  2. Pull any repo updates from the server to the local files (“Fetch origin”, “Pull origin”)
  3. Make necessary additions, modifications, and deletions to the files
  4. Create commits for all changes in GitHub Desktop app (one commit per substantive change): Enter “Summary” and “Commit to master”
  5. After making all changes and commits, push local file changes to the server using GitHub Desktop (“Fetch origin”, “Push origin”)

2.8 How to collaborate with others

  1. Navigate to the repo on the UI GitLab website
  2. When in the repo, click “Settings”
  3. Click “Members”
  4. Add the Collaborator

2.9 How to create a pull request

  1. To create a pull request, you either need to have write permissions for the repo, or you need to create a fork of the repo. To fork the repo, see here: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo#forking-a-repository (archived at https://perma.cc/33P6-Y4BR)
  2. After forking the repo (if necessary), sync the repo with the latest version from the cloud so you know you are editing the latest version of the files.
  3. Make any changes to the files in the repo that you’d like to incorporate into the repo
  4. Open a pull request with your changes: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork (archived at https://perma.cc/KAP3-L5L7)

2.10 How to clone a repo into local directory with a different folder name (directory must be empty)

  1. Git Bash into directory
git clone https://research-git.uiowa.edu/petersenlab/srs/SRS-DataProcessing.git .
git remote set-url --add origin https://research-git.uiowa.edu/petersenlab/srs/SRS-DataProcessing.git
git remote -v

2.11 How to transfer a repo to a new location/group/subgroup

  1. Create location/group/subgroup (e.g., PetersenLab/School Readiness Study)
  2. When in the repo, click “Settings”
  3. Go to “Advanced”, and click “Expand”
  4. Go to “Transfer project”, and select the location/group/subgroup you want to transfer the repo to under “Select a new namespace”
  5. In the local repo, edit the repo URL in the .git/config file
  6. When asked for your password, enter your username (HawkID) and GitLab Personal Access Token

2.12 How to use large file storage (LFS)

  1. Make sure the large files are not in the repo yet.
  2. In GitHub Desktop, open the repo you want to use LFS for
  3. In GitHub Desktop, select the Repository tab, then select Command Prompt or similar
  4. In the command prompt, type (based on instructions from: https://docs.gitlab.com/ee/topics/git/lfs/; archived at https://perma.cc/6WMC-GTKN):
git lfs install          # initialize the Git LFS project
git lfs track "*.Rdata"  # select the file extensions that you want to treat as large files
  1. This should have created a .gitattributes file in the repo. In GitHub Desktop, commit and push the .gitattributes file to the cloud version of the repo.
  2. Copy the large files into the repo.
  3. In GitHub Desktop, commit and push the large file to the cloud version of the repo.
  4. (Or, if not using GitHub Desktop, can commit in the command prompt (https://docs.gitlab.com/ee/topics/git/lfs/)):
git add .                                            # add the large file to the project
git commit -am "insert name of commit message here"  # commit the file meta data
git push origin master                               # sync the git repo and large file to the GitLab server
  1. When asked for credentials, use your HawkID as your username and your personal access token as your password

2.13 How to create a new repository on a shared network drive

  1. Create a repo on GitHub or GitLab online
  2. Open Git Bash on the desktop
  3. Using Git Bash, set the current directory to the path where the new repo will be. For example, use the following command to clone to the School Readiness Study
cd "R:\Lab\Studies\School Readiness Study"
  1. Next, go to GitLab or GitHub online and obtain the HTTPS URL to the new repository that was created. Clone the repository with the HTTPS link using Git Bash with the following command
git clone (HTTPS Link)

2.14 How to revert changes to a previous commit

  1. Open the Github Desktop and navigate to the repository you would like to revert changes for
  2. Next, click the history tab
  3. Right click the commit you would like to revert back to, and select revert changes
  4. Push the changes to the repo to complete the revision
revert changes
revert changes

2.15 How to perform a partial commit

  1. In GitHub Desktop, click the desired lines in the gutter
  2. Create the commit, and leave the other changes for you to continue working on.

https://github.blog/2015-01-14-partial-commits-in-github-for-windows (archived at https://perma.cc/5U3V-YWRF)

2.16 How to copy a repo to a new repo

https://github.com/new/import

3 Troubleshooting

3.1 Error: Authentication Failed

authentication failed
authentication failed

This error can occur for a variety of reasons. One possibility is that your GitLab Personal Access Token (PAT) has expired. To fix this:

  1. Create a Personal Access Token (https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html, archived at https://perma.cc/6ZH8-JNZC; or https://research-git.uiowa.edu/-/profile/personal_access_tokens, archived at https://perma.cc/7JPU-WDBS) on the UI GitLab instance (https://research-git.uiowa.edu) to access UI GitLab repositories from GitHub Desktop.
    • For application name, put “GitHub”
    • For expiration date, leave it blank (or set it for as late an expiration date as possible)
    • For scopes, select everything
  2. When cloning a repository from UI’s GitLab instance using GitHub Desktop, GitHub Desktop will ask for your username and password. Enter your HawkID as your username and your UI GitLab Personal Access Token as your password.

If you do not receive a prompt to enter your username and password, try removing the saved GitHubcredentials from Windows Credential Manager: https://github.com/desktop/desktop/issues/8860#issuecomment-2211812646

3.2 GitHub shows all files as being changed even though the files haven’t changed

Windows and Mac use different line endings (https://github.com/Microsoft/WSL/issues/184; archived at https://perma.cc/F8UX-YJP3):

git config --global core.autocrlf true

3.3 Error: You are not allowed to push code to protected branches on this project

  1. Make sure the owner of the repo unprotects the branch (https://stackoverflow.com/questions/32246503/fix-gitlab-error-you-are-not-allowed-to-push-code-to-protected-branches-on-thi; archived at https://perma.cc/98AF-N6BY)
  2. Open the repo, click “Settings”, “Repository”, “Protected Branches”
  3. Change “Allowed to merge” and “Allowed to push” to “Developers and Maintainers”, and click “Unprotect”

3.4 Error creating commit

git add -A
git status
git commit -m "Message"` (where "Message" is the summary message of the commit)
git push
git status

3.5 Undo commit (but retain file changes)

git reset --soft HEAD^

3.6 Error: Sync failed

git status
git push

3.7 Error: Sync failed -- Syncing would overwrite your uncommitted changes

https://stackoverflow.com/questions/23084822/github-some-uncommited-changes-would-be-over-written-by-syncing (archived at https://perma.cc/AP5S-G38B):

  1. git stash -u
  2. (perform manual sync in GitHub Desktop)
  3. git stash pop

3.8 Error: Pipeline has failed for master

https://docs.gitlab.com/ee/topics/autodevops/#at-the-project-level (archived at https://perma.cc/3MAQ-ZBFF)

  1. Open the repo in GitLab
  2. Go to your project’s “Settings” > “CI/CD” > “Auto DevOps”
  3. Disable (uncheck) the “Default to Auto DevOps pipeline”
  4. Click “Save changes”

4 OLD

4.1 Creating Repo on Local Directory (if Directory is empty)

  1. Create Repo on GitHub
  2. Don’t add README yet
  3. Open Git Shell, navigate to directory, and type:
git init
git remote add origin https://github.com/DevPsyLab/petersenlab.git
git remote -v
  1. Drag and drop the folder with the repository into the GUI app
  2. Add .gitignore file with .Rhistory

4.2 Creating Repo on Local Directory (if Directory is not empty)

  1. Create Repo on GitHub
  2. Don’t add README yet
  3. Open Git Shell, navigate to directory, and type:
git init
git add .
git commit -m 'First commit'
git remote add origin https://research-git.uiowa.edu/itpetersen/PetersenLab.git
git remote -v
git push -u origin master
  1. Drag and drop the folder with the repository into the GUI app
  2. Add .gitignore file with .Rhistory

4.3 Creating R Scripts Repo on Lab Server

  1. Create R Scripts Repo
  2. Open R Scripts folder and delete .git folder
  3. Open Git Shell and type:
git init
git add .
git commit -m 'First commit'
git remote add origin https://research-git.uiowa.edu/PetersenLab/R-Scripts.git
git remote -v
git push -u origin master
  1. Move R Scripts folder to another location
  2. Clone repo into folder:
    • open Git Shell
    • navigate to Z:\TDS II\Data\R Scripts\
    git clone https://research-git.uiowa.edu/PetersenLab/R-Scripts.git .
    The dot on the end of the git clone command means “the current directory”
  3. Drag and drop the folder with the repository into the GUI app
  4. Add .gitignore file with .Rhistory
LS0tCnRpdGxlOiAiR2l0LCBHaXRMYWIsIGFuZCBHaXRIdWIiCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLAogIGVycm9yID0gVFJVRSwKICBjb21tZW50ID0gIiIpCmBgYAoKRm9yIGNvZGUgYmVsb3csIE9wZW4gYEdpdGAgKG9yIFBvd2Vyc2hlbGwsIFRlcm1pbmFsLCBDb21tYW5kIFByb21wdCwgZXRjLikgaW4gZGlyZWN0b3J5IG9mIHJlcG9zaXRvcnkgYW5kIHVzZSB0aGUgcmVsZXZhbnQgY29kZS4KCiMgV2h5IEl0IGlzIEltcG9ydGFudCB0byBVc2UgYEdpdGAvVmVyc2lvbiBDb250cm9sCgpUaGVyZSBhcmUgbWFueSByZWFzb25zIHdoeSBpdCBpcyBpbXBvcnRhbnQgdG8gdXNlIGdpdC92ZXJzaW9uIGNvbnRyb2w6CgotIEl0IChgR2l0SHViYC9gR2l0TGFiYCkgcHJvdmlkZXMgYmFja3VwcyBvZiBhbGwgZmlsZXMgaW4gdGhlIGNsb3VkCi0gSXQgKGBHaXRIdWJgL2BHaXRMYWJgKSBhbGxvd3MgeW91IHRvIGFjY2VzcyB0aGUgZmlsZXMgaW4gdGhlIGNsb3VkIGZyb20gYW55IGNvbXB1dGVyIHdpdGggYWNjZXNzIHRvIHRoZSBpbnRlcm5ldCwgZXZlbiBpZiB5b3UgYXJlIGF3YXkgZnJvbSB5b3VyIGxvY2FsIGNvbXB1dGVyCi0gVmVyc2lvbiBjb250cm9sIHByb3ZpZGVzIGhpc3Rvcnkgb2YgYWxsIChjb21taXR0ZWQpIGNoYW5nZXMgbWFkZSB0byBhbGwgZmlsZXMKLSBJZiB5b3UgbWFrZSBhIG1pc3Rha2UgaW4geW91ciBjb2RlLCB5b3UgY2FuIGVhc2lseSByZXZlcnQgdG8gYSBwcmlvciB2ZXJzaW9uIGJlY2F1c2UgeW91IHRvb2sgc25hcHNob3RzIChjb21taXRzKSBvZiB5b3VyIGZpbGVzIQogICAgLSBZb3UgZG9uJ3QgbmVlZCB0byBrZWVwIGFsbCB0aGUgImNvbW1lbnRlZCBvdXQiIGxpbmVzIG9mIGNvZGUKICAgICAgICAtIFRoaXMgYWxsb3dzIHlvdSB0byB3cml0ZSBjbGVhbmVyIGNvZGUsIGJlY2F1c2UgeW91IGNhbiByZW1vdmUgY29tbWVudGVkIG91dCBsaW5lcyBvZiBjb2RlLCBrbm93aW5nIHRoYXQgeW91IGNhbiBlYXNpbHkgcmVjb3ZlciB0aGVtIGluIHlvdXIgY29tbWl0IGhpc3RvcnkKICAgIC0gWW91IGRvbid0IGhhdmUgdG8ga2VlcCBmaWxlcyBvciBmb2xkZXJzIG5hbWVkICJwcm9qZWN0X29sZCIgb3Igd2hhdGV2ZXIKICAgICAgICAtIFRoaXMgYWxsb3dzIHlvdSB0byBrZWVwIGNsZWFuZXIgZmlsZS9mb2xkZXIgZGlyZWN0b3JpZXMgZm9yIHlvdXIgcHJvamVjdHMKLSBgR2l0YCBrZWVwcyBhbGwgZmlsZXMgZm9yIHRoZSBwcm9qZWN0IHNlbGYtY29udGFpbmVkLCB3aGljaCBoZWxwcyBpbmNyZWFzZSByZXByb2R1Y2liaWxpdHkKLSBJdCAoYEdpdEh1YmAvYEdpdExhYmApIGFsbG93cyBlYXNpZXIgY29sbGFib3JhdGlvbiB3aXRoIG90aGVycyBvbiB0aGUgcHJvamVjdAotIEl0IChgR2l0SHViYC9gR2l0TGFiYCkgYWxsb3dzIGVhc2llciBzaGFyaW5nIHdpdGggb3V0c2lkZSByZXNlYXJjaGVycwoKIyBIb3cgdG8gVXNlCgojIyBUbyBiZWdpbiB7I3RvQmVnaW59CgoxLiBJbnN0YWxsIGBnaXRgIChodHRwczovL2dpdC1zY20uY29tL2Rvd25sb2FkcykKMS4gSW5zdGFsbCBgR2l0SHViIERlc2t0b3BgIGFwcCAoaHR0cHM6Ly9kZXNrdG9wLmdpdGh1Yi5jb20pCjEuIENyZWF0ZSBhIFBlcnNvbmFsIEFjY2VzcyBUb2tlbiAoaHR0cHM6Ly9kb2NzLmdpdGxhYi5jb20vZWUvdXNlci9wcm9maWxlL3BlcnNvbmFsX2FjY2Vzc190b2tlbnMuaHRtbCwgYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy82Wkg4LUpOWkM7IG9yIGh0dHBzOi8vcmVzZWFyY2gtZ2l0LnVpb3dhLmVkdS8tL3Byb2ZpbGUvcGVyc29uYWxfYWNjZXNzX3Rva2VucywgYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy83SlBVLVdEQlMpIG9uIHRoZSBVSSBgR2l0TGFiYCBpbnN0YW5jZSAoaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1KSB0byBhY2Nlc3MgVUkgYEdpdExhYmAgcmVwb3NpdG9yaWVzIGZyb20gYEdpdEh1YiBEZXNrdG9wYC4KICAgIC0gIEZvciBhcHBsaWNhdGlvbiBuYW1lLCBwdXQgIkdpdEh1YiIKICAgIC0gIEZvciBleHBpcmF0aW9uIGRhdGUsIGxlYXZlIGl0IGJsYW5rIChvciBzZXQgaXQgZm9yIGFzIGxhdGUgYW4gZXhwaXJhdGlvbiBkYXRlIGFzIHBvc3NpYmxlKQogICAgLSAgRm9yIHNjb3Blcywgc2VsZWN0IGV2ZXJ5dGhpbmcKMS4gV2hlbiBjbG9uaW5nIGEgcmVwb3NpdG9yeSBmcm9tIFVJJ3MgYEdpdExhYmAgaW5zdGFuY2UgdXNpbmcgYEdpdEh1YiBEZXNrdG9wYCwgYEdpdEh1YiBEZXNrdG9wYCB3aWxsIGFzayBmb3IgeW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQuCkVudGVyIHlvdXIgSGF3a0lEIGFzIHlvdXIgdXNlcm5hbWUgYW5kIHlvdXIgVUkgYEdpdExhYmAgUGVyc29uYWwgQWNjZXNzIFRva2VuIGFzIHlvdXIgcGFzc3dvcmQuCgojIyBCZXN0IHByYWN0aWNlcyB3b3JraW5nIHdpdGggdmVyc2lvbiBjb250cm9sIHsjYmVzdFByYWN0aWNlc30KCi0gQ3JlYXRlIGEgbmV3IHJlcG9zaXRvcnkgKHJlcG8pIHdoZW5ldmVyIHlvdSBzdGFydCBhIG5ldyBwcm9qZWN0Ci0gRm9sbG93IHRoZSBQZXRlcnNlbiBMYWIgdGVtcGxhdGUgZm9yIGhvdyB0byBzdHJ1Y3R1cmUgeW91ciByZXBvIChmb2xkZXIgc3RydWN0dXJlLCBgLmdpdGlnbm9yZWAgZmlsZSwgZXRjLik6CiAgICAtIGh0dHBzOi8vcmVzZWFyY2gtZ2l0LnVpb3dhLmVkdS9QZXRlcnNlbkxhYi9UZW1wbGF0ZQotIFRvIGNvbGxhYm9yYXRlIHdpdGggb3RoZXJzOgogICAgLSBOYXZpZ2F0ZSB0byB0aGUgcmVwbyBvbiB0aGUgVUkgYEdpdExhYmAgd2Vic2l0ZQogICAgLSBXaGVuIGluIHRoZSByZXBvLCBjbGljayAiTWVtYmVycyIKICAgIC0gQWRkIHRoZSBDb2xsYWJvcmF0b3IKLSBFYWNoIHRpbWUgeW91IHdhbnQgdG8gd29yayBvbiB0aGUgZmlsZXMgaW4gdGhlIHJlcG8sIGZvbGxvdyB0aGlzIGN5Y2xlOgogICAgMS4gVXNpbmcgdGhlIGBHaXRIdWIgRGVza3RvcGAgYXBwLCBzeW5jIHRoZSByZXBvIGZpbGVzIGZyb20gdGhlIGNsb3VkIHRvIHRoZSByZXBvIG9uIHlvdXIgbG9jYWwgY29tcHV0ZXIgKGkuZS4sIGZldGNoIGFueSByZXBvIHVwZGF0ZXMgdG8geW91ciBsb2NhbCBtYWNoaW5lIGZyb20gdGhlIGNsb3VkKQogICAgICAgIC0gTWFrZSBzdXJlIHRvIGRvIHRoaXMgYmVmb3JlIG1hbnkgY29kZSBjaGFuZ2VzIHNvIHlvdSBhcmUgd29ya2luZyB3aXRoIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBmaWxlcwogICAgMS4gRG8geW91ciB3b3JrIG9uIHRoZSByZXBvOiBtYWtlIGFueSBjb2RlL2ZpbGUvZm9sZGVyIGFkZGl0aW9ucywgY2hhbmdlcywgb3IgZGVsZXRpb25zCiAgICAxLiBVc2luZyB0aGUgYEdpdEh1YiBEZXNrdG9wYCBhcHAsIGNvbW1pdCB0aGUgY2hhbmdlcwogICAgICAgIC0gQ29tbWl0IGNoYW5nZXMgdG8gdGhlIGNsb3VkIGVhcmx5IGFuZCBvZnRlbjsgd2hlbiBkZWNpZGluZyB3aGF0IHRvIGNvbW1pdCBhbmQgd2hlbiwgdHJ5IHRvIGdyb3VwICJzaW1pbGFyIGNoYW5nZXMiIGludG8gdGhlIHNhbWUgY29tbWl0ICgibGlrZSBnb2VzIHdpdGggbGlrZSIpCiAgICAgICAgLSBVc2UgYSBzZXBhcmF0ZSAiY29tbWl0IiBmb3IgZWFjaCBzZXBhcmFibGUgImZ1bmN0aW9uYWwgdW5pdCIgY2hhbmdlZAogICAgMS4gVXNpbmcgdGhlIGBHaXRIdWIgRGVza3RvcGAgYXBwLCBzeW5jIHRoZSByZXBvIGZpbGVzIGZyb20geW91ciBsb2NhbCBjb21wdXRlciB0byB0aGUgcmVwbyBvbiB0aGUgY2xvdWQgKGkuZS4sIHB1c2ggYWxsIG9mIHlvdXIgY29tbWl0dGVkIGNoYW5nZXMgdG8gdGhlIGNsb3VkKQogICAgICAgIC0gTmV2ZXIgbGVhdmUgZmlsZSBjaGFuZ2VzIHVuY29tbWl0dGVkIG9yIHVuc3luY2VkIHdoZW4geW91IHN0b3Agd29ya2luZyBvbiB0aGUgcmVwbyBmb3IgdGhlIGRheSEKCiMjIEluc3RydWN0aW9ucyBmb3IgdXNpbmcgYEdpdEh1YiBEZXNrdG9wYCBhcHAgd2l0aCBgR2l0TGFiYAoKLSBodHRwczovL2l0bmV4dC5pby9ob3ctdG8tdXNlLWdpdGh1Yi1kZXNrdG9wLXdpdGgtZ2l0bGFiLWNkNGQyZGUzZDEwNCAoYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy9TNTlSLTNZVDcpCi0gaHR0cHM6Ly9jb21tdW5pdHkucmVjbGFpbWhvc3RpbmcuY29tL3QvdXNpbmctZ2l0aHViLWRlc2t0b3Atd2l0aC1naXRsYWIvODc2IChhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjL1pQVDktS0VRTCkKLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMjYzOTgxNS9kb2VzLWdpdGh1Yi1mb3Itd2luZG93cy13b3JrLXdpdGgtZ2l0bGFiIChhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjLzk5UlItNktMRSkKLSBodHRwczovL2dpdGh1Yi5jb20vZGVza3RvcC9kZXNrdG9wL2lzc3Vlcy84NTIjaXNzdWVjb21tZW50LTQwMjU0Njg0OCAoYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy8zR0NVLUdUUFUpCi0gaHR0cHM6Ly9naXRodWIuY29tL2Rlc2t0b3AvZGVza3RvcC9pc3N1ZXMvMzgxNiNpc3N1ZWNvbW1lbnQtNDIxMDYwOTc0IChhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjL044UlMtQkZXUikKCiMjIEhvdyB0byBjcmVhdGUgYSByZXBvIG9uIGxvY2FsIGNvbXB1dGVyCgoxLiBDcmVhdGUgcmVwb3NpdG9yeSBvbiBVSSBgR2l0TGFiYCB3ZWJzaXRlIChodHRwczovL3Jlc2VhcmNoLWdpdC51aW93YS5lZHUpCjEuIE9wZW4gYEdpdEh1YiBEZXNrdG9wYCBhcHAKMS4gQ2xvbmUgcmVwb3NpdG9yeQoxLiBBZGQgYC5naXRpZ25vcmVgIGZpbGUgKGZyb20gVGVtcGxhdGUgcHJvamVjdDogaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1L3BldGVyc2VubGFiL1RlbXBsYXRlL2Jsb2IvbWFzdGVyLy5naXRpZ25vcmUpIHRvIHRoZSByb290IG9mIHRoZSBjbG9uZWQgcHJvamVjdCBmb2xkZXIKMS4gRm9sbG93IHRoZSBQZXRlcnNlbiBMYWIgdGVtcGxhdGUgZm9yIGhvdyB0byBzdHJ1Y3R1cmUgeW91ciByZXBvIChmb2xkZXIgc3RydWN0dXJlLCBgLmdpdGlnbm9yZWAgZmlsZSwgZXRjLik6IGh0dHBzOi8vcmVzZWFyY2gtZ2l0LnVpb3dhLmVkdS9QZXRlcnNlbkxhYi9UZW1wbGF0ZQogICAgLSAgTm90ZSB0aGF0IGEgZm9sZGVyIHdpbGwgbm90IGJlIHN5bmNlZCBpZiB0aGVyZSBhcmUgbm8gZmlsZXMgaW4gdGhlbSAoaS5lLiwgaWYgdGhlIGZvbGRlciBpcyBlbXB0eSkKMS4gU3luYyBmaWxlIGNoYW5nZXMgdXNpbmcgYEdpdEh1YiBEZXNrdG9wYCAoIkZldGNoIG9yaWdpbiIsICJQdXNoIG9yaWdpbiIpCgojIyBIb3cgdG8gYWRkIGEgcHJlLWV4aXN0aW5nIHJlcG8gZnJvbSB0aGUgbGFiIGRyaXZlIChgUkRTU2AvbmV0d29yayBzaGFyZSkgdG8geW91ciBjb21wdXRlcgoKRm9yIGV4YW1wbGUsIHRoZSBgU1JTLURhdGFQcm9jZXNzaW5nYCByZXBvIGxpdmVzIG9uIHRoZSBsYWIgZHJpdmUuCgoxLiBNYWtlIHN1cmUgRHIuIFBldGVyc2VuIGhhcyBnaXZlbiB5b3UgY29sbGFib3JhdG9yIGFjY2VzcyB0byB0aGUgcmVwbwoxLiBPcGVuIGBHaXRIdWIgRGVza3RvcGAgYXBwCjEuIE5hdmlnYXRlIHRvIHRoZSBmb2xkZXIgbG9jYXRpb24gb2YgdGhlIHJlcG8gb24gdGhlIGxhYiBkcml2ZQoxLiBEcmFnIHRoZSBgLmdpdGAgZm9sZGVyIHdpdGhpbiB0aGUgcmVwbyB0byB0aGUgYEdpdEh1YiBEZXNrdG9wYCBhcHAKCiMjIEhvdyB0byBjbG9uZSBhIHJlcG8gZnJvbSBgR2l0TGFiYCB0byBsb2NhbAoKMS4gTmF2aWdhdGUgdG8gcmVsZXZhbnQgcmVwbyBvbiBgR2l0TGFiYCAoaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1KQoxLiBDbGljayBgQ2xvbmVgIGluIHJpZ2h0LWhhbmQgY29ybmVyLCBzZWxlY3QgYENsb25lIHdpdGggSFRUUFNgCjEuIE9wZW4gYEdpdEh1YiBEZXNrdG9wYCBBcHAgYW5kIGNsaWNrIGBGaWxlYCwgYENsb25lIFJlcG9zaXRvcnlgCjEuIENsaWNrIHRoZSBgVVJMYCB0YWIKMS4gUGFzdGUgaW4gdGhlIFVSTAoxLiBOYXZpZ2F0ZSB0byB3aGVyZSB5b3Ugd2FudCB0byBzYXZlIGl0CiAgICAtICBUaGUgcmVjb21tZW5kZWQgbG9jYXRpb24gZm9yIHlvdXIgcmVwb3MgaXMgdG8gY3JlYXRlIGEgZm9sZGVyIHRpdGxlZCBgR2l0SHViYCBpbiB5b3VyIGBEb2N1bWVudHNgIGZvbGRlciwgYW5kIHRvIHB1dCByZXBvcyBpbiB0aGUgYEdpdEh1YmAgZm9sZGVyIChieSBkZWZhdWx0OiBQQzogYEM6L1VzZXJzL1tVU0VSTkFNRV0vRG9jdW1lbnRzL0dpdEh1Yi9gOyBNYWM6IGAvVXNlcnMvW3VzZXJdL0RvY3VtZW50cy9HaXRIdWIvYCkgYmVjYXVzZSB2YXJpb3VzIGxhYiBzY3JpcHRzIHRyeSB0byByZWFkIHRoZSBsYWIgZnVuY3Rpb25zIGZyb20gdGhpcyBsb2NhdGlvbjsgaXQgaXMgKk5PVCogcmVjb21tZW5kZWQgdG8gcHV0IGBnaXRgIHJlcG9zIGluIGEgT25lRHJpdmUgZm9sZGVyIGJlY2F1c2UgW2BnaXRgIGZpbGVzIHRlbmQgbm90IHRvIHBsYXkgbmljZSB3aXRoIHN5bmNpbmcgc2VydmljZXNdKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE5MzA1MDMzL3doeS1pcy1wdXR0aW5nLWdpdC1yZXBvc2l0b3JpZXMtaW5zaWRlLW9mLWEtZHJvcGJveC1mb2xkZXItbm90LXJlY29tbWVuZGVkOyBhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjL1VUWDgtS1ZMOSkgKGUuZy4sIE9uZURyaXZlLCBEcm9wYm94KQoxLiBDbGljayBgQ2xvbmVgCjEuIEVudGVyIHlvdXIgYEdpdExhYmAgdXNlcm5hbWUgYXMgeW91ciB1c2VybmFtZSBhbmQgeW91ciBQZXJzb25hbCBBY2Nlc3MgVG9rZW4gYXMgeW91ciBwYXNzd29yZAoKIyMgSG93IHRvIGFkZCwgbW9kaWZ5LCBvciBkZWxldGUgZmlsZXMgaW4gYSByZXBvCgoxLiBPcGVuIHJlbGV2YW50IHJlcG8gaW4gYEdpdEh1YiBEZXNrdG9wYCBhcHAKMS4gUHVsbCBhbnkgcmVwbyB1cGRhdGVzIGZyb20gdGhlIHNlcnZlciB0byB0aGUgbG9jYWwgZmlsZXMgKCJGZXRjaCBvcmlnaW4iLCAiUHVsbCBvcmlnaW4iKQoxLiBNYWtlIG5lY2Vzc2FyeSBhZGRpdGlvbnMsIG1vZGlmaWNhdGlvbnMsIGFuZCBkZWxldGlvbnMgdG8gdGhlIGZpbGVzCjEuIENyZWF0ZSBjb21taXRzIGZvciBhbGwgY2hhbmdlcyBpbiBgR2l0SHViIERlc2t0b3BgIGFwcCAob25lIGNvbW1pdCBwZXIgc3Vic3RhbnRpdmUgY2hhbmdlKTogRW50ZXIgIlN1bW1hcnkiIGFuZCAiQ29tbWl0IHRvIG1hc3RlciIKMS4gQWZ0ZXIgbWFraW5nIGFsbCBjaGFuZ2VzIGFuZCBjb21taXRzLCBwdXNoIGxvY2FsIGZpbGUgY2hhbmdlcyB0byB0aGUgc2VydmVyIHVzaW5nIGBHaXRIdWIgRGVza3RvcGAgKCJGZXRjaCBvcmlnaW4iLCAiUHVzaCBvcmlnaW4iKQoKIyMgSG93IHRvIGNvbGxhYm9yYXRlIHdpdGggb3RoZXJzCgoxLiBOYXZpZ2F0ZSB0byB0aGUgcmVwbyBvbiB0aGUgVUkgYEdpdExhYmAgd2Vic2l0ZQoxLiBXaGVuIGluIHRoZSByZXBvLCBjbGljayAiU2V0dGluZ3MiCjEuIENsaWNrICJNZW1iZXJzIgoxLiBBZGQgdGhlIENvbGxhYm9yYXRvcgoKIyMgSG93IHRvIGNyZWF0ZSBhIHB1bGwgcmVxdWVzdCB7I3B1bGwtcmVxdWVzdH0KCjEuIFRvIGNyZWF0ZSBhIHB1bGwgcmVxdWVzdCwgeW91IGVpdGhlciBuZWVkIHRvIGhhdmUgd3JpdGUgcGVybWlzc2lvbnMgZm9yIHRoZSByZXBvLCBvciB5b3UgbmVlZCB0byBjcmVhdGUgYSBmb3JrIG9mIHRoZSByZXBvLgpUbyBmb3JrIHRoZSByZXBvLCBzZWUgaGVyZTogaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vcHVsbC1yZXF1ZXN0cy9jb2xsYWJvcmF0aW5nLXdpdGgtcHVsbC1yZXF1ZXN0cy93b3JraW5nLXdpdGgtZm9ya3MvZm9yay1hLXJlcG8jZm9ya2luZy1hLXJlcG9zaXRvcnkgKGFyY2hpdmVkIGF0IGh0dHBzOi8vcGVybWEuY2MvMzNQNi1ZNEJSKQoxLiBBZnRlciBmb3JraW5nIHRoZSByZXBvIChpZiBuZWNlc3NhcnkpLCBzeW5jIHRoZSByZXBvIHdpdGggdGhlIGxhdGVzdCB2ZXJzaW9uIGZyb20gdGhlIGNsb3VkIHNvIHlvdSBrbm93IHlvdSBhcmUgZWRpdGluZyB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgdGhlIGZpbGVzLgoxLiBNYWtlIGFueSBjaGFuZ2VzIHRvIHRoZSBmaWxlcyBpbiB0aGUgcmVwbyB0aGF0IHlvdSdkIGxpa2UgdG8gaW5jb3Jwb3JhdGUgaW50byB0aGUgcmVwbwoxLiBPcGVuIGEgcHVsbCByZXF1ZXN0IHdpdGggeW91ciBjaGFuZ2VzOiBodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9wdWxsLXJlcXVlc3RzL2NvbGxhYm9yYXRpbmctd2l0aC1wdWxsLXJlcXVlc3RzL3Byb3Bvc2luZy1jaGFuZ2VzLXRvLXlvdXItd29yay13aXRoLXB1bGwtcmVxdWVzdHMvY3JlYXRpbmctYS1wdWxsLXJlcXVlc3QtZnJvbS1hLWZvcmsgKGFyY2hpdmVkIGF0IGh0dHBzOi8vcGVybWEuY2MvS0FQMy1MNUw3KQoKIyMgSG93IHRvIGNsb25lIGEgcmVwbyBpbnRvIGxvY2FsIGRpcmVjdG9yeSB3aXRoIGEgZGlmZmVyZW50IGZvbGRlciBuYW1lIChkaXJlY3RvcnkgbXVzdCBiZSBlbXB0eSkKCjEuIGBHaXRgIEJhc2ggaW50byBkaXJlY3RvcnkKYGBgCmdpdCBjbG9uZSBodHRwczovL3Jlc2VhcmNoLWdpdC51aW93YS5lZHUvcGV0ZXJzZW5sYWIvc3JzL1NSUy1EYXRhUHJvY2Vzc2luZy5naXQgLgpnaXQgcmVtb3RlIHNldC11cmwgLS1hZGQgb3JpZ2luIGh0dHBzOi8vcmVzZWFyY2gtZ2l0LnVpb3dhLmVkdS9wZXRlcnNlbmxhYi9zcnMvU1JTLURhdGFQcm9jZXNzaW5nLmdpdApnaXQgcmVtb3RlIC12CmBgYAoKIyMgSG93IHRvIHRyYW5zZmVyIGEgcmVwbyB0byBhIG5ldyBsb2NhdGlvbi9ncm91cC9zdWJncm91cAoKMS4gQ3JlYXRlIGxvY2F0aW9uL2dyb3VwL3N1Ymdyb3VwIChlLmcuLCBgUGV0ZXJzZW5MYWIvU2Nob29sIFJlYWRpbmVzcyBTdHVkeWApCjEuIFdoZW4gaW4gdGhlIHJlcG8sIGNsaWNrICJTZXR0aW5ncyIKMS4gR28gdG8gIkFkdmFuY2VkIiwgYW5kIGNsaWNrICJFeHBhbmQiCjEuIEdvIHRvICJUcmFuc2ZlciBwcm9qZWN0IiwgYW5kIHNlbGVjdCB0aGUgbG9jYXRpb24vZ3JvdXAvc3ViZ3JvdXAgeW91IHdhbnQgdG8gdHJhbnNmZXIgdGhlIHJlcG8gdG8gdW5kZXIgIlNlbGVjdCBhIG5ldyBuYW1lc3BhY2UiCjEuIEluIHRoZSBsb2NhbCByZXBvLCBlZGl0IHRoZSByZXBvIFVSTCBpbiB0aGUgYC5naXQvY29uZmlnYCBmaWxlCjEuIFdoZW4gYXNrZWQgZm9yIHlvdXIgcGFzc3dvcmQsIGVudGVyIHlvdXIgdXNlcm5hbWUgKEhhd2tJRCkgYW5kIGBHaXRMYWJgIFBlcnNvbmFsIEFjY2VzcyBUb2tlbgoKIyMgSG93IHRvIHVzZSBsYXJnZSBmaWxlIHN0b3JhZ2UgKExGUykgeyNnaXRMZnN9CgoxLiBNYWtlIHN1cmUgdGhlIGxhcmdlIGZpbGVzIGFyZSBub3QgaW4gdGhlIHJlcG8geWV0LgoxLiBJbiBgR2l0SHViIERlc2t0b3BgLCBvcGVuIHRoZSByZXBvIHlvdSB3YW50IHRvIHVzZSBMRlMgZm9yCjEuIEluIGBHaXRIdWIgRGVza3RvcGAsIHNlbGVjdCB0aGUgYFJlcG9zaXRvcnlgIHRhYiwgdGhlbiBzZWxlY3QgYENvbW1hbmQgUHJvbXB0YCBvciBzaW1pbGFyCjEuIEluIHRoZSBjb21tYW5kIHByb21wdCwgdHlwZSAoYmFzZWQgb24gaW5zdHJ1Y3Rpb25zIGZyb206IGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL3RvcGljcy9naXQvbGZzLzsgYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy82V01DLUdUS04pOgpgYGAKZ2l0IGxmcyBpbnN0YWxsICAgICAgICAgICMgaW5pdGlhbGl6ZSB0aGUgR2l0IExGUyBwcm9qZWN0CmdpdCBsZnMgdHJhY2sgIiouUmRhdGEiICAjIHNlbGVjdCB0aGUgZmlsZSBleHRlbnNpb25zIHRoYXQgeW91IHdhbnQgdG8gdHJlYXQgYXMgbGFyZ2UgZmlsZXMKYGBgCjUuIFRoaXMgc2hvdWxkIGhhdmUgY3JlYXRlZCBhIGAuZ2l0YXR0cmlidXRlc2AgZmlsZSBpbiB0aGUgcmVwby4gSW4gYEdpdEh1YiBEZXNrdG9wYCwgY29tbWl0IGFuZCBwdXNoIHRoZSBgLmdpdGF0dHJpYnV0ZXNgIGZpbGUgdG8gdGhlIGNsb3VkIHZlcnNpb24gb2YgdGhlIHJlcG8uCjYuIENvcHkgdGhlIGxhcmdlIGZpbGVzIGludG8gdGhlIHJlcG8uCjcuIEluIGBHaXRIdWIgRGVza3RvcGAsIGNvbW1pdCBhbmQgcHVzaCB0aGUgbGFyZ2UgZmlsZSB0byB0aGUgY2xvdWQgdmVyc2lvbiBvZiB0aGUgcmVwby4KOC4gKE9yLCBpZiBub3QgdXNpbmcgYEdpdEh1YiBEZXNrdG9wYCwgY2FuIGNvbW1pdCBpbiB0aGUgY29tbWFuZCBwcm9tcHQgKGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL3RvcGljcy9naXQvbGZzLykpOgpgYGAKZ2l0IGFkZCAuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFkZCB0aGUgbGFyZ2UgZmlsZSB0byB0aGUgcHJvamVjdApnaXQgY29tbWl0IC1hbSAiaW5zZXJ0IG5hbWUgb2YgY29tbWl0IG1lc3NhZ2UgaGVyZSIgICMgY29tbWl0IHRoZSBmaWxlIG1ldGEgZGF0YQpnaXQgcHVzaCBvcmlnaW4gbWFzdGVyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc3luYyB0aGUgZ2l0IHJlcG8gYW5kIGxhcmdlIGZpbGUgdG8gdGhlIEdpdExhYiBzZXJ2ZXIKYGBgCjkuIFdoZW4gYXNrZWQgZm9yIGNyZWRlbnRpYWxzLCB1c2UgeW91ciBIYXdrSUQgYXMgeW91ciB1c2VybmFtZSBhbmQgeW91ciBwZXJzb25hbCBhY2Nlc3MgdG9rZW4gYXMgeW91ciBwYXNzd29yZAoKIyMgSG93IHRvIGNyZWF0ZSBhIG5ldyByZXBvc2l0b3J5IG9uIGEgc2hhcmVkIG5ldHdvcmsgZHJpdmUKCjEuIENyZWF0ZSBhIHJlcG8gb24gYEdpdEh1YmAgb3IgYEdpdExhYmAgb25saW5lCjEuIE9wZW4gYEdpdGAgQmFzaCBvbiB0aGUgZGVza3RvcAoxLiBVc2luZyBgR2l0YCBCYXNoLCBzZXQgdGhlIGN1cnJlbnQgZGlyZWN0b3J5IHRvIHRoZSBwYXRoIHdoZXJlIHRoZSBuZXcgcmVwbyB3aWxsIGJlLgpGb3IgZXhhbXBsZSwgdXNlIHRoZSBmb2xsb3dpbmcgY29tbWFuZCB0byBjbG9uZSB0byB0aGUgU2Nob29sIFJlYWRpbmVzcyBTdHVkeQoKYGBgCmNkICJSOlxMYWJcU3R1ZGllc1xTY2hvb2wgUmVhZGluZXNzIFN0dWR5IgpgYGAKCjEuIE5leHQsIGdvIHRvIGBHaXRMYWJgIG9yIGBHaXRIdWJgIG9ubGluZSBhbmQgb2J0YWluIHRoZSBIVFRQUyBVUkwgdG8gdGhlIG5ldyByZXBvc2l0b3J5IHRoYXQgd2FzIGNyZWF0ZWQuCkNsb25lIHRoZSByZXBvc2l0b3J5IHdpdGggdGhlIEhUVFBTIGxpbmsgdXNpbmcgYEdpdGAgQmFzaCB3aXRoIHRoZSBmb2xsb3dpbmcgY29tbWFuZAoKYGBgCmdpdCBjbG9uZSAoSFRUUFMgTGluaykKYGBgCgojIyBIb3cgdG8gcmV2ZXJ0IGNoYW5nZXMgdG8gYSBwcmV2aW91cyBjb21taXQgeyNyZXZlcnRDb21taXR9CgoxLiBPcGVuIHRoZSBgR2l0aHViIERlc2t0b3BgIGFuZCBuYXZpZ2F0ZSB0byB0aGUgcmVwb3NpdG9yeSB5b3Ugd291bGQgbGlrZSB0byByZXZlcnQgY2hhbmdlcyBmb3IKMS4gTmV4dCwgY2xpY2sgdGhlIGBoaXN0b3J5YCB0YWIKMS4gUmlnaHQgY2xpY2sgdGhlIGNvbW1pdCB5b3Ugd291bGQgbGlrZSB0byByZXZlcnQgYmFjayB0bywgYW5kIHNlbGVjdCByZXZlcnQgY2hhbmdlcwoxLiBQdXNoIHRoZSBjaGFuZ2VzIHRvIHRoZSByZXBvIHRvIGNvbXBsZXRlIHRoZSByZXZpc2lvbgoKIVtyZXZlcnQgY2hhbmdlc10oaW1hZ2VzL3JldmVydENoYW5nZXMucG5nKQoKIyMgSG93IHRvIHBlcmZvcm0gYSBwYXJ0aWFsIGNvbW1pdCB7I3BhcnRpYWxDb21taXR9CgoxLiBJbiBgR2l0SHViIERlc2t0b3BgLCBjbGljayB0aGUgZGVzaXJlZCBsaW5lcyBpbiB0aGUgZ3V0dGVyCjIuIENyZWF0ZSB0aGUgY29tbWl0LCBhbmQgbGVhdmUgdGhlIG90aGVyIGNoYW5nZXMgZm9yIHlvdSB0byBjb250aW51ZSB3b3JraW5nIG9uLgoKaHR0cHM6Ly9naXRodWIuYmxvZy8yMDE1LTAxLTE0LXBhcnRpYWwtY29tbWl0cy1pbi1naXRodWItZm9yLXdpbmRvd3MgKGFyY2hpdmVkIGF0IGh0dHBzOi8vcGVybWEuY2MvNVUzVi1ZV1JGKQoKIyMgSG93IHRvIGNvcHkgYSByZXBvIHRvIGEgbmV3IHJlcG8geyNjb3B5UmVwb30KCmh0dHBzOi8vZ2l0aHViLmNvbS9uZXcvaW1wb3J0CgojIyBIb3cgdG8gbWFrZSBhIHJlcG9zaXRvcnkgYSB0ZW1wbGF0ZSByZXBvc2l0b3J5IHsjdGVtcGxhdGVSZXBvfQoKaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vcmVwb3NpdG9yaWVzL2NyZWF0aW5nLWFuZC1tYW5hZ2luZy1yZXBvc2l0b3JpZXMvY3JlYXRpbmctYS10ZW1wbGF0ZS1yZXBvc2l0b3J5IChhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjL1BZVzUtS0FQNSkKCiMjIEhvdyB0byBjcmVhdGUgYSByZXNwb3NpdG9yeSBmcm9tIGEgdGVtcGxhdGUgeyNyZXBvRnJvbVRlbXBsYXRlfQoKaHR0cHM6Ly9kb2NzLmdpdGh1Yi5jb20vZW4vcmVwb3NpdG9yaWVzL2NyZWF0aW5nLWFuZC1tYW5hZ2luZy1yZXBvc2l0b3JpZXMvY3JlYXRpbmctYS1yZXBvc2l0b3J5LWZyb20tYS10ZW1wbGF0ZSAoYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy85RTJDLU1VQ0spCgojIFRyb3VibGVzaG9vdGluZyB7I3Ryb3VibGVzaG9vdGluZ30KCiMjIEVycm9yOiBBdXRoZW50aWNhdGlvbiBGYWlsZWQgeyNhdXRoZW50aWNhdGlvbkZhaWxlZH0KCiFbYXV0aGVudGljYXRpb24gZmFpbGVkXShpbWFnZXMvZ2l0aHViRGVza3RvcEF1dGhlbnRpY2F0aW9uRXJyb3IucG5nKQoKVGhpcyBlcnJvciBjYW4gb2NjdXIgZm9yIGEgdmFyaWV0eSBvZiByZWFzb25zLgpPbmUgcG9zc2liaWxpdHkgaXMgdGhhdCB5b3VyIEdpdExhYiBQZXJzb25hbCBBY2Nlc3MgVG9rZW4gKFBBVCkgaGFzIGV4cGlyZWQuClRvIGZpeCB0aGlzOgoKMS4gQ3JlYXRlIGEgUGVyc29uYWwgQWNjZXNzIFRva2VuIChodHRwczovL2RvY3MuZ2l0bGFiLmNvbS9lZS91c2VyL3Byb2ZpbGUvcGVyc29uYWxfYWNjZXNzX3Rva2Vucy5odG1sLCBhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjLzZaSDgtSk5aQzsgb3IgaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1Ly0vcHJvZmlsZS9wZXJzb25hbF9hY2Nlc3NfdG9rZW5zLCBhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjLzdKUFUtV0RCUykgb24gdGhlIFVJIGBHaXRMYWJgIGluc3RhbmNlIChodHRwczovL3Jlc2VhcmNoLWdpdC51aW93YS5lZHUpIHRvIGFjY2VzcyBVSSBgR2l0TGFiYCByZXBvc2l0b3JpZXMgZnJvbSBgR2l0SHViIERlc2t0b3BgLgogICAgLSAgRm9yIGFwcGxpY2F0aW9uIG5hbWUsIHB1dCAiR2l0SHViIgogICAgLSAgRm9yIGV4cGlyYXRpb24gZGF0ZSwgbGVhdmUgaXQgYmxhbmsgKG9yIHNldCBpdCBmb3IgYXMgbGF0ZSBhbiBleHBpcmF0aW9uIGRhdGUgYXMgcG9zc2libGUpCiAgICAtICBGb3Igc2NvcGVzLCBzZWxlY3QgZXZlcnl0aGluZwoxLiBXaGVuIGNsb25pbmcgYSByZXBvc2l0b3J5IGZyb20gVUkncyBgR2l0TGFiYCBpbnN0YW5jZSB1c2luZyBgR2l0SHViIERlc2t0b3BgLCBgR2l0SHViIERlc2t0b3BgIHdpbGwgYXNrIGZvciB5b3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZC4KRW50ZXIgeW91ciBIYXdrSUQgYXMgeW91ciB1c2VybmFtZSBhbmQgeW91ciBVSSBgR2l0TGFiYCBQZXJzb25hbCBBY2Nlc3MgVG9rZW4gYXMgeW91ciBwYXNzd29yZC4KCklmIHlvdSBkbyBub3QgcmVjZWl2ZSBhIHByb21wdCB0byBlbnRlciB5b3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCwgdHJ5IHJlbW92aW5nIHRoZSBzYXZlZCBHaXRIdWJjcmVkZW50aWFscyBmcm9tIFdpbmRvd3MgQ3JlZGVudGlhbCBNYW5hZ2VyOgpodHRwczovL2dpdGh1Yi5jb20vZGVza3RvcC9kZXNrdG9wL2lzc3Vlcy84ODYwI2lzc3VlY29tbWVudC0yMjExODEyNjQ2CgojIyBgR2l0SHViYCBzaG93cyBhbGwgZmlsZXMgYXMgYmVpbmcgY2hhbmdlZCBldmVuIHRob3VnaCB0aGUgZmlsZXMgaGF2ZW4ndCBjaGFuZ2VkCgpXaW5kb3dzIGFuZCBNYWMgdXNlIGRpZmZlcmVudCBsaW5lIGVuZGluZ3MgKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWNyb3NvZnQvV1NML2lzc3Vlcy8xODQ7IGFyY2hpdmVkIGF0IGh0dHBzOi8vcGVybWEuY2MvRjhVWC1ZSlAzKToKCmBgYApnaXQgY29uZmlnIC0tZ2xvYmFsIGNvcmUuYXV0b2NybGYgdHJ1ZQpgYGAKICAKIyMgRXJyb3I6IGBZb3UgYXJlIG5vdCBhbGxvd2VkIHRvIHB1c2ggY29kZSB0byBwcm90ZWN0ZWQgYnJhbmNoZXMgb24gdGhpcyBwcm9qZWN0YAoKMS4gTWFrZSBzdXJlIHRoZSBvd25lciBvZiB0aGUgcmVwbyB1bnByb3RlY3RzIHRoZSBicmFuY2ggKGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMyMjQ2NTAzL2ZpeC1naXRsYWItZXJyb3IteW91LWFyZS1ub3QtYWxsb3dlZC10by1wdXNoLWNvZGUtdG8tcHJvdGVjdGVkLWJyYW5jaGVzLW9uLXRoaTsgYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy85OEFGLU42QlkpCjEuIE9wZW4gdGhlIHJlcG8sIGNsaWNrICJTZXR0aW5ncyIsICJSZXBvc2l0b3J5IiwgIlByb3RlY3RlZCBCcmFuY2hlcyIKMS4gQ2hhbmdlICJBbGxvd2VkIHRvIG1lcmdlIiBhbmQgIkFsbG93ZWQgdG8gcHVzaCIgdG8gIkRldmVsb3BlcnMgYW5kIE1haW50YWluZXJzIiwgYW5kIGNsaWNrICJVbnByb3RlY3QiCgojIyBFcnJvciBjcmVhdGluZyBjb21taXQKCmBgYApnaXQgYWRkIC1BCmdpdCBzdGF0dXMKZ2l0IGNvbW1pdCAtbSAiTWVzc2FnZSJgICh3aGVyZSAiTWVzc2FnZSIgaXMgdGhlIHN1bW1hcnkgbWVzc2FnZSBvZiB0aGUgY29tbWl0KQpnaXQgcHVzaApnaXQgc3RhdHVzCmBgYAoKIyMgVW5kbyBjb21taXQgKGJ1dCByZXRhaW4gZmlsZSBjaGFuZ2VzKQoKYGBgCmdpdCByZXNldCAtLXNvZnQgSEVBRF4KYGBgCgojIyBFcnJvcjogYFN5bmMgZmFpbGVkYAoKYGBgCmdpdCBzdGF0dXMKZ2l0IHB1c2gKYGBgCgojIyBFcnJvcjogYFN5bmMgZmFpbGVkIC0tIFN5bmNpbmcgd291bGQgb3ZlcndyaXRlIHlvdXIgdW5jb21taXR0ZWQgY2hhbmdlc2AKCmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIzMDg0ODIyL2dpdGh1Yi1zb21lLXVuY29tbWl0ZWQtY2hhbmdlcy13b3VsZC1iZS1vdmVyLXdyaXR0ZW4tYnktc3luY2luZyAoYXJjaGl2ZWQgYXQgaHR0cHM6Ly9wZXJtYS5jYy9BUDVTLUczOEIpOgoKMS4gYGdpdCBzdGFzaCAtdWAKMS4gKHBlcmZvcm0gbWFudWFsIHN5bmMgaW4gYEdpdEh1YiBEZXNrdG9wYCkKMS4gYGdpdCBzdGFzaCBwb3BgCiAgCiMjIEVycm9yOiBgUGlwZWxpbmUgaGFzIGZhaWxlZCBmb3IgbWFzdGVyYAoKaHR0cHM6Ly9kb2NzLmdpdGxhYi5jb20vZWUvdG9waWNzL2F1dG9kZXZvcHMvI2F0LXRoZS1wcm9qZWN0LWxldmVsIChhcmNoaXZlZCBhdCBodHRwczovL3Blcm1hLmNjLzNNQVEtWkJGRikKCjEuIE9wZW4gdGhlIHJlcG8gaW4gYEdpdExhYmAKMS4gR28gdG8geW91ciBwcm9qZWN0J3MgIlNldHRpbmdzIiA+ICJDSS9DRCIgPiAiQXV0byBEZXZPcHMiCjEuIERpc2FibGUgKHVuY2hlY2spIHRoZSAiRGVmYXVsdCB0byBBdXRvIERldk9wcyBwaXBlbGluZSIKMS4gQ2xpY2sgIlNhdmUgY2hhbmdlcyIKCiMgT0xECgojIyBDcmVhdGluZyBSZXBvIG9uIExvY2FsIERpcmVjdG9yeSAoaWYgRGlyZWN0b3J5IGlzIGVtcHR5KQoKMS4gQ3JlYXRlIFJlcG8gb24gR2l0SHViCjEuIERvbid0IGFkZCBSRUFETUUgeWV0CjEuIE9wZW4gYEdpdGAgU2hlbGwsIG5hdmlnYXRlIHRvIGRpcmVjdG9yeSwgYW5kIHR5cGU6CmBgYApnaXQgaW5pdApnaXQgcmVtb3RlIGFkZCBvcmlnaW4gaHR0cHM6Ly9naXRodWIuY29tL0RldlBzeUxhYi9wZXRlcnNlbmxhYi5naXQKZ2l0IHJlbW90ZSAtdgpgYGAKNC4gRHJhZyBhbmQgZHJvcCB0aGUgZm9sZGVyIHdpdGggdGhlIHJlcG9zaXRvcnkgaW50byB0aGUgR1VJIGFwcAo1LiBBZGQgLmdpdGlnbm9yZSBmaWxlIHdpdGggLlJoaXN0b3J5CgojIyBDcmVhdGluZyBSZXBvIG9uIExvY2FsIERpcmVjdG9yeSAoaWYgRGlyZWN0b3J5IGlzICpub3QqIGVtcHR5KQoKMS4gQ3JlYXRlIFJlcG8gb24gR2l0SHViCjEuIERvbid0IGFkZCBSRUFETUUgeWV0CjEuIE9wZW4gYEdpdGAgU2hlbGwsIG5hdmlnYXRlIHRvIGRpcmVjdG9yeSwgYW5kIHR5cGU6CmBgYApnaXQgaW5pdApnaXQgYWRkIC4KZ2l0IGNvbW1pdCAtbSAnRmlyc3QgY29tbWl0JwpnaXQgcmVtb3RlIGFkZCBvcmlnaW4gaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1L2l0cGV0ZXJzZW4vUGV0ZXJzZW5MYWIuZ2l0CmdpdCByZW1vdGUgLXYKZ2l0IHB1c2ggLXUgb3JpZ2luIG1hc3RlcgpgYGAKNC4gRHJhZyBhbmQgZHJvcCB0aGUgZm9sZGVyIHdpdGggdGhlIHJlcG9zaXRvcnkgaW50byB0aGUgR1VJIGFwcAo1LiBBZGQgLmdpdGlnbm9yZSBmaWxlIHdpdGggLlJoaXN0b3J5CgojIyBDcmVhdGluZyBgUmAgU2NyaXB0cyBSZXBvIG9uIExhYiBTZXJ2ZXIKCjEuIENyZWF0ZSBgUmAgU2NyaXB0cyBSZXBvCjEuIE9wZW4gYFJgIFNjcmlwdHMgZm9sZGVyIGFuZCBkZWxldGUgYC5naXRgIGZvbGRlcgoxLiBPcGVuIGBHaXRgIFNoZWxsIGFuZCB0eXBlOgpgYGAKZ2l0IGluaXQKZ2l0IGFkZCAuCmdpdCBjb21taXQgLW0gJ0ZpcnN0IGNvbW1pdCcKZ2l0IHJlbW90ZSBhZGQgb3JpZ2luIGh0dHBzOi8vcmVzZWFyY2gtZ2l0LnVpb3dhLmVkdS9QZXRlcnNlbkxhYi9SLVNjcmlwdHMuZ2l0CmdpdCByZW1vdGUgLXYKZ2l0IHB1c2ggLXUgb3JpZ2luIG1hc3RlcgpgYGAKNC4gTW92ZSBgUmAgU2NyaXB0cyBmb2xkZXIgdG8gYW5vdGhlciBsb2NhdGlvbgo1LiBDbG9uZSByZXBvIGludG8gZm9sZGVyOgogICAgLSBvcGVuIGBHaXRgIFNoZWxsCiAgICAtIG5hdmlnYXRlIHRvIGBaOlxURFMgSUlcRGF0YVxSIFNjcmlwdHNcYAogICAgYGBgCiAgICBnaXQgY2xvbmUgaHR0cHM6Ly9yZXNlYXJjaC1naXQudWlvd2EuZWR1L1BldGVyc2VuTGFiL1ItU2NyaXB0cy5naXQgLgogICAgYGBgCiAgICBUaGUgZG90IG9uIHRoZSBlbmQgb2YgdGhlIGBnaXQgY2xvbmVgIGNvbW1hbmQgbWVhbnMgInRoZSBjdXJyZW50IGRpcmVjdG9yeSIKNi4gRHJhZyBhbmQgZHJvcCB0aGUgZm9sZGVyIHdpdGggdGhlIHJlcG9zaXRvcnkgaW50byB0aGUgR1VJIGFwcAo3LiBBZGQgYC5naXRpZ25vcmVgIGZpbGUgd2l0aCBgLlJoaXN0b3J5YAo=



Developmental Psychopathology Lab