kind: job
metadata:
  categories:
  - audio
  - genai
  tag: ''
  name: transcribe
verbose: false
spec:
  build:
    origin_filename: ''
    requirements:
    - transformers
    - tqdm
    - torchaudio
    - torch
    - accelerate
    base_image: mlrun/mlrun
    code_origin: ''
    functionSourceCode: IyBDb3B5cmlnaHQgMjAyNCBJZ3VhemlvCiMKIyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKIyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiMgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiMKIyAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAojCiMgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQojIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiMgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiMgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAojIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgppbXBvcnQgbG9nZ2luZwppbXBvcnQgb3BlcmF0b3IKaW1wb3J0IG9zCmltcG9ydCB0ZW1wZmlsZQpmcm9tIGZ1bmN0b29scyBpbXBvcnQgcmVkdWNlLCB3cmFwcwpmcm9tIG11bHRpcHJvY2Vzc2luZyBpbXBvcnQgUHJvY2VzcywgUXVldWUKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCmZyb20gdHlwaW5nIGltcG9ydCBBbnksIERpY3QsIEdlbmVyYXRvciwgTGlzdCwgTGl0ZXJhbCwgTmFtZWRUdXBsZSwgVHVwbGUsIFVuaW9uCgppbXBvcnQgcGFuZGFzIGFzIHBkCmltcG9ydCB0b3JjaAppbXBvcnQgdG9yY2hhdWRpbwpmcm9tIHRxZG0gaW1wb3J0IHRxZG0KZnJvbSB0cmFuc2Zvcm1lcnMgaW1wb3J0ICgKICAgIEF1dG9tYXRpY1NwZWVjaFJlY29nbml0aW9uUGlwZWxpbmUsCiAgICBBdXRvTW9kZWxGb3JDYXVzYWxMTSwKICAgIHBpcGVsaW5lLAopCmZyb20gdHJhbnNmb3JtZXJzLnV0aWxzIGltcG9ydCBpc19mbGFzaF9hdHRuXzJfYXZhaWxhYmxlCgoKY2xhc3MgQmFzZVRhc2s6CiAgICAiIiIKICAgIEEgdGFzayB0byB3cml0ZSB0aGUgdHJhbnNjcmlwdGlvbiB0byBmaWxlLgogICAgIiIiCgogICAgZGVmIF9faW5pdF9fKAogICAgICAgIHNlbGYsIGF1ZGlvX2ZpbGU6IFBhdGgsIHRyYW5zY3JpcHRpb25fb3V0cHV0OiBVbmlvbltkaWN0LCBzdHJdLCB0ZXh0X2ZpbGU6IFBhdGgKICAgICk6CiAgICAgICAgIiIiCiAgICAgICAgSW5pdGlhbGl6ZSB0aGUgdGFzay4KCiAgICAgICAgOnBhcmFtIGF1ZGlvX2ZpbGU6ICAgICAgICAgICBQYXRoIHRvIHRoZSBhdWRpbyBmaWxlIHRoYXQgd2FzIHRyYW5zY3JpYmVkLgogICAgICAgIDpwYXJhbSB0cmFuc2NyaXB0aW9uX291dHB1dDogVGhlIHRyYW5zY3JpcHRpb24gb3V0cHV0IGZyb20gdGhlIHBpcGVsaW5lLiBTdHJpbmcgbWVhbnMgYW4gZXhjZXB0aW9uIHdhcyByYWlzZWQuCiAgICAgICAgOnBhcmFtIHRleHRfZmlsZTogICAgICAgICAgICBQYXRoIHRvIHRoZSB0ZXh0IGZpbGUgdG8gd3JpdGUgdGhlIHRyYW5zY3JpcHRpb24gdG8uCiAgICAgICAgIiIiCiAgICAgICAgIyBTdG9yZSB0aGUgcGFyYW1ldGVyczoKICAgICAgICBzZWxmLl9hdWRpb19maWxlID0gYXVkaW9fZmlsZQogICAgICAgIHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0ID0gdHJhbnNjcmlwdGlvbl9vdXRwdXQKICAgICAgICBzZWxmLl90ZXh0X2ZpbGUgPSB0ZXh0X2ZpbGUKCiAgICAgICAgIyBQcmVwYXJlIHRoZSBlcnJvciB2YXJpYWJsZToKICAgICAgICBzZWxmLl9lcnJvcjogc3RyID0gTm9uZQoKICAgIGRlZiBkb190YXNrKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFRyeSB0byBwZXJmb3JtIHRoZSB0YXNrIHN0b3JpbmcgYW4gZXJyb3IgaWYgb2NjdXJyZWQuCiAgICAgICAgIiIiCiAgICAgICAgaWYgaXNpbnN0YW5jZShzZWxmLl90cmFuc2NyaXB0aW9uX291dHB1dCwgc3RyKToKICAgICAgICAgICAgc2VsZi5fZXJyb3IgPSBzZWxmLl90cmFuc2NyaXB0aW9uX291dHB1dAogICAgICAgICAgICByZXR1cm4KICAgICAgICB0cnk6CiAgICAgICAgICAgIHNlbGYuX2RvX3Rhc2soKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZXhjZXB0aW9uOgogICAgICAgICAgICBzZWxmLl9lcnJvciA9IHN0cihleGNlcHRpb24pCgogICAgZGVmIGlzX2ZhaWxlZChzZWxmKSAtPiBib29sOgogICAgICAgICIiIgogICAgICAgIENoZWNrIGlmIHRoZSB0YXNrIGZhaWxlZC4KCiAgICAgICAgOnJldHVybnM6IFdoZXRoZXIgdGhlIHRhc2sgZmFpbGVkLgogICAgICAgICIiIgogICAgICAgIHJldHVybiBzZWxmLl9lcnJvciBpcyBub3QgTm9uZQoKICAgIGRlZiBnZXRfcmVzdWx0KHNlbGYpIC0+IFR1cGxlW3N0ciwgc3RyXToKICAgICAgICAiIiIKICAgICAgICBHZXQgdGhlIHJlc3VsdCBvZiB0aGUgdGFzay4gSWYgdGhlIHRhc2sgZmFpbGVkLCB0aGUgZXJyb3Igd2lsbCBiZSByZXR1cm5lZCwgb3RoZXJ3aXNlLCB0aGUgcmVzdWx0IHdpbGwgYmUgdGhlCiAgICAgICAgdGV4dCBmaWxlIG5hbWUuCgogICAgICAgIDpyZXR1cm5zOiBUaGUgdGFzaydzIHJlc3VsdC4KICAgICAgICAiIiIKICAgICAgICBpZiBzZWxmLmlzX2ZhaWxlZCgpOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fYXVkaW9fZmlsZS5uYW1lLCBzZWxmLl9lcnJvcgogICAgICAgIHJldHVybiBzZWxmLl9hdWRpb19maWxlLm5hbWUsIHNlbGYuX3RleHRfZmlsZS5uYW1lCgogICAgZGVmIHRvX3R1cGxlKHNlbGYpIC0+IFR1cGxlW3N0ciwgZGljdF06CiAgICAgICAgIiIiCiAgICAgICAgQ29udmVydCB0aGUgdGFzayB0byBhIHR1cGxlIHRvIHJlY29uc3RydWN0IGl0IGxhdGVyICh1c2VkIGZvciBtdWx0aXByb2Nlc3NpbmcgdG8gcGFzcyBpbiBxdWV1ZSkuCgogICAgICAgIDpyZXR1cm5zOiBUaGUgY29udmVydGVkIHRhc2suCiAgICAgICAgIiIiCiAgICAgICAgcmV0dXJuIHNlbGYuX19jbGFzc19fLl9fbmFtZV9fLCB7CiAgICAgICAgICAgICJhdWRpb19maWxlIjogc2VsZi5fYXVkaW9fZmlsZSwKICAgICAgICAgICAgInRyYW5zY3JpcHRpb25fb3V0cHV0Ijogc2VsZi5fdHJhbnNjcmlwdGlvbl9vdXRwdXQsCiAgICAgICAgICAgICJ0ZXh0X2ZpbGUiOiBzZWxmLl90ZXh0X2ZpbGUsCiAgICAgICAgfQoKICAgIGRlZiBfZG9fdGFzayhzZWxmKToKICAgICAgICAiIiIKICAgICAgICBQZXJmb3JtIHRoZSB0YXNrIC0gd3JpdGUgdGhlIHRyYW5zY3JpcHRpb24gdG8gdGhlIHN0b3JlZCBmaWxlIHBhdGguCiAgICAgICAgIiIiCiAgICAgICAgIyBDaGVja2luZyBmb3Igbm8gZHVwbGljYXRpb25zOgogICAgICAgIGkgPSAxCiAgICAgICAgd2hpbGUgc2VsZi5fdGV4dF9maWxlLmV4aXN0cygpOgogICAgICAgICAgICBpICs9IDEKICAgICAgICAgICAgc2VsZi5fdGV4dF9maWxlID0gKAogICAgICAgICAgICAgICAgc2VsZi5fdGV4dF9maWxlLnBhcmVudAogICAgICAgICAgICAgICAgLyBmIntzZWxmLl90ZXh0X2ZpbGUuc3RlbS5yc3BsaXQoJ18nLCAxKVswXX1fe2l9e3NlbGYuX3RleHRfZmlsZS5zdWZmaXh9IgogICAgICAgICAgICApCgogICAgICAgICMgTWFrZSBzdXJlIGFsbCBkaXJlY3RvcmllcyBhcmUgY3JlYXRlZDoKICAgICAgICBzZWxmLl90ZXh0X2ZpbGUucGFyZW50Lm1rZGlyKGV4aXN0X29rPVRydWUsIHBhcmVudHM9VHJ1ZSkKCiAgICAgICAgIyBXcml0ZSB0byBmaWxlOgogICAgICAgIHdpdGggb3BlbihzZWxmLl90ZXh0X2ZpbGUsICJ3IikgYXMgZnA6CiAgICAgICAgICAgIGZwLndyaXRlKHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0WyJ0ZXh0Il0pCgoKY2xhc3MgU3BlZWNoRGlhcml6YXRpb25UYXNrKEJhc2VUYXNrKToKICAgICIiIgogICAgQSB0YXNrIHRvIHdyaXRlIHRoZSB0cmFuc2NyaXB0aW9uIHRvIGZpbGUgd2l0aCByZXNwZWN0IHRvIGEgZ2l2ZW4gc3BlZWNoIGRpYXJpemF0aW9uLgogICAgIiIiCgogICAgY2xhc3MgX0RpYXJpemF0aW9uU2VnbWVudChOYW1lZFR1cGxlKToKICAgICAgICAiIiIKICAgICAgICBBIHNwZWVjaCBkaWFyaXphdGlvbiBzZWdtZW50LgogICAgICAgICIiIgoKICAgICAgICBzdGFydDogZmxvYXQKICAgICAgICBlbmQ6IGZsb2F0CiAgICAgICAgc3BlYWtlcjogc3RyCgogICAgY2xhc3MgX1dvcmRUaW1lc3RhbXAoTmFtZWRUdXBsZSk6CiAgICAgICAgIiIiCiAgICAgICAgQSB3b3JkIHdpdGggaXRzIHN0YXJ0IGFuZCBlbmQgdGltZXN0YW1wcy4KICAgICAgICAiIiIKCiAgICAgICAgc3RhcnQ6IGZsb2F0CiAgICAgICAgZW5kOiBmbG9hdAogICAgICAgIHRleHQ6IHN0cgoKICAgIGRlZiBfX2luaXRfXygKICAgICAgICBzZWxmLAogICAgICAgIGF1ZGlvX2ZpbGU6IFBhdGgsCiAgICAgICAgdHJhbnNjcmlwdGlvbl9vdXRwdXQ6IGRpY3QsCiAgICAgICAgdGV4dF9maWxlOiBQYXRoLAogICAgICAgIHNwZWVjaF9kaWFyaXphdGlvbjogTGlzdFtUdXBsZVtmbG9hdCwgZmxvYXQsIHN0cl1dLAogICAgKToKICAgICAgICAiIiIKICAgICAgICBJbml0aWFsaXplIHRoZSB0YXNrLgoKICAgICAgICA6cGFyYW0gYXVkaW9fZmlsZTogICAgICAgICAgIFBhdGggdG8gdGhlIGF1ZGlvIGZpbGUgdGhhdCB3YXMgdHJhbnNjcmliZWQuCiAgICAgICAgOnBhcmFtIHRyYW5zY3JpcHRpb25fb3V0cHV0OiBUaGUgdHJhbnNjcmlwdGlvbiBvdXRwdXQgZnJvbSB0aGUgcGlwZWxpbmUuCiAgICAgICAgOnBhcmFtIHRleHRfZmlsZTogICAgICAgICAgICBQYXRoIHRvIHRoZSB0ZXh0IGZpbGUgdG8gd3JpdGUgdGhlIHRyYW5zY3JpcHRpb24gdG8uCiAgICAgICAgOnBhcmFtIHNwZWVjaF9kaWFyaXphdGlvbjogICBBIHNwZWVjaCBkaWFyaXphdGlvbiBhcyBhIGxpc3Qgb2YgdHVwbGVzOiAoc3RhcnQsIGVuZCwgc3BlYWtlcikuCiAgICAgICAgIiIiCiAgICAgICAgc3VwZXIoKS5fX2luaXRfXygKICAgICAgICAgICAgYXVkaW9fZmlsZT1hdWRpb19maWxlLAogICAgICAgICAgICB0cmFuc2NyaXB0aW9uX291dHB1dD10cmFuc2NyaXB0aW9uX291dHB1dCwKICAgICAgICAgICAgdGV4dF9maWxlPXRleHRfZmlsZSwKICAgICAgICApCiAgICAgICAgc2VsZi5fc3BlZWNoX2RpYXJpemF0aW9uID0gc3BlZWNoX2RpYXJpemF0aW9uCiAgICAgICAgc2VsZi5fc2VnbWVudHM6IExpc3RbU3BlZWNoRGlhcml6YXRpb25UYXNrLl9EaWFyaXphdGlvblNlZ21lbnRdID0gTm9uZQogICAgICAgIHNlbGYuX2xhc3RfY2hvc2VuX2luZGV4ID0gMAoKICAgIGRlZiB0b190dXBsZShzZWxmKSAtPiBUdXBsZVtzdHIsIGRpY3RdOgogICAgICAgICIiIgogICAgICAgIENvbnZlcnQgdGhlIHRhc2sgdG8gYSB0dXBsZSB0byByZWNvbnN0cnVjdCBpdCBsYXRlciAodXNlZCBmb3IgbXVsdGlwcm9jZXNzaW5nIHRvIHBhc3MgaW4gcXVldWUpLgoKICAgICAgICA6cmV0dXJuczogVGhlIGNvbnZlcnRlZCB0YXNrLgogICAgICAgICIiIgogICAgICAgIHRhc2tfY2xhc3MsIHRhc2tfa3dhcmdzID0gc3VwZXIoKS50b190dXBsZSgpCiAgICAgICAgcmV0dXJuIHRhc2tfY2xhc3MsIHsKICAgICAgICAgICAgKip0YXNrX2t3YXJncywKICAgICAgICAgICAgInNwZWVjaF9kaWFyaXphdGlvbiI6IHNlbGYuX3NwZWVjaF9kaWFyaXphdGlvbiwKICAgICAgICB9CgogICAgZGVmIF9kb190YXNrKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFBlcmZvcm0gdGhlIHRhc2sgLSB3cml0ZSB0aGUgdHJhbnNjcmlwdGlvbiB0byB0aGUgc3RvcmVkIGZpbGUgcGF0aCB3aXRoIHJlc3BlY3QgdG8gdGhlIGdpdmVuIHNwZWVjaCBkaWFyaXphdGlvbi4KICAgICAgICAiIiIKICAgICAgICAjIENoZWNrIGlmIGEgc3BlZWNoIGRpYXJpemF0aW9uIGlzIGdpdmVuLCBpZiBub3QsIGp1c3Qgd3JpdGUgdGhlIHRyYW5zY3JpcHRpb24gdG8gZmlsZToKICAgICAgICBpZiBub3Qgc2VsZi5fc3BlZWNoX2RpYXJpemF0aW9uOgogICAgICAgICAgICBzdXBlcigpLl9kb190YXNrKCkKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgICMgQ2FzdCB0aGUgY2h1bmtzIHRvIHdvcmQgdGltZXN0YW1wcyB0dXBsZXM6CiAgICAgICAgd29yZHMgPSBbCiAgICAgICAgICAgIFNwZWVjaERpYXJpemF0aW9uVGFzay5fV29yZFRpbWVzdGFtcCgKICAgICAgICAgICAgICAgIHN0YXJ0PWNodW5rWyJ0aW1lc3RhbXAiXVswXSwKICAgICAgICAgICAgICAgIGVuZD1jaHVua1sidGltZXN0YW1wIl1bMV0sCiAgICAgICAgICAgICAgICB0ZXh0PWNodW5rWyJ0ZXh0Il0sCiAgICAgICAgICAgICkKICAgICAgICAgICAgZm9yIGNodW5rIGluIHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0WyJjaHVua3MiXQogICAgICAgIF0KCiAgICAgICAgIyBDYXN0IHNwZWVjaCBkaWFyaXphdGlvbiB0byBzZWdtZW50cyB0dXBsZXM6CiAgICAgICAgc2VsZi5fc2VnbWVudHMgPSBbCiAgICAgICAgICAgIFNwZWVjaERpYXJpemF0aW9uVGFzay5fRGlhcml6YXRpb25TZWdtZW50KCpzZWdtZW50KQogICAgICAgICAgICBmb3Igc2VnbWVudCBpbiBzZWxmLl9zcGVlY2hfZGlhcml6YXRpb24KICAgICAgICBdCgogICAgICAgICMgVHJ5IHRvIG1hdGNoIHRoZSBXaGlzcGVyIG1vZGVsIHByZWRpY3RlZCB0aW1lc3RhbXBzIHRvIHRoZSBjbG9zZXN0IGRpYXJpemF0aW9uIHNlZ21lbnQgKGNsb3Nlc3QgZGlhcml6YXRpb24KICAgICAgICAjIHNlZ21lbnQgd2lsbCBiZSB0aGUgbW9zdCBvdmVybGFwcGluZyB3aXRoIHRoZSB3b3JkLCBhbmQgaWYgdGhlcmUgaXMgbm8gb3ZlcmxhcCwgdGhlIGNsb3Nlc3Qgc2VnbWVudCB0byB0aGUKICAgICAgICAjIHdvcmQpOgogICAgICAgIHNwZWFrZXIgPSBzZWxmLl9zZWdtZW50c1tzZWxmLl9sYXN0X2Nob3Nlbl9pbmRleF0uc3BlYWtlcgogICAgICAgIHRleHQgPSBmIntzcGVha2VyfToiCiAgICAgICAgZm9yIHdvcmQgaW4gd29yZHM6CiAgICAgICAgICAgICMgR2V0IHRoZSBuZXh0IGRpYXJpemF0aW9uIHNlZ21lbnQ6CiAgICAgICAgICAgIHNlbGYuX2dldF9uZXh0X3NlZ21lbnQod29yZD13b3JkKQogICAgICAgICAgICAjIENoZWNrIGlmIHRoZSBzZWdtZW50IGlzIG9mIHRoZSBzYW1lIHNwZWFrZXI6CiAgICAgICAgICAgIGlmIHNlbGYuX3NlZ21lbnRzW3NlbGYuX2xhc3RfY2hvc2VuX2luZGV4XS5zcGVha2VyID09IHNwZWFrZXI6CiAgICAgICAgICAgICAgICAjIENvbGxlY3QgdGhlIHdvcmQ6CiAgICAgICAgICAgICAgICB0ZXh0ICs9IHdvcmQudGV4dAogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgIyBBcHBlbmQgYSBuZXdsaW5lIGFuZCB1cGRhdGUgdGhlIG5ldyBzcGVha2VyOgogICAgICAgICAgICAgICAgc3BlYWtlciA9IHNlbGYuX3NlZ21lbnRzW3NlbGYuX2xhc3RfY2hvc2VuX2luZGV4XS5zcGVha2VyCiAgICAgICAgICAgICAgICB0ZXh0ICs9IGYiXG57c3BlYWtlcn06e3dvcmQudGV4dH0iCgogICAgICAgICMgVXBkYXRlIHRoZSB0cmFuc2NyaXB0aW9uIG91dHB1dCB3aXRoIHRoZSBuZXcgdGV4dCB0byB3cml0ZSBpdCB0byBmaWxlOgogICAgICAgIHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0WyJ0ZXh0Il0gPSB0ZXh0CiAgICAgICAgc3VwZXIoKS5fZG9fdGFzaygpCgogICAgZGVmIF9nZXRfbmV4dF9zZWdtZW50KAogICAgICAgIHNlbGYsCiAgICAgICAgd29yZDogX1dvcmRUaW1lc3RhbXAsCiAgICApOgogICAgICAgICIiIgogICAgICAgIEdldCB0aGUgbmV4dCBkaWFyaXphdGlvbiBzZWdtZW50IHRoZSBnaXZlbiB3b3JkIGZhbGxzIGludG8uIFRoZSBgc2VsZi5fbGFzdF9jaG9zZW5faW5kZXhgIHdpbGwgYmUgdXBkYXRlZAogICAgICAgIGFjY29yZGluZ2x5LgoKICAgICAgICA6cGFyYW0gd29yZDogVGhlIHdvcmQgdGltZXN0YW1wIHRvIG1hdGNoIHRvIHRoZSBuZXh0IHNlZ21lbnQuCiAgICAgICAgIiIiCiAgICAgICAgIyBJZiB0aGUgbGFzdCBjaG9zZW4gc2VnbWVudCBpcyB0aGUgbGFzdCBzZWdtZW50LCByZXR1cm4gaXQ6CiAgICAgICAgaWYgc2VsZi5fbGFzdF9jaG9zZW5faW5kZXggPT0gbGVuKHNlbGYuX3NlZ21lbnRzKSAtIDE6CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICAjIEdldCB0aGUgbGFzdCBjaG9zZW4gZGlhcml6YXRpb24gc2VnbWVudDoKICAgICAgICBsYXN0X2Nob3NlbiA9IHNlbGYuX3NlZ21lbnRzW3NlbGYuX2xhc3RfY2hvc2VuX2luZGV4XQoKICAgICAgICAjIE5vbmUgdmFsdWUgbWF5IGFwcGVhciBpZiB0aGUgd29yZCBpcyB0aGUgbGFzdCB3b3JkIGluIHRoZSBhdWRpbyBmaWxlLCBvciBpdCB3YXMgc3BsaXQgZHVyaW5nIGluZmVyZW5jZS4gSW4KICAgICAgICAjIHRoYXQgY2FzZSwgd2UnbGwgc2V0IHRoZSBsYXN0IHNlZ21lbnQ6CiAgICAgICAgaWYgd29yZC5lbmQgaXMgTm9uZToKICAgICAgICAgICAgc2VsZi5fbGFzdF9jaG9zZW5faW5kZXggPSBsZW4oc2VsZi5fc2VnbWVudHMpIC0gMQogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgIyBJZiB0aGUgd29yZCBlbmRzIGJlZm9yZSB0aGUgbGFzdCBjaG9zZW4gc2VnbWVudDoKICAgICAgICBpZiB3b3JkLmVuZCA8PSBsYXN0X2Nob3Nlbi5zdGFydDoKICAgICAgICAgICAgIyBUaGVuIGl0IGlzIHN0aWxsIHRoZSBjbG9zZXN0IHNlZ21lbnQKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgICMgV2UgY2hlY2sgaWYgaXQgZW5kcyBpbnNpZGUgdGhlIGxhc3QgY2hvc2VuIHNlZ21lbnQ6CiAgICAgICAgaWYgd29yZC5lbmQgPCBsYXN0X2Nob3Nlbi5lbmQ6CiAgICAgICAgICAgICMgVGhlbiBpdCBzdGlsbCBpcyB0aGUgY2xvc2VzdCBzZWdtZW50CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICAjIFRoZSB3b3JkIGVuZHMgYWZ0ZXIgdGhlIHNlZ21lbnQsIHdlIG5lZWQgdG8gY29sbGVjdCBhbGwgbmV4dCBzZWdtZW50cyB1cCB1bnRpbCB0aGUgd29yZCBlbmRzIGJlZm9yZSB0aGVtOgogICAgICAgIHBvc3NpYmxlX3NlZ21lbnRzID0gW3NlbGYuX2xhc3RfY2hvc2VuX2luZGV4XQogICAgICAgIGZvciBpIGluIHJhbmdlKHNlbGYuX2xhc3RfY2hvc2VuX2luZGV4ICsgMSwgbGVuKHNlbGYuX3NlZ21lbnRzKSk6CiAgICAgICAgICAgIGlmIHdvcmQuZW5kID4gc2VsZi5fc2VnbWVudHNbaV0uZW5kOgogICAgICAgICAgICAgICAgcG9zc2libGVfc2VnbWVudHMuYXBwZW5kKGkpCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBwb3NzaWJsZV9zZWdtZW50cy5hcHBlbmQoaSkKICAgICAgICAgICAgYnJlYWsKCiAgICAgICAgIyBDaGVjayBmb3IgdGhlIG1vc3Qgb3ZlcmxhcHBpbmcgb3B0aW9uOgogICAgICAgIGJlc3Rfb3ZlcmxhcCA9IDAKICAgICAgICBtb3N0X292ZXJsYXBwaW5nX3NlZ21lbnRfaW5kZXggPSBOb25lCiAgICAgICAgZm9yIGkgaW4gcG9zc2libGVfc2VnbWVudHM6CiAgICAgICAgICAgICMgSWYgdGhlIHdvcmQgc3RhcnRzIGJlZm9yZSBzZWdtZW50OgogICAgICAgICAgICBpZiB3b3JkLnN0YXJ0IDw9IHNlbGYuX3NlZ21lbnRzW2ldLnN0YXJ0OgogICAgICAgICAgICAgICAgIyBJZiBpdCBlbmRzIGJlZm9yZSB0aGUgc2VnbWVudCwgdGhlcmUgaXMgYW4gb3ZlcmxhcCBmcm9tIHRoZSBzdGFydCBvZiB0aGUgc2VnbWVudCB0byB0aGUgZW5kIG9mIHRoZQogICAgICAgICAgICAgICAgIyB3b3JkOgogICAgICAgICAgICAgICAgaWYgd29yZC5lbmQgPCBzZWxmLl9zZWdtZW50c1tpXS5lbmQ6CiAgICAgICAgICAgICAgICAgICAgb3ZlcmxhcCA9IHdvcmQuZW5kIC0gc2VsZi5fc2VnbWVudHNbaV0uc3RhcnQKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgIyBUaGUgd29yZCBpcyB3cmFwcGluZyB0aGUgc2VnbWVudCwgdGhlIG92ZXJsYXAgaXMgdGhlIHNlZ21lbnQncyBsZW5ndGg6CiAgICAgICAgICAgICAgICAgICAgb3ZlcmxhcCA9IHNlbGYuX3NlZ21lbnRzW2ldLmVuZCAtIHNlbGYuX3NlZ21lbnRzW2ldLnN0YXJ0CiAgICAgICAgICAgICMgVGhlIHdvcmQgc3RhcnRzIGluIHNlZ21lbnQsIGNoZWNrIGlmIHRoZSB3b3JkIGVuZHMgaW4gaXQ6CiAgICAgICAgICAgIGVsaWYgd29yZC5lbmQgPCBzZWxmLl9zZWdtZW50c1tpXS5lbmQ6CiAgICAgICAgICAgICAgICAjIFRoZSBvdmVybGFwIGlzIHRoZSB3b3JkJ3MgbGVuZ3RoOgogICAgICAgICAgICAgICAgb3ZlcmxhcCA9IHdvcmQuZW5kIC0gd29yZC5zdGFydAogICAgICAgICAgICAjIFRoZSB3b3JkIHN0YXJ0IGluIHNlZ21lbnQgYnV0IGVuZHMgYWZ0ZXIgaXQsIHRoZSBvdmVybGFwIGlzIGZyb20gdGhlIHdvcmQncyBzdGFydCB0byB0aGUgc2VnbWVudCdzIGVuZDoKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIG92ZXJsYXAgPSBzZWxmLl9zZWdtZW50c1tpXS5lbmQgLSB3b3JkLnN0YXJ0CiAgICAgICAgICAgICMgQ2hlY2sgZm9yIG5ldyBiZXN0IG92ZXJsYXA6CiAgICAgICAgICAgIGlmIG92ZXJsYXAgPiBiZXN0X292ZXJsYXA6CiAgICAgICAgICAgICAgICBiZXN0X292ZXJsYXAgPSBvdmVybGFwCiAgICAgICAgICAgICAgICBtb3N0X292ZXJsYXBwaW5nX3NlZ21lbnRfaW5kZXggPSBpCiAgICAgICAgaWYgbW9zdF9vdmVybGFwcGluZ19zZWdtZW50X2luZGV4IGlzIG5vdCBOb25lOgogICAgICAgICAgICBzZWxmLl9sYXN0X2Nob3Nlbl9pbmRleCA9IG1vc3Rfb3ZlcmxhcHBpbmdfc2VnbWVudF9pbmRleAogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgIyBJZiB0aGVyZSBpcyBubyBvdmVybGFwcGluZyBzZWdtZW50LCByZXR1cm4gdGhlIGNsb3Nlc3Qgc2VnbWVudDoKICAgICAgICBiZXN0X2Rpc3RhbmNlID0gTm9uZQogICAgICAgIGNsb3Nlc3Rfc2VnbWVudF9pbmRleCA9IE5vbmUKICAgICAgICBmb3IgaSBpbiBwb3NzaWJsZV9zZWdtZW50czoKICAgICAgICAgICAgZGlzdGFuY2UgPSAoCiAgICAgICAgICAgICAgICB3b3JkLnN0YXJ0IC0gc2VsZi5fc2VnbWVudHNbaV0uZW5kCiAgICAgICAgICAgICAgICBpZiB3b3JkLnN0YXJ0ID4gc2VsZi5fc2VnbWVudHNbaV0uZW5kCiAgICAgICAgICAgICAgICBlbHNlIHNlbGYuX3NlZ21lbnRzW2ldLnN0YXJ0IC0gd29yZC5lbmQKICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBiZXN0X2Rpc3RhbmNlIGlzIE5vbmUgb3IgZGlzdGFuY2UgPCBiZXN0X2Rpc3RhbmNlOgogICAgICAgICAgICAgICAgYmVzdF9kaXN0YW5jZSA9IGRpc3RhbmNlCiAgICAgICAgICAgICAgICBjbG9zZXN0X3NlZ21lbnRfaW5kZXggPSBpCiAgICAgICAgc2VsZi5fbGFzdF9jaG9zZW5faW5kZXggPSBjbG9zZXN0X3NlZ21lbnRfaW5kZXgKCgpjbGFzcyBTcGVlY2hEaWFyaXphdGlvblBlckNoYW5uZWxUYXNrKEJhc2VUYXNrKToKICAgICIiIgogICAgQSB0YXNrIHRvIHdyaXRlIHRoZSB0cmFuc2NyaXB0aW9uIHRvIGZpbGUgd2l0aCByZXNwZWN0IHRvIGEgZ2l2ZW4gc3BlZWNoIGRpYXJpemF0aW9uIHBlciBjaGFubmVsLgogICAgIiIiCgogICAgY2xhc3MgX1dvcmRUaW1lc3RhbXAoTmFtZWRUdXBsZSk6CiAgICAgICAgIiIiCiAgICAgICAgQSB3b3JkIHdpdGggaXRzIHN0YXJ0IGFuZCBlbmQgdGltZXN0YW1wcyBhbmQgc3BlYWtlciBsYWJlbCAoY2hhbm5lbCB0aGUgd29yZCB3YXMgdGFrZW4gZnJvbSkuCiAgICAgICAgIiIiCgogICAgICAgIHN0YXJ0OiBmbG9hdAogICAgICAgIGVuZDogZmxvYXQKICAgICAgICBzcGVha2VyOiBzdHIKICAgICAgICB0ZXh0OiBzdHIKCiAgICBkZWYgX19pbml0X18oc2VsZiwgYXVkaW9fZmlsZTogUGF0aCwgdGV4dF9maWxlOiBQYXRoKToKICAgICAgICAiIiIKICAgICAgICBJbml0aWFsaXplIHRoZSB0YXNrLgoKICAgICAgICA6cGFyYW0gYXVkaW9fZmlsZTogUGF0aCB0byB0aGUgYXVkaW8gZmlsZSB0aGF0IHdhcyB0cmFuc2NyaWJlZC4KICAgICAgICA6cGFyYW0gdGV4dF9maWxlOiAgUGF0aCB0byB0aGUgdGV4dCBmaWxlIHRvIHdyaXRlIHRoZSB0cmFuc2NyaXB0aW9uIHRvLgogICAgICAgICIiIgogICAgICAgIHN1cGVyKCkuX19pbml0X18oCiAgICAgICAgICAgIGF1ZGlvX2ZpbGU9YXVkaW9fZmlsZSwgdHJhbnNjcmlwdGlvbl9vdXRwdXQ9e30sIHRleHRfZmlsZT10ZXh0X2ZpbGUKICAgICAgICApCiAgICAgICAgc2VsZi5fdHJhbnNjcmlwdGlvbl9vdXRwdXRfY2hhbm5lbHM6IExpc3RbVHVwbGVbc3RyLCBkaWN0XV0gPSBbXQoKICAgIEBwcm9wZXJ0eQogICAgZGVmIHRyYW5zY3JpcHRpb25fb3V0cHV0X2NoYW5uZWxzKHNlbGYpIC0+IExpc3RbVHVwbGVbc3RyLCBkaWN0XV06CiAgICAgICAgIiIiCiAgICAgICAgR2V0IHRoZSB0cmFuc2NyaXB0aW9uIG91dHB1dCBjaGFubmVscy4KCiAgICAgICAgOnJldHVybnM6IFRoZSB0cmFuc2NyaXB0aW9uIG91dHB1dCBjaGFubmVscy4KICAgICAgICAiIiIKICAgICAgICByZXR1cm4gc2VsZi5fdHJhbnNjcmlwdGlvbl9vdXRwdXRfY2hhbm5lbHMKCiAgICBkZWYgZG9fdGFzayhzZWxmKToKICAgICAgICAiIiIKICAgICAgICBUcnkgdG8gcGVyZm9ybSB0aGUgdGFzayBzdG9yaW5nIGFuIGVycm9yIGlmIG9jY3VycmVkLgogICAgICAgICIiIgogICAgICAgIGZvciBfLCBjaGFubmVsX291dHB1dCBpbiBzZWxmLl90cmFuc2NyaXB0aW9uX291dHB1dF9jaGFubmVsczoKICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShjaGFubmVsX291dHB1dCwgc3RyKToKICAgICAgICAgICAgICAgIHNlbGYuX2Vycm9yID0gc2VsZi5fdHJhbnNjcmlwdGlvbl9vdXRwdXRfY2hhbm5lbHMKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgIHN1cGVyKCkuZG9fdGFzaygpCgogICAgZGVmIHRvX3R1cGxlKHNlbGYpIC0+IFR1cGxlW3N0ciwgZGljdF06CiAgICAgICAgIiIiCiAgICAgICAgQ29udmVydCB0aGUgdGFzayB0byBhIHR1cGxlIHRvIHJlY29uc3RydWN0IGl0IGxhdGVyICh1c2VkIGZvciBtdWx0aXByb2Nlc3NpbmcgdG8gcGFzcyBpbiBxdWV1ZSkuCgogICAgICAgIDpyZXR1cm5zOiBUaGUgY29udmVydGVkIHRhc2suCiAgICAgICAgIiIiCiAgICAgICAgdGFza19jbGFzcywgdGFza19rd2FyZ3MgPSBzdXBlcigpLnRvX3R1cGxlKCkKICAgICAgICB0YXNrX2t3YXJncy5wb3AoInRyYW5zY3JpcHRpb25fb3V0cHV0IikKICAgICAgICByZXR1cm4gdGFza19jbGFzcywgdGFza19rd2FyZ3MKCiAgICBkZWYgX2RvX3Rhc2soc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgUGVyZm9ybSB0aGUgdGFzayAtIHdyaXRlIHRoZSB0cmFuc2NyaXB0aW9uIHRvIHRoZSBzdG9yZWQgZmlsZSBwYXRoIHdpdGggcmVzcGVjdCB0byB0aGUgZ2l2ZW4gc3BlZWNoIGRpYXJpemF0aW9uCiAgICAgICAgcGVyIGNoYW5uZWwuCiAgICAgICAgIiIiCiAgICAgICAgIyBDYXN0IHRoZSBjaHVua3MgdG8gd29yZCB0aW1lc3RhbXBzIHR1cGxlczoKICAgICAgICB3b3Jkc19wZXJfY2hhbm5lbCA9IFsKICAgICAgICAgICAgWwogICAgICAgICAgICAgICAgU3BlZWNoRGlhcml6YXRpb25QZXJDaGFubmVsVGFzay5fV29yZFRpbWVzdGFtcCgKICAgICAgICAgICAgICAgICAgICBzdGFydD1jaHVua1sidGltZXN0YW1wIl1bMF0sCiAgICAgICAgICAgICAgICAgICAgZW5kPWNodW5rWyJ0aW1lc3RhbXAiXVsxXSwKICAgICAgICAgICAgICAgICAgICBzcGVha2VyPXNwZWFrZXIsCiAgICAgICAgICAgICAgICAgICAgdGV4dD1jaHVua1sidGV4dCJdLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgZm9yIGNodW5rIGluIG91dHB1dFsiY2h1bmtzIl0KICAgICAgICAgICAgXQogICAgICAgICAgICBmb3Igc3BlYWtlciwgb3V0cHV0IGluIHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0X2NoYW5uZWxzCiAgICAgICAgXQoKICAgICAgICAjIE1lcmdlIGFuZCBzb3J0IHRoZSB3b3JkcyBwZXIgY2hhbm5lbCBieSB0aGVpciBzdGFydCB0aW1lOgogICAgICAgIHdvcmRzID0gb3BlcmF0b3IuYWRkKCp3b3Jkc19wZXJfY2hhbm5lbCkKICAgICAgICB3b3Jkcy5zb3J0KCkKCiAgICAgICAgIyBXcml0ZSB0aGUgdHJhbnNjcmlwdGlvbiB0byBmaWxlOgogICAgICAgIGN1cnJlbnRfc3BlYWtlciA9IHdvcmRzWzBdLnNwZWFrZXIKICAgICAgICB0ZXh0ID0gZiJ7Y3VycmVudF9zcGVha2VyfToiCiAgICAgICAgZm9yIHdvcmQgaW4gd29yZHM6CiAgICAgICAgICAgICMgQ2hlY2sgaWYgdGhlIHdvcmQncyBzcGVha2VyIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBjdXJyZW50IG9uZToKICAgICAgICAgICAgaWYgd29yZC5zcGVha2VyICE9IGN1cnJlbnRfc3BlYWtlcjoKICAgICAgICAgICAgICAgICMgQXBwZW5kIGEgbmV3bGluZSBhbmQgdXBkYXRlIHRoZSBuZXcgc3BlYWtlcjoKICAgICAgICAgICAgICAgIGN1cnJlbnRfc3BlYWtlciA9IHdvcmQuc3BlYWtlcgogICAgICAgICAgICAgICAgdGV4dCArPSBmIlxue2N1cnJlbnRfc3BlYWtlcn06IgogICAgICAgICAgICAjIENvbGxlY3QgdGhlIHdvcmQ6CiAgICAgICAgICAgIHRleHQgKz0gd29yZC50ZXh0CgogICAgICAgICMgVXBkYXRlIHRoZSB0cmFuc2NyaXB0aW9uIG91dHB1dCB3aXRoIHRoZSBuZXcgdGV4dCB0byB3cml0ZSBpdCB0byBmaWxlOgogICAgICAgIHNlbGYuX3RyYW5zY3JpcHRpb25fb3V0cHV0WyJ0ZXh0Il0gPSB0ZXh0CiAgICAgICAgc3VwZXIoKS5fZG9fdGFzaygpCgoKY2xhc3MgQmF0Y2hQcm9jZXNzb3I6CiAgICAiIiIKICAgIEEgYmF0Y2ggcHJvY2Vzc29yIHRvIHByb2Nlc3MgYmF0Y2hlcyBvZiB0cmFuc2NyaXB0aW9ucy4gVGhlIGJhdGNoIHByb2Nlc3NvciBpcyBjcmVhdGluZyB0YXNrcyBhbmQgaXMgYWltZWQgdG8gYmUKICAgIHdvcmtpbmcgYWxvbmcgdGhlIHRyYW5zY3JpYmVyLiBJdCBjYW4gYmUgdXNlZCB3aXRoIG11bHRpcHJvY2Vzc2luZyBxdWV1ZSBvciBydW4gdGhlIHRhc2tzIGRpcmVjdGx5IHVzaW5nIHRoZQogICAgYXNzb2NpYXRlZCBtZXRob2RzLgogICAgIiIiCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGF1ZGlvX2ZpbGVzOiBMaXN0W1BhdGhdLCBvdXRwdXRfZGlyZWN0b3J5OiBQYXRoKToKICAgICAgICAiIiIKICAgICAgICBJbml0aWFsaXplIHRoZSBiYXRjaCBwcm9jZXNzb3IuCgogICAgICAgIDpwYXJhbSBhdWRpb19maWxlczogICAgICBUaGUgbGlzdCBvZiBhbGwgYXVkaW8gZmlsZXMgdG8gdHJhbnNjcmliZS4KICAgICAgICA6cGFyYW0gb3V0cHV0X2RpcmVjdG9yeTogVGhlIG91dHB1dCBkaXJlY3RvcnkgdG8gd3JpdGUgdGhlIHRyYW5zY3JpcHRpb25zIHRvLgogICAgICAgICIiIgogICAgICAgICMgU3RvcmUgdGhlIHBhcmFtZXRlcnM6CiAgICAgICAgc2VsZi5fYXVkaW9fZmlsZXMgPSBhdWRpb19maWxlcwogICAgICAgIHNlbGYuX291dHB1dF9kaXJlY3RvcnkgPSBvdXRwdXRfZGlyZWN0b3J5CgogICAgICAgICMgUHJlcGFyZSB0aGUgYmF0Y2hpbmcgdmFyaWFibGVzOgogICAgICAgIHNlbGYuX2N1cnJlbnRfZmlsZV9pbmRleCA9IDAKICAgICAgICBzZWxmLl90YXNrczogTGlzdFtCYXNlVGFza10gPSBbXQogICAgICAgIHNlbGYuX3Jlc3VsdHM6IExpc3RbVHVwbGVbYm9vbCwgVHVwbGVbc3RyLCBzdHJdXV0gPSBbXQoKICAgIGRlZiBwcm9jZXNzX2JhdGNoKHNlbGYsIGJhdGNoOiBMaXN0W1VuaW9uW2RpY3QsIHN0cl1dKToKICAgICAgICAiIiIKICAgICAgICBQcm9jZXNzIGEgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMuIFRhc2tzIHJlbGF0ZWQgdG8gdGhlIGdpdmVuIGJhdGNoIHdpbGwgYmUgY3JlYXRlZCBhbmQgc3RvcmVkIGluIHRoZSBiYXRjaAogICAgICAgIHByb2Nlc3Nvci4KCiAgICAgICAgOnBhcmFtIGJhdGNoOiBUaGUgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMgdG8gcHJvY2Vzcy4KICAgICAgICAiIiIKICAgICAgICAjIEdldCB0aGUgcmVsZXZhbnQgZmlsZXMgYmVsb25ncyB0byB0aGUgZ2l2ZW4gYmF0Y2g6CiAgICAgICAgY3VycmVudF9maWxlcyA9IHNlbGYuX2dldF9jdXJyZW50X2ZpbGVzKGJhdGNoX3NpemU9bGVuKGJhdGNoKSkKCiAgICAgICAgIyBCdWlsZCB0aGUgZGlhcml6YXRpb24gdGFza3M6CiAgICAgICAgc2VsZi5fdGFza3MuZXh0ZW5kKAogICAgICAgICAgICBbCiAgICAgICAgICAgICAgICBCYXNlVGFzaygKICAgICAgICAgICAgICAgICAgICBhdWRpb19maWxlPWZpbGUsCiAgICAgICAgICAgICAgICAgICAgdHJhbnNjcmlwdGlvbl9vdXRwdXQ9YmF0Y2hbaV0sCiAgICAgICAgICAgICAgICAgICAgdGV4dF9maWxlPXNlbGYuX291dHB1dF9kaXJlY3RvcnkgLyBmIntmaWxlLnN0ZW19LnR4dCIsCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICBmb3IgaSwgZmlsZSBpbiBlbnVtZXJhdGUoY3VycmVudF9maWxlcykKICAgICAgICAgICAgXQogICAgICAgICkKCiAgICBkZWYgZ2V0X3Rhc2tzKHNlbGYpIC0+IExpc3RbQmFzZVRhc2tdOgogICAgICAgICIiIgogICAgICAgIEdldCB0aGUgdGFza3MgdG8gcGVyZm9ybS4KCiAgICAgICAgOnJldHVybnM6IFRoZSB0YXNrcyB0byBwZXJmb3JtLgogICAgICAgICIiIgogICAgICAgIHRhc2tzID0gc2VsZi5fdGFza3MKICAgICAgICBzZWxmLl90YXNrcyA9IFtdCiAgICAgICAgcmV0dXJuIHRhc2tzCgogICAgZGVmIGRvX3Rhc2tzKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFBlcmZvcm0gdGhlIHRhc2tzLiBTaG91bGQgYmUgdXNlZCBpZiBubyBtdWx0aXByb2Nlc3NpbmcgcXVldWUgaXMgZ2l2ZW4gdG8gYSB0cmFuc2NyaWJlci4KICAgICAgICAiIiIKICAgICAgICBmb3IgdGFzayBpbiBzZWxmLmdldF90YXNrcygpOgogICAgICAgICAgICB0YXNrLmRvX3Rhc2soKQogICAgICAgICAgICBzZWxmLl9yZXN1bHRzLmFwcGVuZCgodGFzay5pc19mYWlsZWQoKSwgdGFzay5nZXRfcmVzdWx0KCkpKQoKICAgIGRlZiBnZXRfcmVzdWx0cyhzZWxmKSAtPiBMaXN0W1R1cGxlW2Jvb2wsIFR1cGxlW3N0ciwgc3RyXV1dOgogICAgICAgICIiIgogICAgICAgIEdldCB0aGUgcmVzdWx0cyBvZiB0aGUgdGFza3MuIFRoZSBzdG9yZWQgcmVzdWx0cyBhcmUgdGhlbiBjbGVhcmVkLgoKICAgICAgICA6cmV0dXJuczogVGhlIHJlc3VsdHMgb2YgdGhlIHRhc2tzLgogICAgICAgICIiIgogICAgICAgIHJlc3VsdHMgPSBzZWxmLl9yZXN1bHRzCiAgICAgICAgc2VsZi5fcmVzdWx0cyA9IFtdCiAgICAgICAgcmV0dXJuIHJlc3VsdHMKCiAgICBkZWYgX2dldF9jdXJyZW50X2ZpbGVzKHNlbGYsIGJhdGNoX3NpemU6IGludCkgLT4gTGlzdFtQYXRoXToKICAgICAgICAiIiIKICAgICAgICBHZXQgdGhlIGN1cnJlbnQgZmlsZXMgdG8gcHJvY2Vzcy4KCiAgICAgICAgOnBhcmFtIGJhdGNoX3NpemU6IFRoZSBiYXRjaCBzaXplIHRvIHByb2dyZXNzIHRoZSBjdXJyZW50IGZpbGUgaW5kZXguCgogICAgICAgIDpyZXR1cm5zOiBUaGUgY3VycmVudCBmaWxlcyB0byBwcm9jZXNzLgogICAgICAgICIiIgogICAgICAgIGVuZF9pbmRleCA9ICgKICAgICAgICAgICAgc2VsZi5fY3VycmVudF9maWxlX2luZGV4ICsgYmF0Y2hfc2l6ZQogICAgICAgICAgICBpZiBzZWxmLl9jdXJyZW50X2ZpbGVfaW5kZXggKyBiYXRjaF9zaXplIDwgbGVuKHNlbGYuX2F1ZGlvX2ZpbGVzKQogICAgICAgICAgICBlbHNlIGxlbihzZWxmLl9hdWRpb19maWxlcykKICAgICAgICApCiAgICAgICAgY3VycmVudF9maWxlcyA9IHNlbGYuX2F1ZGlvX2ZpbGVzW3NlbGYuX2N1cnJlbnRfZmlsZV9pbmRleCA6IGVuZF9pbmRleF0KICAgICAgICBzZWxmLl9jdXJyZW50X2ZpbGVfaW5kZXggPSBlbmRfaW5kZXgKICAgICAgICByZXR1cm4gY3VycmVudF9maWxlcwoKCmNsYXNzIFNwZWVjaERpYXJpemF0aW9uQmF0Y2hQcm9jZXNzb3IoQmF0Y2hQcm9jZXNzb3IpOgogICAgIiIiCiAgICBBIGJhdGNoIHByb2Nlc3NvciB0byBwcm9jZXNzIGJhdGNoZXMgb2YgdHJhbnNjcmlwdGlvbnMgd2l0aCByZXNwZWN0IHRvIGEgZ2l2ZW4gc3BlZWNoIGRpYXJpemF0aW9uLiBUaGUgYmF0Y2gKICAgIHByb2Nlc3NvciBpcyBjcmVhdGluZyB0YXNrcyBhbmQgaXMgYWltZWQgdG8gYmUgd29ya2luZyBhbG9uZyB0aGUgdHJhbnNjcmliZXIuIEl0IGNhbiBiZSB1c2VkIHdpdGggbXVsdGlwcm9jZXNzaW5nCiAgICBxdWV1ZSBvciBydW4gdGhlIHRhc2tzIGRpcmVjdGx5IHVzaW5nIHRoZSBhc3NvY2lhdGVkIG1ldGhvZHMuCiAgICAiIiIKCiAgICBkZWYgX19pbml0X18oCiAgICAgICAgc2VsZiwgYXVkaW9fZmlsZXM6IExpc3RbUGF0aF0sIG91dHB1dF9kaXJlY3Rvcnk6IFBhdGgsIHNwZWVjaF9kaWFyaXphdGlvbjogZGljdAogICAgKToKICAgICAgICAiIiIKICAgICAgICBJbml0aWFsaXplIHRoZSBiYXRjaCBwcm9jZXNzb3IuCgogICAgICAgIDpwYXJhbSBhdWRpb19maWxlczogICAgICAgIFRoZSBsaXN0IG9mIGFsbCBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlLgogICAgICAgIDpwYXJhbSBvdXRwdXRfZGlyZWN0b3J5OiAgIFRoZSBvdXRwdXQgZGlyZWN0b3J5IHRvIHdyaXRlIHRoZSB0cmFuc2NyaXB0aW9ucyB0by4KICAgICAgICA6cGFyYW0gc3BlZWNoX2RpYXJpemF0aW9uOiBBIHNwZWVjaCBkaWFyaXphdGlvbiBkaWN0aW9uYXJ5IHRvIHBhc3MgYWxvbmcgd2l0aCBlYWNoIHByb2Nlc3NlZCBiYXRjaC4KICAgICAgICAiIiIKICAgICAgICBzdXBlcigpLl9faW5pdF9fKGF1ZGlvX2ZpbGVzPWF1ZGlvX2ZpbGVzLCBvdXRwdXRfZGlyZWN0b3J5PW91dHB1dF9kaXJlY3RvcnkpCiAgICAgICAgc2VsZi5fc3BlZWNoX2RpYXJpemF0aW9uID0gc3BlZWNoX2RpYXJpemF0aW9uCiAgICAgICAgc2VsZi5fYXVkaW9fZmlsZXMgPSBhdWRpb19maWxlcwoKICAgIGRlZiBwcm9jZXNzX2JhdGNoKHNlbGYsIGJhdGNoOiBMaXN0W2RpY3RdKToKICAgICAgICAiIiIKICAgICAgICBQcm9jZXNzIGEgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMuIFRhc2tzIHJlbGF0ZWQgdG8gdGhlIGdpdmVuIGJhdGNoIHdpbGwgYmUgY3JlYXRlZCBhbmQgc3RvcmVkIGluIHRoZSBiYXRjaAogICAgICAgIHByb2Nlc3Nvci4KCiAgICAgICAgOnBhcmFtIGJhdGNoOiBUaGUgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMgdG8gcHJvY2Vzcy4KICAgICAgICAiIiIKICAgICAgICAjIEdldCB0aGUgcmVsZXZhbnQgZmlsZXMgYmVsb25ncyB0byB0aGUgZ2l2ZW4gYmF0Y2g6CiAgICAgICAgY3VycmVudF9maWxlcyA9IHNlbGYuX2dldF9jdXJyZW50X2ZpbGVzKGJhdGNoX3NpemU9bGVuKGJhdGNoKSkKCiAgICAgICAgIyBCdWlsZCB0aGUgZGlhcml6YXRpb24gdGFza3M6CiAgICAgICAgc2VsZi5fdGFza3MuZXh0ZW5kKAogICAgICAgICAgICBbCiAgICAgICAgICAgICAgICBTcGVlY2hEaWFyaXphdGlvblRhc2soCiAgICAgICAgICAgICAgICAgICAgYXVkaW9fZmlsZT1maWxlLAogICAgICAgICAgICAgICAgICAgIHRyYW5zY3JpcHRpb25fb3V0cHV0PWJhdGNoW2ldLAogICAgICAgICAgICAgICAgICAgIHRleHRfZmlsZT1zZWxmLl9vdXRwdXRfZGlyZWN0b3J5IC8gZiJ7ZmlsZS5zdGVtfS50eHQiLAogICAgICAgICAgICAgICAgICAgIHNwZWVjaF9kaWFyaXphdGlvbj1zZWxmLl9zcGVlY2hfZGlhcml6YXRpb24uZ2V0KGZpbGUubmFtZSksCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICBmb3IgaSwgZmlsZSBpbiBlbnVtZXJhdGUoY3VycmVudF9maWxlcykKICAgICAgICAgICAgXQogICAgICAgICkKCgpjbGFzcyBQZXJDaGFubmVsU3BlZWNoRGlhcml6YXRpb25CYXRjaFByb2Nlc3NvcihCYXRjaFByb2Nlc3Nvcik6CiAgICAiIiIKICAgIEEgYmF0Y2ggcHJvY2Vzc29yIHRvIHByb2Nlc3MgYmF0Y2hlcyBvZiB0cmFuc2NyaXB0aW9ucyBwZXIgY2hhbm5lbC4gVGhlIGJhdGNoIHByb2Nlc3NvciBpcyBjcmVhdGluZyB0YXNrcyB3aXRoIHRoZQogICAgc2VsZWN0ZWQgYW1vdW50IG9mIGNoYW5uZWxzIGdpdmVuIGFuZCBpcyBhaW1lZCB0byBiZSB3b3JraW5nIGFsb25nIHRoZSB0cmFuc2NyaWJlci4gSXQgY2FuIGJlIHVzZWQgd2l0aAogICAgbXVsdGlwcm9jZXNzaW5nIHF1ZXVlIG9yIHJ1biB0aGUgdGFza3MgZGlyZWN0bHkgdXNpbmcgdGhlIGFzc29jaWF0ZWQgbWV0aG9kcy4KICAgICIiIgoKICAgIGRlZiBfX2luaXRfXygKICAgICAgICBzZWxmLAogICAgICAgIGF1ZGlvX2ZpbGVzOiBMaXN0W1BhdGhdLAogICAgICAgIG91dHB1dF9kaXJlY3Rvcnk6IFBhdGgsCiAgICAgICAgbl9jaGFubmVsczogaW50LAogICAgICAgIHNwZWFrZXJzOiBMaXN0W3N0cl0sCiAgICApOgogICAgICAgICIiIgogICAgICAgIEluaXRpYWxpemUgdGhlIGJhdGNoIHByb2Nlc3Nvci4KCiAgICAgICAgOnBhcmFtIGF1ZGlvX2ZpbGVzOiAgICAgIFRoZSBsaXN0IG9mIGFsbCBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlLgogICAgICAgIDpwYXJhbSBvdXRwdXRfZGlyZWN0b3J5OiBUaGUgb3V0cHV0IGRpcmVjdG9yeSB0byB3cml0ZSB0aGUgdHJhbnNjcmlwdGlvbnMgdG8uCiAgICAgICAgOnBhcmFtIG5fY2hhbm5lbHM6ICAgICAgIFRoZSBudW1iZXIgb2YgY2hhbm5lbHMgaW4gZWFjaCBhdWRpbyBmaWxlIHRvIHRyYW5zY3JpYmUuCiAgICAgICAgOnBhcmFtIHNwZWFrZXJzOiAgICAgICAgIFRoZSBzcGVha2VycyBsYWJlbHMgdG8gdXNlIGZvciBlYWNoIGNoYW5uZWwuCiAgICAgICAgIiIiCiAgICAgICAgc3VwZXIoKS5fX2luaXRfXyhhdWRpb19maWxlcz1hdWRpb19maWxlcywgb3V0cHV0X2RpcmVjdG9yeT1vdXRwdXRfZGlyZWN0b3J5KQoKICAgICAgICAjIFN0b3JlIHRoZSBwYXJhbWV0ZXJzOgogICAgICAgIHNlbGYuX25fY2hhbm5lbHMgPSBuX2NoYW5uZWxzCiAgICAgICAgc2VsZi5fc3BlYWtlcnMgPSBzcGVha2VycwoKICAgICAgICAjIFByZXBhcmUgYSBjaGFubmVsIGJ1ZmZlciB0byBzdG9yZSB0aGUgY2hhbm5lbHMgdW50aWwgdGhlIGN1cnJlbnQgdGFzayBjcmVhdGVkIGlzIGZ1bGx5IGNvdmVyZWQ6CiAgICAgICAgc2VsZi5fdGFza19pbl9wcm9jZXNzOiBTcGVlY2hEaWFyaXphdGlvblBlckNoYW5uZWxUYXNrID0gTm9uZQoKICAgIGRlZiBwcm9jZXNzX2JhdGNoKHNlbGYsIGJhdGNoOiBMaXN0W2RpY3RdKToKICAgICAgICAiIiIKICAgICAgICBQcm9jZXNzIGEgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMuIFRhc2tzIHJlbGF0ZWQgdG8gdGhlIGdpdmVuIGJhdGNoIHdpbGwgYmUgY3JlYXRlZCBhbmQgc3RvcmVkIGluIHRoZSBiYXRjaAogICAgICAgIHByb2Nlc3Nvci4KCiAgICAgICAgOnBhcmFtIGJhdGNoOiBUaGUgYmF0Y2ggb2YgdHJhbnNjcmlwdGlvbnMgdG8gcHJvY2Vzcy4KICAgICAgICAiIiIKICAgICAgICAjIEdvIG92ZXIgdGhlIGJhdGNoIGFuZCBjcmVhdGUgdGhlIHRhc2tzOgogICAgICAgIGZvciBvdXRwdXQgaW4gYmF0Y2g6CiAgICAgICAgICAgICMgQ2hlY2sgaWYgdGhlcmUgaXMgYSB0YXNrIGluIHByb2Nlc3M6CiAgICAgICAgICAgIGlmIG5vdCBzZWxmLl90YXNrX2luX3Byb2Nlc3M6CiAgICAgICAgICAgICAgICAjIENyZWF0ZSBhIG5ldyB0YXNrOgogICAgICAgICAgICAgICAgc2VsZi5fdGFza19pbl9wcm9jZXNzID0gU3BlZWNoRGlhcml6YXRpb25QZXJDaGFubmVsVGFzaygKICAgICAgICAgICAgICAgICAgICBhdWRpb19maWxlPXNlbGYuX2F1ZGlvX2ZpbGVzW3NlbGYuX2N1cnJlbnRfZmlsZV9pbmRleF0sCiAgICAgICAgICAgICAgICAgICAgdGV4dF9maWxlPXNlbGYuX291dHB1dF9kaXJlY3RvcnkKICAgICAgICAgICAgICAgICAgICAvIGYie3NlbGYuX2F1ZGlvX2ZpbGVzW3NlbGYuX2N1cnJlbnRfZmlsZV9pbmRleF0uc3RlbX0udHh0IiwKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBHZXQgdGhlIGNoYW5uZWwncyBzcGVha2VyOgogICAgICAgICAgICBzcGVha2VyID0gc2VsZi5fc3BlYWtlcnNbCiAgICAgICAgICAgICAgICBsZW4oc2VsZi5fdGFza19pbl9wcm9jZXNzLnRyYW5zY3JpcHRpb25fb3V0cHV0X2NoYW5uZWxzKQogICAgICAgICAgICBdCiAgICAgICAgICAgICMgQ29sbGVjdCB0aGUgY2hhbm5lbCBpbnRvIHRoZSBwcm9jZXNzZWQgdGFzazoKICAgICAgICAgICAgc2VsZi5fdGFza19pbl9wcm9jZXNzLnRyYW5zY3JpcHRpb25fb3V0cHV0X2NoYW5uZWxzLmFwcGVuZCgKICAgICAgICAgICAgICAgIChzcGVha2VyLCBvdXRwdXQpCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBDaGVjayBpZiB0aGUgdGFzayBpcyBmdWxseSBjb3ZlcmVkIChhbGwgY2hhbm5lbHMgYXJlIGNvbGxlY3RlZCk6CiAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgIGxlbihzZWxmLl90YXNrX2luX3Byb2Nlc3MudHJhbnNjcmlwdGlvbl9vdXRwdXRfY2hhbm5lbHMpCiAgICAgICAgICAgICAgICA9PSBzZWxmLl9uX2NoYW5uZWxzCiAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICAjIENvbGxlY3QgdGhlIHRhc2sgYW5kIHJlc2V0IHRoZSB0YXNrIGluIHByb2Nlc3M6CiAgICAgICAgICAgICAgICBzZWxmLl90YXNrcy5hcHBlbmQoc2VsZi5fdGFza19pbl9wcm9jZXNzKQogICAgICAgICAgICAgICAgc2VsZi5fY3VycmVudF9maWxlX2luZGV4ICs9IDEKICAgICAgICAgICAgICAgIHNlbGYuX3Rhc2tfaW5fcHJvY2VzcyA9IE5vbmUKCgpjbGFzcyBUcmFuc2NyaWJlcjoKICAgICIiIgogICAgQSB0cmFuc2NyaXB0aW9uIHdyYXBwZXIgZm9yIHRoZSBIdWdnaW5nZmFjZSdzIEFTUiBwaXBlbGluZSAtCiAgICBodHRwczovL2h1Z2dpbmdmYWNlLmNvL3RyYW5zZm9ybWVycy9tYWluX2NsYXNzZXMvcGlwZWxpbmVzLmh0bWwjdHJhbnNmb3JtZXJzLkF1dG9tYXRpY1NwZWVjaFJlY29nbml0aW9uUGlwZWxpbmUgdG8KICAgIHVzZSB3aXRoIE9wZW5BSSdzIFdoaXNwZXIgbW9kZWxzIC0gaHR0cHM6Ly9odWdnaW5nZmFjZS5jby9vcGVuYWkuCiAgICAiIiIKCiAgICBkZWYgX19pbml0X18oCiAgICAgICAgc2VsZiwKICAgICAgICBtb2RlbF9uYW1lOiBzdHIsCiAgICAgICAgZGV2aWNlOiBzdHIgPSBOb25lLAogICAgICAgIHVzZV9mbGFzaF9hdHRlbnRpb25fMjogYm9vbCA9IE5vbmUsCiAgICAgICAgdXNlX2JldHRlcl90cmFuc2Zvcm1lcnM6IGJvb2wgPSBOb25lLAogICAgICAgIGFzc2lzdGFudF9tb2RlbDogc3RyID0gTm9uZSwKICAgICAgICBtYXhfbmV3X3Rva2VuczogaW50ID0gMTI4LAogICAgICAgIGNodW5rX2xlbmd0aF9zOiBpbnQgPSAzMCwKICAgICAgICBiYXRjaF9zaXplOiBpbnQgPSAyLAogICAgICAgIHNwb2tlbl9sYW5ndWFnZTogc3RyID0gTm9uZSwKICAgICAgICB0cmFuc2xhdGVfdG9fZW5nbGlzaDogYm9vbCA9IEZhbHNlLAogICAgICAgIHJldHVybl90aW1lc3RhbXBzOiBVbmlvbltib29sLCBMaXRlcmFsWyJ3b3JkIl1dID0gRmFsc2UsCiAgICAgICAgcGVyX2NoYW5uZWxfdHJhbnNjcmlwdGlvbjogaW50ID0gMCwKICAgICk6CiAgICAgICAgIiIiCiAgICAgICAgSW5pdGlhbGl6ZSB0aGUgdHJhbnNjcmliZXIuCgogICAgICAgIDpwYXJhbSBtb2RlbF9uYW1lOiAgICAgICAgICAgICAgICBUaGUgbW9kZWwgbmFtZSB0byB1c2UuIFNob3VsZCBiZSBhIG1vZGVsIGZyb20gdGhlIE9wZW5BSSdzIFdoaXNwZXIgbW9kZWxzIGZvcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXN0IHJlc3VsdHMgKGZvciBleGFtcGxlICJ0aW55IiwgImJhc2UiLCAibGFyZ2UiLCBldGMuKS4KICAgICAgICA6cGFyYW0gZGV2aWNlOiAgICAgICAgICAgICAgICAgICAgVGhlIGRldmljZSB0byB1c2UgZm9yIGluZmVyZW5jZS4gSWYgbm90IGdpdmVuLCB3aWxsIHVzZSBHUFUgaWYgYXZhaWxhYmxlLgogICAgICAgIDpwYXJhbSB1c2VfZmxhc2hfYXR0ZW50aW9uXzI6ICAgICBXaGV0aGVyIHRvIHVzZSB0aGUgRmxhc2ggQXR0ZW50aW9uIDIgaW1wbGVtZW50YXRpb24uIEl0IGNhbiBiZSB1c2VkIG9ubHkgd2l0aAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmUgb2YgdGhlIGZvbGxvd2luZyBHUFVzOiBOdmlkaWEgSCBzZXJpZXMgYW5kIE52aWRpYSBBIHNlcmllcy4gVDQgc3VwcG9ydAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsIGJlIGF2YWlsYWJsZSBzb29uLgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTm90ZTogSWYgYm90aCBgdXNlX2ZsYXNoX2F0dGVudGlvbl8yYCBhbmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHVzZV9iZXR0ZXJfdHJhbnNmb3JtZXJzYCBhcmUgYE5vbmVgLCB0aGUgb3B0aW1pemF0aW9uIHdpbGwgYmUgY2hvc2VuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9tYXRpY2FsbHkgYWNjb3JkaW5nIHRvIHRoZSBhdmFpbGFibGUgcmVzb3VyY2VzLgoKICAgICAgICA6cGFyYW0gdXNlX2JldHRlcl90cmFuc2Zvcm1lcnM6ICAgV2hldGhlciB0byB1c2UgdGhlIEJldHRlciBUcmFuc2Zvcm1lcnMgbGlicmFyeSB0byBmdXJ0aGVyIG9wdGltaXplIHRoZSBtb2RlbC4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2hvdWxkIGJlIHVzZWQgZm9yIGFsbCB1c2UgY2FzZXMgdGhhdCBkbyBub3Qgc3VwcG9ydCBmbGFzaCBhdHRlbnRpb24gMi4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vdGU6IElmIGJvdGggYHVzZV9mbGFzaF9hdHRlbnRpb25fMmAgYW5kIGB1c2VfYmV0dGVyX3RyYW5zZm9ybWVyc2AgYXJlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOb25lYCwgdGhlIG9wdGltaXphdGlvbiB3aWxsIGJlIGNob3NlbiBhdXRvbWF0aWNhbGx5IGFjY29yZGluZyB0byB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZhaWxhYmxlIHJlc291cmNlcy4KICAgICAgIDpwYXJhbSBhc3Npc3RhbnRfbW9kZWw6ICAgICAgICAgICBUaGUgYXNzaXN0YW50IG1vZGVsIG5hbWUgdG8gdXNlIGZvciBpbmZlcmVuY2UuIE5vdGljZSB0aGF0IHRoZSBvcHRpbWl6YXRpb25zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChmbGFzaCBhdHRlbnRpb24gMiBhbmQgYmV0dGVyIHRyYW5zZm9ybWVycykgd2lsbCBiZSBhcHBsaWVkIGZvciB0aGUgYXNzaXN0YW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdlbGwuIFNob3VsZCBiZSBhIG1vZGVsIGZyb20gSHVnZ2luZ2ZhY2UncyBkaXN0aWwtd2hpc3BlciAoc2VlIGhlcmUgZm9yCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vcmUgaW5mb3JtYXRpb246IGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9kaXN0aWwtd2hpc3BlcikuCiAgICAgICAgOnBhcmFtIG1heF9uZXdfdG9rZW5zOiAgICAgICAgICAgIFRoZSBtYXhpbXVtIG51bWJlciBvZiBuZXcgdG9rZW5zIHRvIGdlbmVyYXRlLiBUaGlzIGlzIHVzZWQgdG8gbGltaXQgdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyYXRpb24gbGVuZ3RoLiBEZWZhdWx0IGlzIDEyOCB0b2tlbnMuCiAgICAgICAgOnBhcmFtIGNodW5rX2xlbmd0aF9zOiAgICAgICAgICAgIFRoZSBhdWRpbyBjaHVuayB0byBzcGxpdCB0aGUgYXVkaW8gdG8gKGluIHNlY29uZHMpLiBEZWZhdWx0IGlzIDMwIHNlY29uZHMuCiAgICAgICAgOnBhcmFtIGJhdGNoX3NpemU6ICAgICAgICAgICAgICAgIFRoZSBiYXRjaCBzaXplIHRvIHVzZSBmb3IgaW5mZXJlbmNlLiBEZWZhdWx0IGlzIDIuCiAgICAgICAgOnBhcmFtIHNwb2tlbl9sYW5ndWFnZTogICAgICAgICAgIEFpbSB3aGlzcGVyIHRvIGtub3cgd2hhdCBsYW5ndWFnZSBpcyBzcG9rZW4uIElmIE5vbmUsIGl0IHdpbGwgdHJ5IHRvIGRldGVjdCBpdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgZWFjaCBjaHVuay4KICAgICAgICA6cGFyYW0gdHJhbnNsYXRlX3RvX2VuZ2xpc2g6ICAgICAgV2hldGhlciB0byB0cmFuc2xhdGUgdGhlIHRyYW5zY3JpcHRpb25zIHRvIEVuZ2xpc2guIERlZmF1bHQgaXMgRmFsc2UuCiAgICAgICAgOnBhcmFtIHJldHVybl90aW1lc3RhbXBzOiAgICAgICAgIFdoZXRoZXIgdG8gcmV0dXJuIHRoZSB0aW1lc3RhbXBzIG9mIHRoZSB3b3Jkcy4gSWYgIndvcmQiLCB3aWxsIHJldHVybiB0aGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wcyBvZiBlYWNoIHdvcmQuIElmIFRydWUgd2lsbCByZXR1cm4gdGhlIHRpbWVzdGFtcHMgb2YgZWFjaCBjaHVuay4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCBpcyBGYWxzZS4gQWltZWQgdG8gYmUgdXNlZCBmb3Igc3BlZWNoIGRpYXJpemF0aW9uLgogICAgICAgIDpwYXJhbSBwZXJfY2hhbm5lbF90cmFuc2NyaXB0aW9uOiBXaGV0aGVyIHRvIGRvIHBlciBjaGFubmVsIHRyYW5zY3JpcHRpb24uIElmIG5lZWRlZCB0byBydW4gcGVyIGNoYW5uZWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNjcmlwdGlvbiwgcGFzcyB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzIGV4cGVjdGVkIGZvciBlYWNoIGF1ZGlvIGZpbGUgaGVyZS4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCBtZWFucyByZWd1bGFyIHRyYW5zY3JpcHRpb24gKG1lcmdlIGNoYW5uZWxzKS4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vdGU6IElmIGBwZXJfY2hhbm5lbF90cmFuc2NyaXB0aW9uYCBpcyBub3QgMCwgYGJhdGNoX3NpemVgIG11c3QgYmUgdHJlYXRlZCB0bwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZSB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzIGFuZCBub3QgYXVkaW8gZmlsZXMuIEFpbWVkIHRvIGJlIHVzZWQgZm9yIHBlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsIHNwZWVjaCBkaWFyaXphdGlvbi4KICAgICAgICAiIiIKICAgICAgICAjIFN0b3JlIGxvYWRpbmcgcGFyYW1ldGVyczoKICAgICAgICBzZWxmLl9tb2RlbF9uYW1lID0gbW9kZWxfbmFtZQogICAgICAgIHNlbGYuX2RldmljZSA9IGRldmljZQogICAgICAgIHNlbGYuX3VzZV9mbGFzaF9hdHRlbnRpb25fMiA9IHVzZV9mbGFzaF9hdHRlbnRpb25fMgogICAgICAgIHNlbGYuX3VzZV9iZXR0ZXJfdHJhbnNmb3JtZXJzID0gdXNlX2JldHRlcl90cmFuc2Zvcm1lcnMKICAgICAgICBzZWxmLl9tYXhfbmV3X3Rva2VucyA9IG1heF9uZXdfdG9rZW5zCiAgICAgICAgc2VsZi5fY2h1bmtfbGVuZ3RoX3MgPSBjaHVua19sZW5ndGhfcwogICAgICAgIHNlbGYuX2JhdGNoX3NpemUgPSBiYXRjaF9zaXplCiAgICAgICAgc2VsZi5fcmV0dXJuX3RpbWVzdGFtcHMgPSByZXR1cm5fdGltZXN0YW1wcwogICAgICAgIHNlbGYuX3Blcl9jaGFubmVsX3RyYW5zY3JpcHRpb24gPSBwZXJfY2hhbm5lbF90cmFuc2NyaXB0aW9uCgogICAgICAgICMgU3RvcmUgZ2VuZXJhdGlvbiBwYXJhbWV0ZXJzOgogICAgICAgIHNlbGYuX2Fzc2lzdGFudF9tb2RlbCA9IGFzc2lzdGFudF9tb2RlbAogICAgICAgIHNlbGYuX3Nwb2tlbl9sYW5ndWFnZSA9IHNwb2tlbl9sYW5ndWFnZQogICAgICAgIHNlbGYuX3RyYW5zbGF0ZV90b19lbmdsaXNoID0gdHJhbnNsYXRlX3RvX2VuZ2xpc2gKCiAgICAgICAgIyBQcmVwYXJlIHRoZSB0cmFuc2NyaXB0aW9uIG9iamVjdHM6CiAgICAgICAgc2VsZi5fdHJhbnNjcmlwdGlvbl9waXBlbGluZTogQXV0b21hdGljU3BlZWNoUmVjb2duaXRpb25QaXBlbGluZSA9IE5vbmUKICAgICAgICBzZWxmLl9nZW5lcmF0ZV9rd2FyZ3M6IGRpY3QgPSBOb25lCgogICAgZGVmIGxvYWQoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgTG9hZCB0aGUgdHJhbnNjcmliZXIuIE11c3QgYmUgY2FsbGVkIGJlZm9yZSB0cmFuc2NyaWJpbmcuCiAgICAgICAgIiIiCiAgICAgICAgIyBTZXQgdGhlIGRldmljZSBhbmQgZGF0YSB0eXBlIHRvIHVzZSAocHJlZmVyIEdQVSBpZiBhdmFpbGFibGUpOgogICAgICAgIGRldmljZSA9IHRvcmNoLmRldmljZSgKICAgICAgICAgICAgc2VsZi5fZGV2aWNlIG9yICJjdWRhIiBpZiB0b3JjaC5jdWRhLmlzX2F2YWlsYWJsZSgpIGVsc2UgImNwdSIKICAgICAgICApCiAgICAgICAgdG9yY2hfZHR5cGUgPSB0b3JjaC5mbG9hdDE2IGlmIGRldmljZS50eXBlID09ICJjdWRhIiBlbHNlIHRvcmNoLmZsb2F0MzIKCiAgICAgICAgIyBDaG9vc2UgdGhlIG9wdGltaXphdGlvbiB0byB1c2UgKGluIGNhc2UgdGhlIHVzZXIgZGlkIG5vdCBzcGVjaWZ5IGFueSk6CiAgICAgICAgaWYgKAogICAgICAgICAgICBzZWxmLl91c2VfZmxhc2hfYXR0ZW50aW9uXzIgaXMgTm9uZQogICAgICAgICAgICBhbmQgc2VsZi5fdXNlX2JldHRlcl90cmFuc2Zvcm1lcnMgaXMgTm9uZQogICAgICAgICk6CiAgICAgICAgICAgICMgUHJlZmVyIHRvIHVzZSBmbGFzaCBhdHRlbnRpb24gMiBpZiBhdmFpbGFibGUgYW5kIGN1ZGEgZGV2aWNlIGlzIHN1cHBvcnRlZCAoc2VlIEdQVSBuYW1lcyB0byBhcmNoaXRlY3R1cmUKICAgICAgICAgICAgIyBoZXJlOiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX052aWRpYV9ncmFwaGljc19wcm9jZXNzaW5nX3VuaXRzI1Rlc2xhKToKICAgICAgICAgICAgaWYgZGV2aWNlLnR5cGUgPT0gImN1ZGEiIGFuZCBpc19mbGFzaF9hdHRuXzJfYXZhaWxhYmxlKCk6CiAgICAgICAgICAgICAgICBjdWRhX2RldmljZV9uYW1lID0gdG9yY2guY3VkYS5nZXRfZGV2aWNlX3Byb3BlcnRpZXMoZGV2aWNlKS5uYW1lCiAgICAgICAgICAgICAgICBpZiBhbnkoCiAgICAgICAgICAgICAgICAgICAgY3VkYV9kZXZpY2VfbmFtZS5zdGFydHN3aXRoKGdwdV9uYW1lKQogICAgICAgICAgICAgICAgICAgIGZvciBncHVfbmFtZSBpbiBbCiAgICAgICAgICAgICAgICAgICAgICAgICJOVklESUEgQSIsICAjIEZvciBBbXBlcmUgYXJjaGl0ZWN0dXJlIChlLmcuIEExMCwgQTMwLCBBMTAwKQogICAgICAgICAgICAgICAgICAgICAgICAiTlZJRElBIEgiLCAgIyBGb3IgSG9wcGVyIGFyY2hpdGVjdHVyZSAoZS5nLiBIMTAwKQogICAgICAgICAgICAgICAgICAgICAgICAiTlZJRElBIEwiLCAgIyBGb3IgQWRhIExvdmVsYWNlIGFyY2hpdGVjdHVyZSAoZS5nLiBMNCwgTDQwKQogICAgICAgICAgICAgICAgICAgICAgICAiTlZJRElBIFJUWCAzMCIsICAjIEZvciBBZGEgTG92ZWxhY2UgYXJjaGl0ZWN0dXJlIChSVFggMzAgc2VyaWVzKQogICAgICAgICAgICAgICAgICAgICAgICAiTlZJRElBIFJUWCA0MCIsICAjIEZvciBBZGEgTG92ZWxhY2UgYXJjaGl0ZWN0dXJlIChSVFggNDAgc2VyaWVzKQogICAgICAgICAgICAgICAgICAgICAgICAiTlZJRElBIFJUWCA1MCIsICAjIEZvciBBZGEgTG92ZWxhY2UgYXJjaGl0ZWN0dXJlIChSVFggNTAgc2VyaWVzKQogICAgICAgICAgICAgICAgICAgICAgICAjIFdpbGwgYmUgc3VwcG9ydGVkIHNvb24gYWNjb3JkaW5nIHRvIEZsYXNoQXR0ZW50aW9uIEdpdEh1YiByZXBvOgogICAgICAgICAgICAgICAgICAgICAgICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9EYW8tQUlMYWIvZmxhc2gtYXR0ZW50aW9uP3RhYj1yZWFkbWUtb3YtZmlsZSNpbnN0YWxsYXRpb24tYW5kLWZlYXR1cmVzCiAgICAgICAgICAgICAgICAgICAgICAgICMgIk5WSURJQSBUNCIsICAjIEZvciBUdXJpbmcgYXJjaGl0ZWN0dXJlIChvbmx5IFQ0KQogICAgICAgICAgICAgICAgICAgICAgICAjICJOVklESUEgUlRYIDIwIiwgICMgRm9yIFR1cmluZyBhcmNoaXRlY3R1cmUgKFJUWCAyMCBzZXJpZXMpCiAgICAgICAgICAgICAgICAgICAgXQogICAgICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgICAgICBzZWxmLl91c2VfZmxhc2hfYXR0ZW50aW9uXzIgPSBUcnVlCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIHNlbGYuX3VzZV9iZXR0ZXJfdHJhbnNmb3JtZXJzID0gVHJ1ZQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgc2VsZi5fdXNlX2JldHRlcl90cmFuc2Zvcm1lcnMgPSBUcnVlCgogICAgICAgICMgQnVpbGQgdGhlIG9wdGltaXphdGlvbnMga3dhcmdzOgogICAgICAgIG1vZGVsX2t3YXJncyA9IHsKICAgICAgICAgICAgImxvd19jcHVfbWVtX3VzYWdlIjogVHJ1ZSwKICAgICAgICAgICAgInVzZV9zYWZldGVuc29ycyI6IFRydWUsCiAgICAgICAgfQogICAgICAgIGlmIHNlbGYuX3VzZV9mbGFzaF9hdHRlbnRpb25fMjoKICAgICAgICAgICAgaWYgX0xPR0dFUjoKICAgICAgICAgICAgICAgIF9MT0dHRVIuaW5mbygKICAgICAgICAgICAgICAgICAgICAiVXNpbmcgRmxhc2hBdHRlbnRpb24yIG9wdGltaXphdGlvbiAtIG1ha2Ugc3VyZSB0aGUgYGZsYXNoLWF0dG5gIHBhY2thZ2UgaXMgaW5zdGFsbGVkIHZpYSAiCiAgICAgICAgICAgICAgICAgICAgImBwaXAgaW5zdGFsbCAtVSBmbGFzaC1hdHRuIC0tbm8tYnVpbGQtaXNvbGF0aW9uYCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgbW9kZWxfa3dhcmdzWyJhdHRuX2ltcGxlbWVudGF0aW9uIl0gPSAiZmxhc2hfYXR0ZW50aW9uXzIiCiAgICAgICAgZWxpZiBzZWxmLl91c2VfYmV0dGVyX3RyYW5zZm9ybWVyczoKICAgICAgICAgICAgaWYgX0xPR0dFUjoKICAgICAgICAgICAgICAgIF9MT0dHRVIuaW5mbygKICAgICAgICAgICAgICAgICAgICAiVXNpbmcgQmV0dGVyVHJhbnNmb3JtZXJzIG9wdGltaXphdGlvbiAtIG1ha2Ugc3VyZSB0aGUgYG9wdGltdW1gIHBhY2thZ2UgaXMgaW5zdGFsbGVkIHZpYSAiCiAgICAgICAgICAgICAgICAgICAgImBwaXAgaW5zdGFsbCAtVSBvcHRpbXVtYCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgbW9kZWxfa3dhcmdzWyJhdHRuX2ltcGxlbWVudGF0aW9uIl0gPSAic2RwYSIKCiAgICAgICAgIyBJbml0aWFsaXplIHRoZSBzcGVlY2ggcmVjb2duaXRpb24gcGlwZWxpbmU6CiAgICAgICAgc2VsZi5fdHJhbnNjcmlwdGlvbl9waXBlbGluZSA9IHBpcGVsaW5lKAogICAgICAgICAgICB0YXNrPSJhdXRvbWF0aWMtc3BlZWNoLXJlY29nbml0aW9uIiwKICAgICAgICAgICAgbW9kZWw9c2VsZi5fbW9kZWxfbmFtZSwKICAgICAgICAgICAgbW9kZWxfa3dhcmdzPW1vZGVsX2t3YXJncy5jb3B5KCksCiAgICAgICAgICAgIGJhdGNoX3NpemU9c2VsZi5fYmF0Y2hfc2l6ZSwKICAgICAgICAgICAgbWF4X25ld190b2tlbnM9c2VsZi5fbWF4X25ld190b2tlbnMsCiAgICAgICAgICAgIGNodW5rX2xlbmd0aF9zPXNlbGYuX2NodW5rX2xlbmd0aF9zLAogICAgICAgICAgICByZXR1cm5fdGltZXN0YW1wcz1zZWxmLl9yZXR1cm5fdGltZXN0YW1wcywKICAgICAgICAgICAgdG9yY2hfZHR5cGU9dG9yY2hfZHR5cGUsCiAgICAgICAgICAgIGRldmljZT1kZXZpY2UsCiAgICAgICAgKQoKICAgICAgICAjIFByZXBhcmUgdGhlIGdlbmVyYXRpb24ga3dhcmdzOgogICAgICAgIHNlbGYuX2dlbmVyYXRlX2t3YXJncyA9IHsKICAgICAgICAgICAgImxhbmd1YWdlIjogc2VsZi5fc3Bva2VuX2xhbmd1YWdlLAogICAgICAgICAgICAidGFzayI6ICJ0cmFuc2xhdGUiIGlmIHNlbGYuX3RyYW5zbGF0ZV90b19lbmdsaXNoIGVsc2UgInRyYW5zY3JpYmUiLAogICAgICAgIH0KCiAgICAgICAgIyBJbml0aWFsaXplIHRoZSBhc3Npc3RhbnQgbW9kZWwgKGlmIG5lZWRlZCk6CiAgICAgICAgaWYgc2VsZi5fYXNzaXN0YW50X21vZGVsOgogICAgICAgICAgICBhc3Npc3RhbnRfbW9kZWwgPSBBdXRvTW9kZWxGb3JDYXVzYWxMTS5mcm9tX3ByZXRyYWluZWQoCiAgICAgICAgICAgICAgICBzZWxmLl9hc3Npc3RhbnRfbW9kZWwsIHRvcmNoX2R0eXBlPXRvcmNoX2R0eXBlLCAqKm1vZGVsX2t3YXJncwogICAgICAgICAgICApCiAgICAgICAgICAgIGFzc2lzdGFudF9tb2RlbC50byhkZXZpY2UpCiAgICAgICAgICAgIHNlbGYuX2dlbmVyYXRlX2t3YXJnc1siYXNzaXN0YW50X21vZGVsIl0gPSBhc3Npc3RhbnRfbW9kZWwKCiAgICBkZWYgdHJhbnNjcmliZSgKICAgICAgICBzZWxmLAogICAgICAgIGF1ZGlvX2ZpbGVzOiBMaXN0W1BhdGhdLAogICAgICAgIGJhdGNoX3Byb2Nlc3NvcjogQmF0Y2hQcm9jZXNzb3IgPSBOb25lLAogICAgICAgIGJhdGNoZXNfcXVldWU6IFF1ZXVlID0gTm9uZSwKICAgICAgICB2ZXJib3NlOiBib29sID0gRmFsc2UsCiAgICApIC0+IFVuaW9uW0xpc3RbTGlzdFtkaWN0XV0sIE5vbmVdOgogICAgICAgICIiIgogICAgICAgIFRyYW5zY3JpYmUgdGhlIGdpdmVuIGF1ZGlvIGZpbGVzLiBUaGUgdHJhbnNjcmlwdGlvbnMgd2lsbCBiZSBzZW50IHRvIGEgcXVldWUgb3IgYSBiYXRjaCBwcm9jZXNzb3IgZm9yIGZ1cnRoZXIKICAgICAgICBwcm9jZXNzaW5nIGxpa2Ugd3JpdGluZyB0byB0ZXh0IGZpbGVzLiBJZiBubyBxdWV1ZSBvciBiYXRjaCBwcm9jZXNzb3IgaXMgZ2l2ZW4sIHRoZSB0cmFuc2NyaXB0aW9ucyBvdXRwdXRzIGZyb20KICAgICAgICB0aGUgcGlwZWxpbmUgd2lsbCBiZSByZXR1cm5lZC4gT3RoZXJ3aXNlLCBgTm9uZWAgaXMgcmV0dXJuZWQuCgogICAgICAgIDpwYXJhbSBhdWRpb19maWxlczogICAgIFRoZSBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlLgogICAgICAgIDpwYXJhbSBiYXRjaF9wcm9jZXNzb3I6IEEgYmF0Y2ggcHJvY2Vzc29yLgogICAgICAgIDpwYXJhbSBiYXRjaGVzX3F1ZXVlOiAgIEEgbXVsdGlwcm9jZXNzaW5nIHF1ZXVlIHRvIHB1dCB0aGUgYmF0Y2hlcyBpbi4KICAgICAgICA6cGFyYW0gdmVyYm9zZTogICAgICAgICBXaGV0aGVyIHRvIHNob3cgYSBwcm9ncmVzcyBiYXIuIERlZmF1bHQgaXMgRmFsc2UuCgogICAgICAgIDpyZXR1cm5zOiBUaGUgdHJhbnNjcmlwdGlvbnMgb3V0cHV0cyBmcm9tIHRoZSBwaXBlbGluZSBpZiBubyBxdWV1ZSBvciBiYXRjaCBwcm9jZXNzb3IgaXMgZ2l2ZW4sIG90aGVyd2lzZSwKICAgICAgICAgICAgICAgICAgYE5vbmVgLgogICAgICAgICIiIgogICAgICAgICMgV3JhcCB0aGUgYXVkaW8gZmlsZXMgd2l0aCBhIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciB0aGVtIHZpYSBhIGdlbmVyYXRvciAoc2F2ZSBtZW1vcnkgYW5kIHJ1bnRpbWUgd2l0aAogICAgICAgICMgSHVnZ2luZ2ZhY2UncyBwaXBlbGluZXMgYXMgdGhleSBwcmVsb2FkIGVhY2ggaW5wdXQgd2hpbGUgaW5mZXJlbmNlIGlzIHJ1bm5pbmcpOgogICAgICAgIGRlZiBhdWRpb19pdGVyYXRvcigpIC0+IEdlbmVyYXRvcltVbmlvbltkaWN0LCBzdHJdLCBOb25lLCBOb25lXToKICAgICAgICAgICAgaWYgc2VsZi5fcGVyX2NoYW5uZWxfdHJhbnNjcmlwdGlvbjoKICAgICAgICAgICAgICAgIGZvciBhdWRpb19maWxlIGluIGF1ZGlvX2ZpbGVzOgogICAgICAgICAgICAgICAgICAgIGF1ZGlvLCBzYW1wbGluZ19yYXRlID0gdG9yY2hhdWRpby5sb2FkKHN0cihhdWRpb19maWxlKSkKICAgICAgICAgICAgICAgICAgICBhdWRpbyA9IGF1ZGlvLm51bXB5KCkKICAgICAgICAgICAgICAgICAgICBmb3IgY2hhbm5lbCBpbiBhdWRpbzoKICAgICAgICAgICAgICAgICAgICAgICAgeWllbGQgeyJyYXciOiBjaGFubmVsLCAic2FtcGxpbmdfcmF0ZSI6IHNhbXBsaW5nX3JhdGV9CiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBmb3IgYXVkaW9fZmlsZSBpbiBhdWRpb19maWxlczoKICAgICAgICAgICAgICAgICAgICB5aWVsZCBzdHIoYXVkaW9fZmlsZSkKCiAgICAgICAgIyBDcmVhdGUgYSBiYXRjaCBpdGVyYXRvcjoKICAgICAgICBkZWYgYmF0Y2hfaXRlcmF0b3IoKSAtPiBHZW5lcmF0b3JbTGlzdFtVbmlvbltkaWN0LCBzdHJdXSwgTm9uZSwgTm9uZV06CiAgICAgICAgICAgIGJhdGNoID0gW10KICAgICAgICAgICAgZm9yIGF1ZGlvIGluIGF1ZGlvX2l0ZXJhdG9yKCk6CiAgICAgICAgICAgICAgICBiYXRjaC5hcHBlbmQoYXVkaW8pCiAgICAgICAgICAgICAgICBpZiBsZW4oYmF0Y2gpID09IHNlbGYuX2JhdGNoX3NpemU6CiAgICAgICAgICAgICAgICAgICAgeWllbGQgYmF0Y2gKICAgICAgICAgICAgICAgICAgICBiYXRjaCA9IFtdCiAgICAgICAgICAgIGlmIGJhdGNoOgogICAgICAgICAgICAgICAgeWllbGQgYmF0Y2gKCiAgICAgICAgIyBQcmVwYXJlIHRoZSBzdWNjZXNzZXMgZGF0YWZyYW1lIGFuZCBlcnJvcnMgZGljdGlvbmFyeSB0byBiZSByZXR1cm5lZDoKICAgICAgICBvdXRwdXRzID0gW10KCiAgICAgICAgIyBJbmZlciB0aHJvdWdoIHRoZSBwaXBlbGluZToKICAgICAgICBmb3IgaW5wdXRfYmF0Y2ggaW4gdHFkbSgKICAgICAgICAgICAgYmF0Y2hfaXRlcmF0b3IoKSBpZiBzZWxmLl9iYXRjaF9zaXplID4gMSBlbHNlIGF1ZGlvX2l0ZXJhdG9yKCksCiAgICAgICAgICAgIGRlc2M9IlRyYW5zY3JpYmluZyIsCiAgICAgICAgICAgIHVuaXQ9ImNoYW5uZWwiIGlmIHNlbGYuX3Blcl9jaGFubmVsX3RyYW5zY3JpcHRpb24gZWxzZSAiYXVkaW8gZmlsZSIsCiAgICAgICAgICAgIHRvdGFsPSgKICAgICAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICAgICAobGVuKGF1ZGlvX2ZpbGVzKSAvLyBzZWxmLl9iYXRjaF9zaXplKQogICAgICAgICAgICAgICAgICAgICsgKGxlbihhdWRpb19maWxlcykgJSBzZWxmLl9iYXRjaF9zaXplICE9IDApCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAqIChzZWxmLl9wZXJfY2hhbm5lbF90cmFuc2NyaXB0aW9uIG9yIDEpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIGRpc2FibGU9bm90IHZlcmJvc2UsCiAgICAgICAgKToKICAgICAgICAgICAgIyBJbmZlcjoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgb3V0cHV0X2JhdGNoID0gc2VsZi5fdHJhbnNjcmlwdGlvbl9waXBlbGluZSgKICAgICAgICAgICAgICAgICAgICBpbnB1dF9iYXRjaCwKICAgICAgICAgICAgICAgICAgICBnZW5lcmF0ZV9rd2FyZ3M9c2VsZi5fZ2VuZXJhdGVfa3dhcmdzLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgICMgQ29sbGVjdCB0aGUgZXhjZXB0aW9uOgogICAgICAgICAgICAgICAgb3V0cHV0X2JhdGNoID0gc3RyKGV4Y2VwdGlvbikKICAgICAgICAgICAgICAgICMgQWxpZ24gdG8gYmF0Y2ggc2l6ZToKICAgICAgICAgICAgICAgIG91dHB1dF9iYXRjaCA9ICgKICAgICAgICAgICAgICAgICAgICBbb3V0cHV0X2JhdGNoXSAqIGxlbihpbnB1dF9iYXRjaCkKICAgICAgICAgICAgICAgICAgICBpZiBpc2luc3RhbmNlKGlucHV0X2JhdGNoLCBsaXN0KQogICAgICAgICAgICAgICAgICAgIGVsc2UgW291dHB1dF9iYXRjaF0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBUbyBhbGlnbiB3aXRoIGJhdGNoaW5nLCBpZiBiYXRjaCBzaXplIGlzIDEsIHdyYXAgdGhlIG91dHB1dCB3aXRoIGEgbGlzdDoKICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShvdXRwdXRfYmF0Y2gsIGRpY3QpOgogICAgICAgICAgICAgICAgb3V0cHV0X2JhdGNoID0gW291dHB1dF9iYXRjaF0KICAgICAgICAgICAgIyBJZiBhIGJhdGNoIHByb2Nlc3NvciBpcyBnaXZlbiwgcHJvY2VzcyB0aGUgYmF0Y2g6CiAgICAgICAgICAgIGlmIGJhdGNoX3Byb2Nlc3NvcjoKICAgICAgICAgICAgICAgICMgUHJvY2VzcyBpdCBkaXJlY3RseToKICAgICAgICAgICAgICAgIGJhdGNoX3Byb2Nlc3Nvci5wcm9jZXNzX2JhdGNoKGJhdGNoPW91dHB1dF9iYXRjaCkKICAgICAgICAgICAgICAgIGJhdGNoX3Byb2Nlc3Nvci5kb190YXNrcygpCiAgICAgICAgICAgIGVsaWYgYmF0Y2hlc19xdWV1ZToKICAgICAgICAgICAgICAgICMgT3RoZXJ3aXNlLCBxdWV1ZSB0aGUgYmF0Y2g6CiAgICAgICAgICAgICAgICBiYXRjaGVzX3F1ZXVlLnB1dChvdXRwdXRfYmF0Y2gpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAjIE90aGVyd2lzZSwgY29sbGVjdCB0aGUgb3V0cHV0IGFzIGlzIHdpdGhvdXQgcHJvY2Vzc2luZzoKICAgICAgICAgICAgICAgIG91dHB1dHMuYXBwZW5kKG91dHB1dF9iYXRjaCkKCiAgICAgICAgIyBDaGVjayBpZiBnaXZlbiBhIG11bHRpcHJvY2Vzc2luZyBxdWV1ZSBvciBhIGJhdGNoIHByb2Nlc3NvcjoKICAgICAgICBpZiBiYXRjaGVzX3F1ZXVlOgogICAgICAgICAgICBiYXRjaGVzX3F1ZXVlLnB1dChfTVVMVElQUk9DRVNTSU5HX1NUT1BfTUFSSykKCiAgICAgICAgcmV0dXJuIG91dHB1dHMgaWYgbm90IGJhdGNoX3Byb2Nlc3NvciBlbHNlIE5vbmUKCgojOiBUaGUgdmFsdWUgdG8gc2VuZCBpbnRvIG11bHRpcHJvY2Vzc2luZyBxdWV1ZXMgdG8gc3RvcCB0aGUgcHJvY2VzczoKX01VTFRJUFJPQ0VTU0lOR19TVE9QX01BUksgPSAiU1RPUCIKCgpkZWYgX211bHRpcHJvY2Vzc2luZ19wcm9jZXNzX2JhdGNoZXMoCiAgICBiYXRjaF9wcm9jZXNzb3I6IEJhdGNoUHJvY2Vzc29yLAogICAgYmF0Y2hlc19xdWV1ZTogUXVldWUsCiAgICB0YXNrc19xdWV1ZTogUXVldWUsCiAgICBuX3Rhc2tfY29tcGxldGVyczogaW50LAopOgogICAgIiIiCiAgICBQcm9jZXNzIHRoZSBiYXRjaGVzIGluIHRoZSBnaXZlbiBiYXRjaGVzIHF1ZXVlIGFuZCBwdXQgdGhlIHRhc2tzIGluIHRoZSBnaXZlbiB0YXNrcyBxdWV1ZS4gVGhlIGZ1bmN0aW9uIHdpbGwgc3RvcAogICAgd2hlbiB0aGUgZ2l2ZW4gYmF0Y2hlcyBxdWV1ZSB3aWxsIHJlY2VpdmUgdGhlIHN0b3AgbWFyay4gSXQgaXMgYWltZWQgdG8gYmUgdXNlZCB3aXRoIG11bHRpcHJvY2Vzc2luZyBhcyBhIHByb2Nlc3MuCgogICAgOnBhcmFtIGJhdGNoX3Byb2Nlc3NvcjogICBBIGJhdGNoIHByb2Nlc3NvciB0byBwcm9jZXNzIHRoZSBiYXRjaGVzLgogICAgOnBhcmFtIGJhdGNoZXNfcXVldWU6ICAgICBBIHF1ZXVlIHRvIGdldCB0aGUgYmF0Y2hlcyBmcm9tLgogICAgOnBhcmFtIHRhc2tzX3F1ZXVlOiAgICAgICBBIHF1ZXVlIHRvIHB1dCB0aGUgdGFza3MgaW4uCiAgICA6cGFyYW0gbl90YXNrX2NvbXBsZXRlcnM6IFRoZSBudW1iZXIgb2YgdGFzayBjb21wbGV0ZXJzIChwcm9jZXNzZXMgdGhhdCBydW4gdGhlIGBfbXVsdGlwcm9jZXNzaW5nX2NvbXBsZXRlX3Rhc2tzYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbikuIEEgc3RvcCBtYXJrIHdpbGwgYmUgc2VudCB0byB0aGUgdGFza3MgcXVldWUgZm9yIGVhY2ggdGFzayBjb21wbGV0ZXIuCiAgICAiIiIKICAgIHdoaWxlIFRydWU6CiAgICAgICAgIyBHZXQgdGhlIGJhdGNoOgogICAgICAgIGJhdGNoOiBMaXN0W2RpY3RdID0gYmF0Y2hlc19xdWV1ZS5nZXQoKQogICAgICAgIGlmIGJhdGNoID09IF9NVUxUSVBST0NFU1NJTkdfU1RPUF9NQVJLOgogICAgICAgICAgICBicmVhawoKICAgICAgICAjIFByb2Nlc3MgdGhlIGJhdGNoOgogICAgICAgIGJhdGNoX3Byb2Nlc3Nvci5wcm9jZXNzX2JhdGNoKGJhdGNoPWJhdGNoKQoKICAgICAgICAjIEdldCB0aGUgdGFza3M6CiAgICAgICAgdGFza3MgPSBiYXRjaF9wcm9jZXNzb3IuZ2V0X3Rhc2tzKCkKCiAgICAgICAgIyBRdWV1ZSB0aGUgdGFza3M6CiAgICAgICAgZm9yIHRhc2sgaW4gdGFza3M6CiAgICAgICAgICAgIHRhc2tzX3F1ZXVlLnB1dCh0YXNrLnRvX3R1cGxlKCkpCgogICAgIyBNYXJrIHRoZSBlbmQgb2YgdGhlIGJhdGNoZXM6CiAgICBmb3IgXyBpbiByYW5nZShuX3Rhc2tfY29tcGxldGVycyk6CiAgICAgICAgdGFza3NfcXVldWUucHV0KF9NVUxUSVBST0NFU1NJTkdfU1RPUF9NQVJLKQoKCmRlZiBfbXVsdGlwcm9jZXNzaW5nX2NvbXBsZXRlX3Rhc2tzKHRhc2tzX3F1ZXVlOiBRdWV1ZSwgcmVzdWx0c19xdWV1ZTogUXVldWUpOgogICAgIiIiCiAgICBDb21wbGV0ZSB0aGUgdGFza3MgaW4gdGhlIGdpdmVuIHF1ZXVlIGFuZCBwdXQgdGhlIHJlc3VsdHMgaW4gdGhlIGdpdmVuIHJlc3VsdHMgcXVldWUuIFRoZSBmdW5jdGlvbiB3aWxsIHN0b3Agd2hlbgogICAgdGhlIGdpdmVuIHRhc2tzIHF1ZXVlIHdpbGwgcmVjZWl2ZSB0aGUgc3RvcCBtYXJrLiBJdCBpcyBhaW1lZCB0byBiZSB1c2VkIHdpdGggbXVsdGlwcm9jZXNzaW5nIGFzIGEgcHJvY2Vzcy4KCiAgICA6cGFyYW0gdGFza3NfcXVldWU6ICAgQSBxdWV1ZSB0byBnZXQgdGhlIHRhc2tzIGZyb20uCiAgICA6cGFyYW0gcmVzdWx0c19xdWV1ZTogQSBxdWV1ZSB0byBwdXQgdGhlIHJlc3VsdHMgaW4uCiAgICAiIiIKICAgIHRhc2tzX21hcCA9IHsKICAgICAgICBCYXNlVGFzay5fX25hbWVfXzogQmFzZVRhc2ssCiAgICAgICAgU3BlZWNoRGlhcml6YXRpb25UYXNrLl9fbmFtZV9fOiBTcGVlY2hEaWFyaXphdGlvblRhc2ssCiAgICAgICAgU3BlZWNoRGlhcml6YXRpb25QZXJDaGFubmVsVGFzay5fX25hbWVfXzogU3BlZWNoRGlhcml6YXRpb25QZXJDaGFubmVsVGFzaywKICAgIH0KCiAgICB3aGlsZSBUcnVlOgogICAgICAgICMgR2V0IHRoZSB0YXNrOgogICAgICAgIHRhc2sgPSB0YXNrc19xdWV1ZS5nZXQoKQogICAgICAgIGlmIHRhc2sgPT0gX01VTFRJUFJPQ0VTU0lOR19TVE9QX01BUks6CiAgICAgICAgICAgIGJyZWFrCgogICAgICAgICMgUmVjb25zdHJ1Y3QgdGhlIHRhc2s6CiAgICAgICAgdGFza19jbGFzcywgdGFza19rd2FyZ3MgPSB0YXNrCiAgICAgICAgdGFzayA9IHRhc2tzX21hcFt0YXNrX2NsYXNzXSgqKnRhc2tfa3dhcmdzKQoKICAgICAgICAjIENvbXBsZXRlIHRoZSB0YXNrOgogICAgICAgIHRhc2suZG9fdGFzaygpCiAgICAgICAgcmVzdWx0c19xdWV1ZS5wdXQoKHRhc2suaXNfZmFpbGVkKCksIHRhc2suZ2V0X3Jlc3VsdCgpKSkKCiAgICAjIE1hcmsgdGhlIGVuZCBvZiB0aGUgdGFza3M6CiAgICByZXN1bHRzX3F1ZXVlLnB1dChfTVVMVElQUk9DRVNTSU5HX1NUT1BfTUFSSykKCgojIEdldCB0aGUgZ2xvYmFsIGxvZ2dlcjoKX0xPR0dFUiA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKCkKCgpkZWYgb3Blbl9tcGlfaGFuZGxlcigKICAgIHdvcmtlcl9pbnB1dHM6IExpc3Rbc3RyXSwgcm9vdF93b3JrZXJfaW5wdXRzOiBEaWN0W3N0ciwgQW55XSA9IE5vbmUKKToKICAgIGdsb2JhbCBfTE9HR0VSCgogICAgIyBDaGVjayBmb3IgTUxSdW4gYW5kIE9wZW5NUEkgYXZhaWxhYmlsaXR5OgogICAgY29udGV4dCwgY29tbSA9IF9jaGVja19tbHJ1bl9hbmRfb3Blbl9tcGkoKQoKICAgICMgQ2hlY2sgaWYgTUxSdW4gaXMgYXZhaWxhYmxlLCBzZXQgdGhlIGdsb2JhbCBsb2dnZXIgdG8gTUxSdW4nczoKICAgIGlmIGNvbnRleHQ6CiAgICAgICAgX0xPR0dFUiA9IGNvbnRleHQubG9nZ2VyCgogICAgZGVmIGRlY29yYXRvcihoYW5kbGVyKToKICAgICAgICBpZiBjb21tIGlzIE5vbmUgb3IgY29tbS5HZXRfc2l6ZSgpID09IDE6CiAgICAgICAgICAgIHJldHVybiBoYW5kbGVyCgogICAgICAgIEB3cmFwcyhoYW5kbGVyKQogICAgICAgIGRlZiB3cmFwcGVyKCoqa3dhcmdzKToKICAgICAgICAgICAgIyBHZXQgdGhlIG9wZW4gbXBpIGVudmlyb25tZW50IHByb3BlcnRpZXM6CiAgICAgICAgICAgIHNpemUgPSBjb21tLkdldF9zaXplKCkKICAgICAgICAgICAgcmFuayA9IGNvbW0uR2V0X3JhbmsoKQoKICAgICAgICAgICAgIyBHaXZlIHRoZSBjb3JyZWN0IGNodW5rIG9mIHRoZSB3b3JrZXJzIGlucHV0czoKICAgICAgICAgICAgZm9yIHdvcmtlcl9pbnB1dCBpbiB3b3JrZXJfaW5wdXRzOgogICAgICAgICAgICAgICAgaW5wdXRfYXJndW1lbnQgPSBrd2FyZ3Nbd29ya2VyX2lucHV0XQogICAgICAgICAgICAgICAgaWYgaW5wdXRfYXJndW1lbnQgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShpbnB1dF9hcmd1bWVudCwgc3RyKToKICAgICAgICAgICAgICAgICAgICBpbnB1dF9hcmd1bWVudCA9IF9nZXRfYXVkaW9fZmlsZXMoCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFfcGF0aD1QYXRoKGlucHV0X2FyZ3VtZW50KS5hYnNvbHV0ZSgpCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgaWYgbGVuKGlucHV0X2FyZ3VtZW50KSA8IHNpemU6CiAgICAgICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigKICAgICAgICAgICAgICAgICAgICAgICAgZiJDYW5ub3Qgc3BsaXQgdGhlIGlucHV0ICd7d29ya2VyX2lucHV0fScgb2YgbGVuZ3RoIHtsZW4oaW5wdXRfYXJndW1lbnQpfSB0byB7c2l6ZX0gd29ya2Vycy4gIgogICAgICAgICAgICAgICAgICAgICAgICBmIlBsZWFzZSByZWR1Y2UgdGhlIGFtb3VudCBvZiB3b3JrZXJzIGZvciB0aGlzIGlucHV0LiIKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICBldmVuX2NodW5rX3NpemUgPSBsZW4oaW5wdXRfYXJndW1lbnQpIC8vIHNpemUKICAgICAgICAgICAgICAgIGNodW5rX3N0YXJ0ID0gcmFuayAqIGV2ZW5fY2h1bmtfc2l6ZQogICAgICAgICAgICAgICAgY2h1bmtfZW5kID0gKAogICAgICAgICAgICAgICAgICAgIChyYW5rICsgMSkgKiBldmVuX2NodW5rX3NpemUKICAgICAgICAgICAgICAgICAgICBpZiByYW5rICsgMSA8IHNpemUKICAgICAgICAgICAgICAgICAgICBlbHNlIGxlbihpbnB1dF9hcmd1bWVudCkKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIGNvbnRleHQubG9nZ2VyLmluZm8oCiAgICAgICAgICAgICAgICAgICAgZiJSYW5rICN7cmFua306IFByb2Nlc3NpbmcgaW5wdXQgY2h1bmsgb2YgJ3t3b3JrZXJfaW5wdXR9JyAiCiAgICAgICAgICAgICAgICAgICAgZiJmcm9tIGluZGV4IHtjaHVua19zdGFydH0gdG8ge2NodW5rX2VuZH0uIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShpbnB1dF9hcmd1bWVudCwgbGlzdCk6CiAgICAgICAgICAgICAgICAgICAgaW5wdXRfYXJndW1lbnQgPSBpbnB1dF9hcmd1bWVudFtjaHVua19zdGFydDpjaHVua19lbmRdCiAgICAgICAgICAgICAgICBlbGlmIGlzaW5zdGFuY2UoaW5wdXRfYXJndW1lbnQsIHBkLkRhdGFGcmFtZSk6CiAgICAgICAgICAgICAgICAgICAgaW5wdXRfYXJndW1lbnQgPSBpbnB1dF9hcmd1bWVudC5pbG9jW2NodW5rX3N0YXJ0OmNodW5rX2VuZDosIDpdCiAgICAgICAgICAgICAgICBrd2FyZ3Nbd29ya2VyX2lucHV0XSA9IGlucHV0X2FyZ3VtZW50CgogICAgICAgICAgICAjIFNldCB0aGUgcm9vdCB3b3JrZXIgb25seSBhcmd1bWVudHM6CiAgICAgICAgICAgIGlmIHJhbmsgPT0gMCBhbmQgcm9vdF93b3JrZXJfaW5wdXRzOgogICAgICAgICAgICAgICAga3dhcmdzLnVwZGF0ZShyb290X3dvcmtlcl9pbnB1dHMpCgogICAgICAgICAgICAjIFJ1biB0aGUgd29ya2VyOgogICAgICAgICAgICBvdXRwdXQgPSBoYW5kbGVyKCoqa3dhcmdzKQoKICAgICAgICAgICAgIyBTYXZlIHRoZSBvdXRwdXQgZGlyZWN0b3J5IG9mIHRoaXMgd29ya2VyOgogICAgICAgICAgICBvdXRwdXRfZGlyZWN0b3J5ID0gUGF0aChvdXRwdXRbMF0pCgogICAgICAgICAgICAjIFNlbmQgdGhlIG91dHB1dCB0byB0aGUgcm9vdCByYW5rIChyYW5rICMwKToKICAgICAgICAgICAgb3V0cHV0ID0gY29tbS5nYXRoZXIob3V0cHV0LCByb290PTApCgogICAgICAgICAgICAjIEpvaW4gdGhlIGRhdGEgZnJvbSBhbGwgd29ya2VyczoKICAgICAgICAgICAgaWYgcmFuayA9PSAwOgogICAgICAgICAgICAgICAgY29udGV4dC5sb2dnZXIuaW5mbygiQ29sbGVjdGluZyBkYXRhIGZyb20gd29ya2VycyB0byByb290IHdvcmtlci4iKQoKICAgICAgICAgICAgICAgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGRpZmZlcmVudCBvdXRwdXQgZGlyZWN0b3JpZXM6CiAgICAgICAgICAgICAgICBvdXRwdXRfZGlyZWN0b3JpZXMgPSBzZXQoW1BhdGgob3V0X2RpcikgZm9yIG91dF9kaXIsIF8sIF8gaW4gb3V0cHV0XSkKICAgICAgICAgICAgICAgIGZvciByIGluIHJhbmdlKDEsIHNpemUpOgogICAgICAgICAgICAgICAgICAgICMgVHJ1ZSBtZWFucyB0aGUgb3RoZXIgd29ya2VycyBzaG91bGQgcGFzcyB0aGVpciBmaWxlcyB0byB0aGUgcm9vdCB3b3JrZXIgKHJhbmsgMCk6CiAgICAgICAgICAgICAgICAgICAgY29tbS5zZW5kKGxlbihvdXRwdXRfZGlyZWN0b3JpZXMpICE9IDEsIGRlc3Q9cikKCiAgICAgICAgICAgICAgICAjIElmIHRoZXJlIGFyZSBkaWZmZXJlbnQgb3V0cHV0IGRpcmVjdG9yaWVzLCBsaXN0ZW4gdG8gdGhlIG90aGVyIHdvcmtlcnM6CiAgICAgICAgICAgICAgICBpZiBsZW4ob3V0cHV0X2RpcmVjdG9yaWVzKSAhPSAxOgogICAgICAgICAgICAgICAgICAgICMgQ29sbGVjdCB0aGUgZmlsZXMgZnJvbSB0aGUgb3RoZXIgd29ya2VyczoKICAgICAgICAgICAgICAgICAgICBmaWxlcyA9IFtdCiAgICAgICAgICAgICAgICAgICAgZm9yIHIgaW4gcmFuZ2UoMSwgc2l6ZSk6CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzLmV4dGVuZChjb21tLnJlY3Yoc291cmNlPXIpKQogICAgICAgICAgICAgICAgICAgICMgV3JpdGUgdGhlIGZpbGVzIHRvIHRoZSByb290IHdvcmtlcidzIG91dHB1dCBkaXJlY3Rvcnk6CiAgICAgICAgICAgICAgICAgICAgZm9yIGZpbGVfbmFtZSwgZmlsZV9jb250ZW50IGluIGZpbGVzOgogICAgICAgICAgICAgICAgICAgICAgICB3aXRoIG9wZW4ob3V0cHV0X2RpcmVjdG9yeSAvIGZpbGVfbmFtZSwgInciKSBhcyBmOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZi53cml0ZShmaWxlX2NvbnRlbnQpCgogICAgICAgICAgICAgICAgIyBDb25jYXRlbmF0ZSB0aGUgZGF0YWZyYW1lczoKICAgICAgICAgICAgICAgIGRhdGFmcmFtZSA9IHBkLmNvbmNhdChvYmpzPVtkZiBmb3IgXywgZGYsIF8gaW4gb3V0cHV0XSwgYXhpcz0wKQoKICAgICAgICAgICAgICAgICMgQ29uY2F0ZW5hdGUgdGhlIGVycm9ycyBkaWN0aW9uYXJpZXM6CiAgICAgICAgICAgICAgICBlcnJvcnNfZGljdGlvbmFyeSA9IHJlZHVjZSgKICAgICAgICAgICAgICAgICAgICBvcGVyYXRvci5pb3IsIFtlcnIgZm9yIF8sIF8sIGVyciBpbiBvdXRwdXRdLCB7fQogICAgICAgICAgICAgICAgKQoKICAgICAgICAgICAgICAgIHJldHVybiBzdHIob3V0cHV0X2RpcmVjdG9yeSksIGRhdGFmcmFtZSwgZXJyb3JzX2RpY3Rpb25hcnkKCiAgICAgICAgICAgICMgTGlzdGVuIHRvIHJhbmsgMCB0byBzZWUgaWYgdGhlcmUgYXJlIGRpZmZlcmVudCBvdXRwdXQgZGlyZWN0b3JpZXMgYW5kIHRoaXMgcmFuayBuZWVkIHRvIHNlbmQgaXRzIGZpbGVzIHRvCiAgICAgICAgICAgICMgaXQ6CiAgICAgICAgICAgIGlmIGNvbW0ucmVjdihzb3VyY2U9MCk6CiAgICAgICAgICAgICAgICBmaWxlcyA9IFtdCiAgICAgICAgICAgICAgICBmb3IgZmlsZSBpbiBvcy5saXN0ZGlyKG91dHB1dF9kaXJlY3RvcnkpOgogICAgICAgICAgICAgICAgICAgIHdpdGggb3BlbihvdXRwdXRfZGlyZWN0b3J5IC8gZmlsZSwgInIiKSBhcyBmOgogICAgICAgICAgICAgICAgICAgICAgICBmaWxlcy5hcHBlbmQoKGZpbGUsIGYucmVhZCgpKSkKICAgICAgICAgICAgICAgIGNvbW0uc2VuZChmaWxlcywgZGVzdD0wKQogICAgICAgICAgICByZXR1cm4gTm9uZQoKICAgICAgICByZXR1cm4gd3JhcHBlcgoKICAgIHJldHVybiBkZWNvcmF0b3IKCgpkZWYgX2NoZWNrX21scnVuX2FuZF9vcGVuX21waSgpIC0+IFR1cGxlWyJtbHJ1bi5NTENsaWVudEN0eCIsICJtcGk0cHkuTVBJLkludHJhY29tbSJdOgogICAgaXNfbXBpID0gRmFsc2UKICAgIHRyeToKICAgICAgICBpbXBvcnQgbWxydW4KCiAgICAgICAgY29udGV4dCA9IG1scnVuLmdldF9vcl9jcmVhdGVfY3R4KG5hbWU9Im1scnVuIikKICAgICAgICBpc19tcGkgPSBjb250ZXh0LmxhYmVscy5nZXQoImtpbmQiLCAiam9iIikgPT0gIm1waWpvYiIKCiAgICAgICAgaWYgaXNfbXBpOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBmcm9tIG1waTRweSBpbXBvcnQgTVBJCgogICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQsIE1QSS5DT01NX1dPUkxECiAgICAgICAgICAgIGV4Y2VwdCBNb2R1bGVOb3RGb3VuZEVycm9yIGFzIG1waTRweV9ub3RfZm91bmQ6CiAgICAgICAgICAgICAgICBjb250ZXh0LmxvZ2dlci5lcnJvcigKICAgICAgICAgICAgICAgICAgICAiVG8gZGlzdHJpYnV0ZSB0aGUgZnVuY3Rpb24gdXNpbmcgTUxSdW4ncyAnbXBpam9iJyB5b3UgbmVlZCB0byBoYXZlIGBtcGk0cHlgIHBhY2thZ2UgaW4geW91ciAiCiAgICAgICAgICAgICAgICAgICAgImludGVycHJldGVyLiBQbGVhc2UgcnVuIGBwaXAgaW5zdGFsbCBtcGk0cHlgIGFuZCBtYWtlIHN1cmUgeW91IGhhdmUgb3Blbi1tcGkuIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgcmFpc2UgbXBpNHB5X25vdF9mb3VuZAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBjb250ZXh0LCBOb25lCiAgICBleGNlcHQgTW9kdWxlTm90Rm91bmRFcnJvciBhcyBtb2R1bGVfbm90X2ZvdW5kOgogICAgICAgIGlmIGlzX21waToKICAgICAgICAgICAgcmFpc2UgbW9kdWxlX25vdF9mb3VuZAogICAgcmV0dXJuIE5vbmUsIE5vbmUKCgpAb3Blbl9tcGlfaGFuZGxlcih3b3JrZXJfaW5wdXRzPVsiZGF0YV9wYXRoIl0sIHJvb3Rfd29ya2VyX2lucHV0cz17InZlcmJvc2UiOiBUcnVlfSkKZGVmIHRyYW5zY3JpYmUoCiAgICAjIElucHV0IC8gT3V0cHV0IGt3YXJnczoKICAgIGRhdGFfcGF0aDogVW5pb25bc3RyLCBQYXRoLCBMaXN0W1VuaW9uW3N0ciwgUGF0aF1dXSwKICAgIG91dHB1dF9kaXJlY3Rvcnk6IHN0ciA9IE5vbmUsCiAgICAjIE1vZGVsIGxvYWRpbmcga3dhcmdzOgogICAgbW9kZWxfbmFtZTogc3RyID0gIm9wZW5haS93aGlzcGVyLXRpbnkiLAogICAgZGV2aWNlOiBzdHIgPSBOb25lLAogICAgdXNlX2ZsYXNoX2F0dGVudGlvbl8yOiBib29sID0gTm9uZSwKICAgIHVzZV9iZXR0ZXJfdHJhbnNmb3JtZXJzOiBib29sID0gTm9uZSwKICAgICMgR2VuZXJhdGlvbiBrd2FyZ3M6CiAgICBhc3Npc3RhbnRfbW9kZWw6IHN0ciA9IE5vbmUsCiAgICBtYXhfbmV3X3Rva2VuczogaW50ID0gMTI4LAogICAgY2h1bmtfbGVuZ3RoX3M6IGludCA9IDMwLAogICAgYmF0Y2hfc2l6ZTogaW50ID0gOCwKICAgIHNwb2tlbl9sYW5ndWFnZTogc3RyID0gTm9uZSwKICAgIHRyYW5zbGF0ZV90b19lbmdsaXNoOiBib29sID0gRmFsc2UsCiAgICAjIERpYXJpemF0aW9uIGt3YXJnczoKICAgIHNwZWVjaF9kaWFyaXphdGlvbjogRGljdFtzdHIsIExpc3RbVHVwbGVbZmxvYXQsIGZsb2F0LCBzdHJdXV0gPSBOb25lLAogICAgc3BlZWNoX2RpYXJpemVfcGVyX2NoYW5uZWw6IGludCA9IE5vbmUsCiAgICBzcGVha2VyX2xhYmVsczogTGlzdFtzdHJdID0gTm9uZSwKICAgICMgT3RoZXIga3dhcmdzOgogICAgdXNlX211bHRpcHJvY2Vzc2luZzogVW5pb25bYm9vbCwgaW50XSA9IEZhbHNlLAogICAgdmVyYm9zZTogYm9vbCA9IEZhbHNlLAopOgogICAgIiIiCiAgICBUcmFuc2NyaWJlIGF1ZGlvIGZpbGVzIGludG8gdGV4dCBmaWxlcyBhbmQgY29sbGVjdCBhZGRpdGlvbmFsIGRhdGEuIFRoZSBlbmQgcmVzdWx0IGlzIGEgZGlyZWN0b3J5IG9mIHRyYW5zY3JpYmVkCiAgICB0ZXh0IGZpbGVzIGFuZCBhIGRhdGFmcmFtZSBjb250YWluaW5nIHRoZSBmb2xsb3dpbmcgY29sdW1uczoKCiAgICAqIGF1ZGlvX2ZpbGUgLSBUaGUgYXVkaW8gZmlsZSBwYXRoLgogICAgKiB0cmFuc2NyaXB0aW9uX2ZpbGUgLSBUaGUgdHJhbnNjcmliZWQgdGV4dCBmaWxlIG5hbWUgaW4gdGhlIG91dHB1dCBkaXJlY3RvcnkuCgogICAgVGhlIHRyYW5zY3JpcHRpb24gaXMgYmFzZWQgb24gSHVnZ2luZ2ZhY2UncyBBU1IgcGlwZWxpbmUgLQogICAgaHR0cHM6Ly9odWdnaW5nZmFjZS5jby90cmFuc2Zvcm1lcnMvbWFpbl9jbGFzc2VzL3BpcGVsaW5lcy5odG1sI3RyYW5zZm9ybWVycy5BdXRvbWF0aWNTcGVlY2hSZWNvZ25pdGlvblBpcGVsaW5lIGFuZAogICAgaXMgdGVzdGVkIHdpdGggT3BlbkFJJ3MgV2hpc3BlciBtb2RlbHMgLSBodHRwczovL2h1Z2dpbmdmYWNlLmNvL29wZW5haS4KCiAgICBJZiBvbmUgb2YgdGhlIHNwZWFrZXIgZGlhcml6YXRpb24gcGFyYW1ldGVycyBhcmUgZ2l2ZW4gKGVpdGhlciBgc3BlZWNoX2RpYXJpemF0aW9uYCBvcgogICAgYHNwZWVjaF9kaWFyaXplX3Blcl9jaGFubmVsYCksIHRoZSB0cmFuc2NyaXB0aW9uIHdpbGwgYmUgd3JpdHRlbiBpbiBhIGNvbnZlcnNhdGlvbiBmb3JtYXQsIHdoZXJlIGVhY2ggc3BlYWtlciB3aWxsCiAgICBiZSB3cml0dGVuIGluIGEgc2VwYXJhdGUgbGluZTo6CgogICAgICAgIHNwZWFrZXJfMTogdGV4dAogICAgICAgIHNwZWFrZXJfMjogdGV4dAogICAgICAgIHNwZWFrZXJfMTogdGV4dAogICAgICAgIC4uLgoKICAgIDpwYXJhbSBkYXRhX3BhdGg6ICAgICAgICAgICAgICAgICAgQSBkaXJlY3Rvcnkgb2YgYXVkaW8gZmlsZXMgb3IgYSBzaW5nbGUgZmlsZSBvciBhIGxpc3Qgb2YgZmlsZXMgdG8gdHJhbnNjcmliZS4KICAgIDpwYXJhbSBvdXRwdXRfZGlyZWN0b3J5OiAgICAgICAgICAgUGF0aCB0byBhIGRpcmVjdG9yeSB0byBzYXZlIGFsbCB0cmFuc2NyaWJlZCBhdWRpbyBmaWxlcy4gSWYgbm90IGdpdmVuLCB3aWxsIHNhdmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIHRyYW5zY3JpYmVkIGZpbGVzIGluIGEgdGVtcG9yYXJ5IGRpcmVjdG9yeS4KICAgIDpwYXJhbSBtb2RlbF9uYW1lOiAgICAgICAgICAgICAgICAgVGhlIG1vZGVsIG5hbWUgdG8gdXNlLiBTaG91bGQgYmUgYSBtb2RlbCBmcm9tIHRoZSBPcGVuQUkncyBXaGlzcGVyIG1vZGVscyBmb3IKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVzdCByZXN1bHRzIChmb3IgZXhhbXBsZSAidGlueSIsICJiYXNlIiwgImxhcmdlIiwgZXRjLikuIFNlZSBoZXJlIGZvciBtb3JlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZm9ybWF0aW9uOiBodHRwczovL2h1Z2dpbmdmYWNlLmNvL29wZW5haT9zZWFyY2hfbW9kZWxzPXdoaXNwZXIuCiAgICA6cGFyYW0gZGV2aWNlOiAgICAgICAgICAgICAgICAgICAgIFRoZSBkZXZpY2UgdG8gdXNlIGZvciBpbmZlcmVuY2UuIElmIG5vdCBnaXZlbiwgd2lsbCB1c2UgR1BVIGlmIGF2YWlsYWJsZS4KICAgIDpwYXJhbSB1c2VfZmxhc2hfYXR0ZW50aW9uXzI6ICAgICAgV2hldGhlciB0byB1c2UgdGhlIEZsYXNoIEF0dGVudGlvbiAyIGltcGxlbWVudGF0aW9uLiBJdCBjYW4gYmUgdXNlZCBvbmx5IHdpdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25lIG9mIHRoZSBmb2xsb3dpbmcgR1BVczogTnZpZGlhIEggc2VyaWVzIGFuZCBOdmlkaWEgQSBzZXJpZXMuIFQ0IHN1cHBvcnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBiZSBhdmFpbGFibGUgc29vbi4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vdGU6IElmIGJvdGggYHVzZV9mbGFzaF9hdHRlbnRpb25fMmAgYW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGB1c2VfYmV0dGVyX3RyYW5zZm9ybWVyc2AgYXJlIGBOb25lYCwgdGhlIG9wdGltaXphdGlvbiB3aWxsIGJlIGNob3NlbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvbWF0aWNhbGx5IGFjY29yZGluZyB0byB0aGUgYXZhaWxhYmxlIHJlc291cmNlcy4KCiAgICA6cGFyYW0gdXNlX2JldHRlcl90cmFuc2Zvcm1lcnM6ICAgIFdoZXRoZXIgdG8gdXNlIHRoZSBCZXR0ZXIgVHJhbnNmb3JtZXJzIGxpYnJhcnkgdG8gZnVydGhlciBvcHRpbWl6ZSB0aGUgbW9kZWwuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNob3VsZCBiZSB1c2VkIGZvciBhbGwgdXNlIGNhc2VzIHRoYXQgZG8gbm90IHN1cHBvcnQgZmxhc2ggYXR0ZW50aW9uIDIuCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOb3RlOiBJZiBib3RoIGB1c2VfZmxhc2hfYXR0ZW50aW9uXzJgIGFuZCBgdXNlX2JldHRlcl90cmFuc2Zvcm1lcnNgIGFyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm9uZWAsIHRoZSBvcHRpbWl6YXRpb24gd2lsbCBiZSBjaG9zZW4gYXV0b21hdGljYWxseSBhY2NvcmRpbmcgdG8gdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2YWlsYWJsZSByZXNvdXJjZXMuCiAgICA6cGFyYW0gYXNzaXN0YW50X21vZGVsOiAgICAgICAgICAgIFRoZSBhc3Npc3RhbnQgbW9kZWwgbmFtZSB0byB1c2UgZm9yIGluZmVyZW5jZS4gTm90aWNlIHRoYXQgdGhlIG9wdGltaXphdGlvbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZsYXNoIGF0dGVudGlvbiAyIGFuZCBiZXR0ZXIgdHJhbnNmb3JtZXJzKSB3aWxsIGJlIGFwcGxpZWQgZm9yIHRoZSBhc3Npc3RhbnQgYXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VsbC4gU2hvdWxkIGJlIGEgbW9kZWwgZnJvbSBIdWdnaW5nZmFjZSdzIGRpc3RpbC13aGlzcGVyIChzZWUgaGVyZSBmb3IgbW9yZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1hdGlvbjogaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2Rpc3RpbC13aGlzcGVyKS4KCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5vdGU6IEN1cnJlbnRseSBhbiBhc3Npc3RhbnQgbW9kZWwgaXMgb25seSB1c2FibGUgd2l0aCBiYXRjaCBzaXplIG9mIDEuCiAgICA6cGFyYW0gbWF4X25ld190b2tlbnM6ICAgICAgICAgICAgIFRoZSBtYXhpbXVtIG51bWJlciBvZiBuZXcgdG9rZW5zIHRvIGdlbmVyYXRlLiBUaGlzIGlzIHVzZWQgdG8gbGltaXQgdGhlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyYXRpb24gbGVuZ3RoLiBEZWZhdWx0IGlzIDEyOCB0b2tlbnMuCiAgICA6cGFyYW0gY2h1bmtfbGVuZ3RoX3M6ICAgICAgICAgICAgIFRoZSBhdWRpbyBjaHVuayB0byBzcGxpdCB0aGUgYXVkaW8gdG8gKGluIHNlY29uZHMpLiBEZWZhdWx0IGlzIDMwIHNlY29uZHMuCiAgICA6cGFyYW0gYmF0Y2hfc2l6ZTogICAgICAgICAgICAgICAgIFRoZSBiYXRjaCBzaXplIHRvIHVzZSBmb3IgaW5mZXJlbmNlLiBEZWZhdWx0IGlzIDIuCiAgICA6cGFyYW0gc3Bva2VuX2xhbmd1YWdlOiAgICAgICAgICAgIEFpbSB3aGlzcGVyIHRvIGtub3cgd2hhdCBsYW5ndWFnZSBpcyBzcG9rZW4uIElmIE5vbmUsIGl0IHdpbGwgdHJ5IHRvIGRldGVjdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdC4KICAgIDpwYXJhbSB0cmFuc2xhdGVfdG9fZW5nbGlzaDogICAgICAgV2hldGhlciB0byB0cmFuc2xhdGUgdGhlIHRyYW5zY3JpcHRpb25zIHRvIEVuZ2xpc2guCiAgICA6cGFyYW0gc3BlZWNoX2RpYXJpemF0aW9uOiAgICAgICAgIEEgc3BlZWNoIGRpYXJpemF0aW9uIGRpY3Rpb25hcnkgd2l0aCB0aGUgZmlsZSBuYW1lcyB0byB0cmFuc2NyaWJlIGFzIGtleXMgYW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZWlyIGRpYXJpemF0aW9uIGFzIHZhbHVlLiBUaGUgZGlhcml6YXRpb24gaXMgYSBsaXN0IG9mIHR1cGxlczoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXJ0LCBlbmQsIHNwZWFrZXIpLiBBbiBleGFtcGxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBhIGRpYXJpemF0aW9uIGRpY3Rpb25hcnk6OgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImF1ZGlvX2ZpbGVfbmFtZSI6IFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzdGFydCI6IDAuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImVuZCI6IDIuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNwZWFrZXIiOiAiQWdlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic3RhcnQiOiAyLjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJlbmQiOiA0LjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzcGVha2VyIjogIkNsaWVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTm90ZTogVGhlIGRpYXJpemF0aW9uIG11c3QgYmUgZm9yIHRoZSBlbnRpcmUgZHVyYXRpb24gb2YgdGhlIGF1ZGlvIGZpbGUgKGFzIGxvbmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMgV2hpc3BlciBpcyBwcmVkaWN0aW5nIHdvcmRzIHVwIHVudGlsIHRoZW4uCiAgICA6cGFyYW0gc3BlZWNoX2RpYXJpemVfcGVyX2NoYW5uZWw6IFBlcmZvcm0gc3BlZWNoIGRpYXJpemF0aW9uIHBlciBjaGFubmVsLiBFYWNoIHNwZWFrZXIgaXMgZXhwZWN0ZWQgdG8gYmVsb25nIHRvCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEgc2VwYXJhdGUgY2hhbm5lbCBpbiB0aGUgYXVkaW8uIE5vdGljZTogVGhpcyB3aWxsIG1ha2UgdGhlIHRyYW5zY3JpcHRpb24KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvd2VyIGFzIGVhY2ggY2hhbm5lbCB3aWwgYmUgdHJhbnNjcmliZWQgc2VwYXJhdGx5LiBJZiBhIHNwZWVjaCBkaWFyaXphdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcyBwYXNzZWQgKHZpYSB0aGUgYHNwZWVjaF9kaWFyaXphdGlvbmAgcGFyYW1ldGVyKSwgdGhpcyBwYXJhbWV0ZXIgaXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlZC4KICAgIDpwYXJhbSBzcGVha2VyX2xhYmVsczogICAgICAgICAgICAgQSBsaXN0IG9mIHNwZWFrZXIgbGFiZWxzIGJ5IGNoYW5uZWwgb3JkZXIgdG8gdXNlIGZvciB3cml0aW5nIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2NyaXB0aW9uIHdpdGggcmVzcGVjdCB0byBwZXIgY2hhbm5lbCBzcGVlY2ggZGlhcml6YXRpb24uIFRoaXMgd29uJ3QgYmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlZCB0b2dldGhlciB3aXRoIGEgZ2l2ZW4gc3BlZWNoIGRpYXJpemF0aW9uICh2aWEgdGhlIGBzcGVlY2hfZGlhcml6YXRpb25gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcikuCiAgICA6cGFyYW0gdXNlX211bHRpcHJvY2Vzc2luZzogICAgICAgIFdoZXRoZXIgdG8gdXNlIG11bHRpcHJvY2Vzc2luZyB0byB0cmFuc2NyaWJlIHRoZSBhdWRpbyBmaWxlcy4gQ2FuIGJlIGVpdGhlciBhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2xlYW4gdmFsdWUgb3IgYW4gaW50ZWdlci4gSWYgYFRydWVgLCB3aWxsIHVzZSB0aGUgZGVmYXVsdCBhbW91bnQgb2Ygd29ya2VycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMyk6IDEgZm9yIHRyYW5zY3JpcHRpb24sIDEgZm9yIGJhdGNoIHByb2Nlc3NpbmcgYW5kIDEgZm9yIHRhc2sgY29tcGxldGlvbiAoc3VjaAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcyBzcGVlY2ggZGlhcml6YXRpb24gYW5kIHdyaXRpbmcgdG8gZmlsZXMpLiBUbyBjb250cm9sIHRoZSBhbW91bnQgb2YgdGFza3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbiB3b3JrZXJzLCBhbiBpbnRlZ2VyIGNhbiBiZSBwcm92aWRlZCB0byBzcGVjaWZ5IHRoZSBhbW91bnQgb2Ygd29ya2Vycy4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEZhbHNlYCwgd2lsbCB1c2UgYSBzaW5nbGUgcHJvY2Vzcy4gRGVmYXVsdCBpcyBgRmFsc2VgLgogICAgOnBhcmFtIHZlcmJvc2U6ICAgICAgICAgICAgICAgICAgICBXaGV0aGVyIHRvIHByaW50IHRoZSBwcm9ncmVzcyBvZiB0aGUgdHJhbnNjcmlwdGlvbi4gRGVmYXVsdCBpcyBgRmFsc2VgLgogICAgIiIiCiAgICBnbG9iYWwgX0xPR0dFUgoKICAgICMgR2V0IHRoZSBpbnB1dCBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlOgogICAgaWYgdmVyYm9zZToKICAgICAgICBfTE9HR0VSLmluZm8oIkNvbGxlY3RpbmcgYXVkaW8gZmlsZXMuIikKICAgIGF1ZGlvX2ZpbGVzID0gX2dldF9hdWRpb19maWxlcyhkYXRhX3BhdGg9ZGF0YV9wYXRoKQogICAgaWYgdmVyYm9zZToKICAgICAgICBfTE9HR0VSLmluZm8oZiJDb2xsZWN0ZWQge2xlbihhdWRpb19maWxlcyl9IGF1ZGlvIGZpbGVzLiIpCgogICAgIyBHZXQgdGhlIG91dHB1dCBkaXJlY3Rvcnk6CiAgICBpZiBvdXRwdXRfZGlyZWN0b3J5IGlzIE5vbmU6CiAgICAgICAgaWYgdmVyYm9zZToKICAgICAgICAgICAgX0xPR0dFUi5pbmZvKCJObyBvdXRwdXQgZGlyZWN0b3J5IGdpdmVuLCB1c2luZyB0ZW1wb3JhcnkgZGlyZWN0b3J5LiIpCiAgICAgICAgb3V0cHV0X2RpcmVjdG9yeSA9IHRlbXBmaWxlLm1rZHRlbXAoKQogICAgb3V0cHV0X2RpcmVjdG9yeSA9IFBhdGgob3V0cHV0X2RpcmVjdG9yeSkuYWJzb2x1dGUoKQogICAgb3V0cHV0X2RpcmVjdG9yeS5ta2RpcihleGlzdF9vaz1UcnVlLCBwYXJlbnRzPVRydWUpCiAgICBpZiB2ZXJib3NlOgogICAgICAgIF9MT0dHRVIuaW5mbyhmIlRyYW5zY3JpcHRpb25zIHdpbGwgYmUgc2F2ZWQgdG86IHtvdXRwdXRfZGlyZWN0b3J5fSIpCgogICAgIyBJbml0aWFsaXplIGEgYmF0Y2ggcHJvY2Vzc29yIGFjY29yZGluZyB0byB1c2VyIHJlcXVpcmVtZW50cyAobm8gc3BlZWNoIGRpYXJpemF0aW9uLCBnaXZlbiBzcGVlY2ggZGlhcml6YXRpb24sCiAgICAjIHNwZWVjaCBkaWFyaXphdGlvbiBwZXIgY2hhbm5lbCk6CiAgICBpZiBzcGVlY2hfZGlhcml6YXRpb246CiAgICAgICAgYmF0Y2hfcHJvY2Vzc29yID0gU3BlZWNoRGlhcml6YXRpb25CYXRjaFByb2Nlc3NvcigKICAgICAgICAgICAgYXVkaW9fZmlsZXM9YXVkaW9fZmlsZXMsCiAgICAgICAgICAgIG91dHB1dF9kaXJlY3Rvcnk9b3V0cHV0X2RpcmVjdG9yeSwKICAgICAgICAgICAgc3BlZWNoX2RpYXJpemF0aW9uPXNwZWVjaF9kaWFyaXphdGlvbiwKICAgICAgICApCiAgICBlbGlmIHNwZWVjaF9kaWFyaXplX3Blcl9jaGFubmVsOgogICAgICAgIGJhdGNoX3Byb2Nlc3NvciA9IFBlckNoYW5uZWxTcGVlY2hEaWFyaXphdGlvbkJhdGNoUHJvY2Vzc29yKAogICAgICAgICAgICBhdWRpb19maWxlcz1hdWRpb19maWxlcywKICAgICAgICAgICAgb3V0cHV0X2RpcmVjdG9yeT1vdXRwdXRfZGlyZWN0b3J5LAogICAgICAgICAgICBuX2NoYW5uZWxzPXNwZWVjaF9kaWFyaXplX3Blcl9jaGFubmVsLAogICAgICAgICAgICBzcGVha2Vycz1zcGVha2VyX2xhYmVscywKICAgICAgICApCiAgICBlbHNlOgogICAgICAgIGJhdGNoX3Byb2Nlc3NvciA9IEJhdGNoUHJvY2Vzc29yKAogICAgICAgICAgICBhdWRpb19maWxlcz1hdWRpb19maWxlcywKICAgICAgICAgICAgb3V0cHV0X2RpcmVjdG9yeT1vdXRwdXRfZGlyZWN0b3J5LAogICAgICAgICkKCiAgICAjIEluaXRpYWxpemUgdGhlIHRyYW5zY3JpcHRpb24gcGlwZWxpbmU6CiAgICB0cmFuc2NyaWJlciA9IFRyYW5zY3JpYmVyKAogICAgICAgIGRldmljZT1kZXZpY2UsCiAgICAgICAgdXNlX2ZsYXNoX2F0dGVudGlvbl8yPXVzZV9mbGFzaF9hdHRlbnRpb25fMiwKICAgICAgICB1c2VfYmV0dGVyX3RyYW5zZm9ybWVycz11c2VfYmV0dGVyX3RyYW5zZm9ybWVycywKICAgICAgICBhc3Npc3RhbnRfbW9kZWw9YXNzaXN0YW50X21vZGVsLAogICAgICAgIG1vZGVsX25hbWU9bW9kZWxfbmFtZSwKICAgICAgICBtYXhfbmV3X3Rva2Vucz1tYXhfbmV3X3Rva2VucywKICAgICAgICBjaHVua19sZW5ndGhfcz1jaHVua19sZW5ndGhfcywKICAgICAgICBiYXRjaF9zaXplPWJhdGNoX3NpemUsCiAgICAgICAgcmV0dXJuX3RpbWVzdGFtcHM9KAogICAgICAgICAgICAid29yZCIKICAgICAgICAgICAgaWYgc3BlZWNoX2RpYXJpemF0aW9uIGlzIG5vdCBOb25lIG9yIHNwZWVjaF9kaWFyaXplX3Blcl9jaGFubmVsIGlzIG5vdCBOb25lCiAgICAgICAgICAgIGVsc2UgRmFsc2UKICAgICAgICApLAogICAgICAgIHBlcl9jaGFubmVsX3RyYW5zY3JpcHRpb249c3BlZWNoX2RpYXJpemVfcGVyX2NoYW5uZWwgb3IgMCwKICAgICAgICBzcG9rZW5fbGFuZ3VhZ2U9c3Bva2VuX2xhbmd1YWdlLAogICAgICAgIHRyYW5zbGF0ZV90b19lbmdsaXNoPXRyYW5zbGF0ZV90b19lbmdsaXNoLAogICAgKQoKICAgICMgUnVuIHRoZSB0cmFuc2NyaXB0aW9uOgogICAgaWYgdXNlX211bHRpcHJvY2Vzc2luZzoKICAgICAgICByZXN1bHRzID0gX3BhcmFsbGVsX3J1bigKICAgICAgICAgICAgbl93b3JrZXJzPXVzZV9tdWx0aXByb2Nlc3NpbmcKICAgICAgICAgICAgaWYgaXNpbnN0YW5jZSh1c2VfbXVsdGlwcm9jZXNzaW5nLCBpbnQpCiAgICAgICAgICAgIGVsc2UgMSwKICAgICAgICAgICAgYXVkaW9fZmlsZXM9YXVkaW9fZmlsZXMsCiAgICAgICAgICAgIGJhdGNoX3Byb2Nlc3Nvcj1iYXRjaF9wcm9jZXNzb3IsCiAgICAgICAgICAgIHRyYW5zY3JpYmVyPXRyYW5zY3JpYmVyLAogICAgICAgICAgICB2ZXJib3NlPXZlcmJvc2UsCiAgICAgICAgKQogICAgZWxzZToKICAgICAgICByZXN1bHRzID0gX3J1bigKICAgICAgICAgICAgYXVkaW9fZmlsZXM9YXVkaW9fZmlsZXMsCiAgICAgICAgICAgIGJhdGNoX3Byb2Nlc3Nvcj1iYXRjaF9wcm9jZXNzb3IsCiAgICAgICAgICAgIHRyYW5zY3JpYmVyPXRyYW5zY3JpYmVyLAogICAgICAgICAgICB2ZXJib3NlPXZlcmJvc2UsCiAgICAgICAgKQoKICAgICMgUHJvY2VzcyB0aGUgcmVzdWx0czoKICAgIGlmIHZlcmJvc2U6CiAgICAgICAgX0xPR0dFUi5pbmZvKCJTdW1tYXJpemluZyB0aGUgcmVzdWx0cy4iKQogICAgc3VjY2Vzc2VzID0gW10KICAgIGVycm9ycyA9IHt9CiAgICBmb3IgaXNfZXJyb3IsIHJlc3VsdCBpbiByZXN1bHRzOgogICAgICAgIGlmIGlzX2Vycm9yOgogICAgICAgICAgICBlcnJvcnNbcmVzdWx0WzBdXSA9IHJlc3VsdFsxXQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHN1Y2Nlc3Nlcy5hcHBlbmQocmVzdWx0KQogICAgc3VjY2Vzc2VzID0gcGQuRGF0YUZyYW1lKHN1Y2Nlc3NlcywgY29sdW1ucz1bImF1ZGlvX2ZpbGUiLCAidHJhbnNjcmlwdGlvbl9maWxlIl0pCiAgICBpZiB2ZXJib3NlOgogICAgICAgIF9MT0dHRVIuaW5mbygKICAgICAgICAgICAgZiJEb25lICh7c3VjY2Vzc2VzLnNoYXBlWzBdfS97bGVuKGF1ZGlvX2ZpbGVzKX0pXG4iCiAgICAgICAgICAgIGYiVHJhbnNjcmlwdGlvbnMgc3VtbWFyeTpcbiIKICAgICAgICAgICAgZiJ7c3VjY2Vzc2VzLmhlYWQoKX0iCiAgICAgICAgKQoKICAgIHJldHVybiBzdHIob3V0cHV0X2RpcmVjdG9yeSksIHN1Y2Nlc3NlcywgZXJyb3JzCgoKZGVmIF9nZXRfYXVkaW9fZmlsZXMoCiAgICBkYXRhX3BhdGg6IFVuaW9uW1BhdGgsIHN0ciwgbGlzdF0sCikgLT4gTGlzdFtQYXRoXToKICAgICIiIgogICAgR2V0IHRoZSBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlLiBJZiBhIHBhdGggdG8gYSBkaXJlY3RvcnkgaXMgZ2l2ZW4sIGFsbCBmaWxlcyBpbiB0aGUgZGlyZWN0b3J5IHdpbGwgYmUgY29sbGVjdGVkLgoKICAgIDpwYXJhbSBkYXRhX3BhdGg6IFRoZSBkYXRhIHBhdGggdG8gY29sbGVjdCB0aGUgYXVkaW8gZmlsZXMgZnJvbS4KCiAgICA6cmV0dXJuczogVGhlIGF1ZGlvIGZpbGVzIGxpc3QuCiAgICAiIiIKICAgICMgQ2hlY2sgaWYgZ2l2ZW4gYSBsaXN0IG9mIHBhdGhzOgogICAgaWYgaXNpbnN0YW5jZShkYXRhX3BhdGgsIGxpc3QpOgogICAgICAgIGF1ZGlvX2ZpbGVzID0gW10KICAgICAgICBmb3IgcGF0aCBpbiBkYXRhX3BhdGg6CiAgICAgICAgICAgIGF1ZGlvX2ZpbGVzLmV4dGVuZChfZ2V0X2F1ZGlvX2ZpbGVzKGRhdGFfcGF0aD1wYXRoKSkKICAgICAgICByZXR1cm4gYXVkaW9fZmlsZXMKCiAgICAjIENoZWNrIGlmIGdpdmVuIGEgc2luZ2xlIHN0cmluZyBwYXRoIHRvIGNhc3QgaXQgdG8gYSBgcGF0aGxpYi5QYXRoYDoKICAgIGlmIGlzaW5zdGFuY2UoZGF0YV9wYXRoLCBzdHIpOgogICAgICAgIGRhdGFfcGF0aCA9IFBhdGgoZGF0YV9wYXRoKS5hYnNvbHV0ZSgpCgogICAgIyBDaGVjayBpZiB0aGUgcGF0aCBpcyBvZiBhIGRpcmVjdG9yeSBvciBhIGZpbGU6CiAgICBpZiBkYXRhX3BhdGguaXNfZGlyKCk6CiAgICAgICAgIyBHZXQgYWxsIGZpbGVzIGluc2lkZSB0aGUgZGlyZWN0b3J5OgogICAgICAgIGF1ZGlvX2ZpbGVzID0gbGlzdChkYXRhX3BhdGguZ2xvYigiKi4qIikpCiAgICBlbGlmIGRhdGFfcGF0aC5pc19maWxlKCk6CiAgICAgICAgYXVkaW9fZmlsZXMgPSBbZGF0YV9wYXRoXQogICAgZWxzZToKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKAogICAgICAgICAgICBmIlVucmVjb2duaXplZCBkYXRhIHBhdGguIFRoZSBwYXJhbWV0ZXIgYGRhdGFfcGF0aGAgbXVzdCBiZSBhIHZhbGlkIHBhdGggdG8gZWl0aGVyIGEgZGlyZWN0b3J5IHBhdGggb3IgYSAiCiAgICAgICAgICAgIGYiZmlsZS4gR2l2ZW46IHtzdHIoZGF0YV9wYXRoKX0gIgogICAgICAgICkKCiAgICByZXR1cm4gYXVkaW9fZmlsZXMKCgpkZWYgX3J1bigKICAgIGF1ZGlvX2ZpbGVzOiBMaXN0W1BhdGhdLAogICAgYmF0Y2hfcHJvY2Vzc29yOiBCYXRjaFByb2Nlc3NvciwKICAgIHRyYW5zY3JpYmVyOiBUcmFuc2NyaWJlciwKICAgIHZlcmJvc2U6IGJvb2wsCikgLT4gTGlzdFtUdXBsZVtib29sLCBUdXBsZVtzdHIsIHN0cl1dXToKICAgICIiIgogICAgUnVuIHRoZSB0cmFuc2NyaXB0aW9uIHdpdGhvdXQgbXVsdGlwcm9jZXNzaW5nLgoKICAgIDpwYXJhbSBhdWRpb19maWxlczogICAgIFRoZSBhdWRpbyBmaWxlcyB0byB0cmFuc2NyaWJlLgogICAgOnBhcmFtIGJhdGNoX3Byb2Nlc3NvcjogVGhlIGJhdGNoIHByb2Nlc3NvciB0byB1c2UuCiAgICA6cGFyYW0gdHJhbnNjcmliZXI6ICAgICBUaGUgdHJhbnNjcmliZXIgdG8gdXNlLgogICAgOnBhcmFtIHZlcmJvc2U6ICAgICAgICAgVmVyYm9zaXR5LgoKICAgIDpyZXR1cm5zOiBUaGUgY29sbGVjdGVkIHJlc3VsdHMuCiAgICAiIiIKICAgICMgTG9hZCB0aGUgdHJhbnNjcmlwdGlvbiBwaXBlbGluZToKICAgIGlmIHZlcmJvc2U6CiAgICAgICAgX0xPR0dFUi5pbmZvKGYiTG9hZGluZyB0aGUgdHJhbnNjcmlwdGlvbiBwaXBlbGluZS4iKQogICAgdHJhbnNjcmliZXIubG9hZCgpCiAgICBpZiB2ZXJib3NlOgogICAgICAgIF9MT0dHRVIuaW5mbygiVHJhbnNjcmlwdGlvbiBwaXBlbGluZSBsb2FkZWQuIikKCiAgICAjIFRyYW5zY3JpYmUgdGhlIGZpbGVzOgogICAgdHJhbnNjcmliZXIudHJhbnNjcmliZSgKICAgICAgICBhdWRpb19maWxlcz1hdWRpb19maWxlcywKICAgICAgICBiYXRjaF9wcm9jZXNzb3I9YmF0Y2hfcHJvY2Vzc29yLAogICAgICAgIHZlcmJvc2U9dmVyYm9zZSwKICAgICkKCiAgICAjIFJldHVybiB0aGUgcmVzdWx0czoKICAgIHJldHVybiBiYXRjaF9wcm9jZXNzb3IuZ2V0X3Jlc3VsdHMoKQoKCmRlZiBfcGFyYWxsZWxfcnVuKAogICAgbl93b3JrZXJzOiBpbnQsCiAgICBhdWRpb19maWxlczogTGlzdFtQYXRoXSwKICAgIGJhdGNoX3Byb2Nlc3NvcjogQmF0Y2hQcm9jZXNzb3IsCiAgICB0cmFuc2NyaWJlcjogVHJhbnNjcmliZXIsCiAgICB2ZXJib3NlOiBib29sLAopOgogICAgIiIiCiAgICBSdW4gdGhlIHRyYW5zY3JpcHRpb24gd2l0aCBtdWx0aXByb2Nlc3NpbmcuCgogICAgOnBhcmFtIG5fd29ya2VyczogICAgICAgVGhlIGFtb3VudCBvZiB3b3JrZXJzIHRvIHVzZSBhcyB0YXNrIGNvbXBsZXRlcnMuCiAgICA6cGFyYW0gYXVkaW9fZmlsZXM6ICAgICBUaGUgYXVkaW8gZmlsZXMgdG8gdHJhbnNjcmliZS4KICAgIDpwYXJhbSBiYXRjaF9wcm9jZXNzb3I6IFRoZSBiYXRjaCBwcm9jZXNzb3IgdG8gdXNlLgogICAgOnBhcmFtIHRyYW5zY3JpYmVyOiAgICAgVGhlIHRyYW5zY3JpYmVyIHRvIHVzZS4KICAgIDpwYXJhbSB2ZXJib3NlOiAgICAgICAgIFZlcmJvc2l0eS4KCiAgICA6cmV0dXJuczogVGhlIGNvbGxlY3RlZCByZXN1bHRzLgogICAgIiIiCiAgICAjIEluaXRpYWxpemUgdGhlIG11bHRpcHJvY2Vzc2luZyBxdWV1ZXM6CiAgICBiYXRjaGVzX3F1ZXVlID0gUXVldWUoKQogICAgdGFza3NfcXVldWUgPSBRdWV1ZSgpCiAgICByZXN1bHRzX3F1ZXVlID0gUXVldWUoKQoKICAgICMgSW5pdGlhbGl6ZSB0aGUgbXVsdGlwcm9jZXNzaW5nIHByb2Nlc3NlczoKICAgIGJhdGNoX3Byb2Nlc3NpbmdfcHJvY2VzcyA9IFByb2Nlc3MoCiAgICAgICAgdGFyZ2V0PV9tdWx0aXByb2Nlc3NpbmdfcHJvY2Vzc19iYXRjaGVzLAogICAgICAgIGt3YXJncz17CiAgICAgICAgICAgICJiYXRjaF9wcm9jZXNzb3IiOiBiYXRjaF9wcm9jZXNzb3IsCiAgICAgICAgICAgICJiYXRjaGVzX3F1ZXVlIjogYmF0Y2hlc19xdWV1ZSwKICAgICAgICAgICAgInRhc2tzX3F1ZXVlIjogdGFza3NfcXVldWUsCiAgICAgICAgICAgICJuX3Rhc2tfY29tcGxldGVycyI6IG5fd29ya2VycywKICAgICAgICB9LAogICAgKQogICAgdGFza19jb21wbGV0aW9uX3Byb2Nlc3NlcyA9IFsKICAgICAgICBQcm9jZXNzKAogICAgICAgICAgICB0YXJnZXQ9X211bHRpcHJvY2Vzc2luZ19jb21wbGV0ZV90YXNrcywKICAgICAgICAgICAga3dhcmdzPXsidGFza3NfcXVldWUiOiB0YXNrc19xdWV1ZSwgInJlc3VsdHNfcXVldWUiOiByZXN1bHRzX3F1ZXVlfSwKICAgICAgICApCiAgICAgICAgZm9yIF8gaW4gcmFuZ2Uobl93b3JrZXJzKQogICAgXQoKICAgICMgU3RhcnQgdGhlIG11bHRpcHJvY2Vzc2luZyBwcm9jZXNzZXM6CiAgICBiYXRjaF9wcm9jZXNzaW5nX3Byb2Nlc3Muc3RhcnQoKQogICAgZm9yIHAgaW4gdGFza19jb21wbGV0aW9uX3Byb2Nlc3NlczoKICAgICAgICBwLnN0YXJ0KCkKCiAgICAjIExvYWQgdGhlIHRyYW5zY3JpcHRpb24gcGlwZWxpbmU6CiAgICBpZiB2ZXJib3NlOgogICAgICAgIF9MT0dHRVIuaW5mbyhmIkxvYWRpbmcgdGhlIHRyYW5zY3JpcHRpb24gcGlwZWxpbmUuIikKICAgIHRyYW5zY3JpYmVyLmxvYWQoKQogICAgaWYgdmVyYm9zZToKICAgICAgICBfTE9HR0VSLmluZm8oIlRyYW5zY3JpcHRpb24gcGlwZWxpbmUgbG9hZGVkLiIpCgogICAgIyBUcmFuc2NyaWJlIHRoZSBmaWxlczoKICAgIHRyYW5zY3JpYmVyLnRyYW5zY3JpYmUoCiAgICAgICAgYXVkaW9fZmlsZXM9YXVkaW9fZmlsZXMsIGJhdGNoZXNfcXVldWU9YmF0Y2hlc19xdWV1ZSwgdmVyYm9zZT12ZXJib3NlCiAgICApCgogICAgIyBDb2xsZWN0IHRoZSByZXN1bHRzOgogICAgcmVzdWx0cyA9IFtdCiAgICBzdG9wX21hcmtzX2NvdW50ZXIgPSAwCiAgICB3aGlsZSBUcnVlOgogICAgICAgICMgR2V0IGEgcmVzdWx0IGZyb20gdGhlIHF1ZXVlOgogICAgICAgIHJlc3VsdDogVHVwbGVbYm9vbCwgVHVwbGVbc3RyLCBzdHJdXSA9IHJlc3VsdHNfcXVldWUuZ2V0KCkKICAgICAgICBpZiByZXN1bHQgPT0gX01VTFRJUFJPQ0VTU0lOR19TVE9QX01BUks6CiAgICAgICAgICAgIHN0b3BfbWFya3NfY291bnRlciArPSAxCiAgICAgICAgICAgIGlmIHN0b3BfbWFya3NfY291bnRlciA9PSBuX3dvcmtlcnM6CiAgICAgICAgICAgICAgICBicmVhawogICAgICAgIGVsc2U6CiAgICAgICAgICAgICMgQ29sbGVjdCB0aGUgcmVzdWx0OgogICAgICAgICAgICByZXN1bHRzLmFwcGVuZChyZXN1bHQpCgogICAgIyBXYWl0IGZvciB0aGUgcHJvY2Vzc2VzIHRvIGZpbmlzaDoKICAgIHJlc3VsdHNfcXVldWUuZW1wdHkoKQogICAgYmF0Y2hfcHJvY2Vzc2luZ19wcm9jZXNzLmpvaW4oKQogICAgZm9yIHAgaW4gdGFza19jb21wbGV0aW9uX3Byb2Nlc3NlczoKICAgICAgICBwLmpvaW4oKQoKICAgIHJldHVybiByZXN1bHRz
  disable_auto_mount: false
  description: Transcribe audio files into text files
  image: ''
  command: ''
  default_handler: transcribe
  entry_points:
    do_task:
      name: do_task
      doc: Try to perform the task storing an error if occurred.
      lineno: 348
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
    is_failed:
      name: is_failed
      doc: Check if the task failed.
      lineno: 70
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: Whether the task failed.
        type: bool
    get_result:
      name: get_result
      doc: 'Get the result of the task. If the task failed, the error will be returned,
        otherwise, the result will be the

        text file name.'
      lineno: 78
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: The task's result.
        type: Tuple[str, str]
    to_tuple:
      name: to_tuple
      doc: Convert the task to a tuple to reconstruct it later (used for multiprocessing
        to pass in queue).
      lineno: 358
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: The converted task.
        type: Tuple[str, dict]
    transcription_output_channels:
      name: transcription_output_channels
      doc: Get the transcription output channels.
      lineno: 340
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: The transcription output channels.
        type: List[Tuple[str, dict]]
    process_batch:
      name: process_batch
      doc: 'Process a batch of transcriptions. Tasks related to the given batch will
        be created and stored in the batch

        processor.'
      lineno: 575
      parameters:
      - name: self
      - name: batch
        type: List[dict]
        doc: The batch of transcriptions to process.
      has_varargs: false
      has_kwargs: false
    get_tasks:
      name: get_tasks
      doc: Get the tasks to perform.
      lineno: 453
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: The tasks to perform.
        type: List[BaseTask]
    do_tasks:
      name: do_tasks
      doc: Perform the tasks. Should be used if no multiprocessing queue is given
        to a transcriber.
      lineno: 463
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
    get_results:
      name: get_results
      doc: Get the results of the tasks. The stored results are then cleared.
      lineno: 471
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
      outputs:
      - doc: The results of the tasks.
        type: List[Tuple[bool, Tuple[str, str]]]
    load:
      name: load
      doc: Load the transcriber. Must be called before transcribing.
      lineno: 695
      parameters:
      - name: self
      has_varargs: false
      has_kwargs: false
    transcribe:
      name: transcribe
      doc: "Transcribe audio files into text files and collect additional data. The\
        \ end result is a directory of transcribed\ntext files and a dataframe containing\
        \ the following columns:\n\n* audio_file - The audio file path.\n* transcription_file\
        \ - The transcribed text file name in the output directory.\n\nThe transcription\
        \ is based on Huggingface's ASR pipeline -\nhttps://huggingface.co/transformers/main_classes/pipelines.html#transformers.AutomaticSpeechRecognitionPipeline\
        \ and\nis tested with OpenAI's Whisper models - https://huggingface.co/openai.\n\
        \nIf one of the speaker diarization parameters are given (either `speech_diarization`\
        \ or\n`speech_diarize_per_channel`), the transcription will be written in\
        \ a conversation format, where each speaker will\nbe written in a separate\
        \ line::\n\n    speaker_1: text\n    speaker_2: text\n    speaker_1: text\n\
        \    ..."
      lineno: 1097
      parameters:
      - name: data_path
        type: Union[str, Path, List[Union[str, Path]]]
        doc: A directory of audio files or a single file or a list of files to transcribe.
      - name: output_directory
        type: str
        doc: Path to a directory to save all transcribed audio files. If not given,
          will save the transcribed files in a temporary directory.
        default: null
      - name: model_name
        type: str
        doc: 'The model name to use. Should be a model from the OpenAI''s Whisper
          models for best results (for example "tiny", "base", "large", etc.). See
          here for more information: https://huggingface.co/openai?search_models=whisper.'
        default: openai/whisper-tiny
      - name: device
        type: str
        doc: The device to use for inference. If not given, will use GPU if available.
        default: null
      - name: use_flash_attention_2
        type: bool
        doc: 'Whether to use the Flash Attention 2 implementation. It can be used
          only with one of the following GPUs: Nvidia H series and Nvidia A series.
          T4 support will be available soon.'
        default: null
      - name: use_better_transformers
        type: bool
        doc: Whether to use the Better Transformers library to further optimize the
          model. Should be used for all use cases that do not support flash attention
          2.
        default: null
      - name: assistant_model
        type: str
        doc: 'The assistant model name to use for inference. Notice that the optimizations
          (flash attention 2 and better transformers) will be applied for the assistant
          as well. Should be a model from Huggingface''s distil-whisper (see here
          for more information: https://github.com/huggingface/distil-whisper).'
        default: null
      - name: max_new_tokens
        type: int
        doc: The maximum number of new tokens to generate. This is used to limit the
          generation length. Default is 128 tokens.
        default: 128
      - name: chunk_length_s
        type: int
        doc: The audio chunk to split the audio to (in seconds). Default is 30 seconds.
        default: 30
      - name: batch_size
        type: int
        doc: The batch size to use for inference. Default is 2.
        default: 8
      - name: spoken_language
        type: str
        doc: Aim whisper to know what language is spoken. If None, it will try to
          detect it.
        default: null
      - name: translate_to_english
        type: bool
        doc: Whether to translate the transcriptions to English.
        default: false
      - name: speech_diarization
        type: Dict[str, List[Tuple[float, float, str]]]
        doc: 'A speech diarization dictionary with the file names to transcribe as
          keys and their diarization as value. The diarization is a list of tuples:
          (start, end, speaker). An example for a diarization dictionary::'
        default: null
      - name: speech_diarize_per_channel
        type: int
        doc: 'Perform speech diarization per channel. Each speaker is expected to
          belong to a separate channel in the audio. Notice: This will make the transcription
          slower as each channel wil be transcribed separatly. If a speech diarization
          is passed (via the `speech_diarization` parameter), this parameter is ignored.'
        default: null
      - name: speaker_labels
        type: List[str]
        doc: A list of speaker labels by channel order to use for writing the transcription
          with respect to per channel speech diarization. This won't be used together
          with a given speech diarization (via the `speech_diarization` parameter).
        default: null
      - name: use_multiprocessing
        type: Union[bool, int]
        doc: 'Whether to use multiprocessing to transcribe the audio files. Can be
          either a boolean value or an integer. If `True`, will use the default amount
          of workers (3): 1 for transcription, 1 for batch processing and 1 for task
          completion (such as speech diarization and writing to files). To control
          the amount of tasks completion workers, an integer can be provided to specify
          the amount of workers. `False`, will use a single process. Default is `False`.'
        default: false
      - name: verbose
        type: bool
        doc: Whether to print the progress of the transcription. Default is `False`.
        default: false
      has_varargs: false
      has_kwargs: false
    audio_iterator:
      name: audio_iterator
      doc: ''
      lineno: 804
      has_varargs: false
      has_kwargs: false
      outputs:
      - type: Generator[Union[dict, str], None, None]
    batch_iterator:
      name: batch_iterator
      doc: ''
      lineno: 816
      has_varargs: false
      has_kwargs: false
      outputs:
      - type: Generator[List[Union[dict, str]], None, None]
    open_mpi_handler:
      name: open_mpi_handler
      doc: ''
      lineno: 957
      parameters:
      - name: worker_inputs
        type: List[str]
      - name: root_worker_inputs
        type: Dict[str, Any]
        default: null
      has_varargs: false
      has_kwargs: false
    decorator:
      name: decorator
      doc: ''
      lineno: 969
      parameters:
      - name: handler
      has_varargs: false
      has_kwargs: false
    wrapper:
      name: wrapper
      doc: ''
      lineno: 974
      has_varargs: false
      has_kwargs: true