Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fDAKy-0004v2-0p for pgadmin-hackers@arkaria.postgresql.org; Mon, 30 Apr 2018 15:03:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1fDAKw-0002Wo-Pw for pgadmin-hackers@arkaria.postgresql.org; Mon, 30 Apr 2018 15:03:30 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fDAKw-0002WM-2O for pgadmin-hackers@lists.postgresql.org; Mon, 30 Apr 2018 15:03:30 +0000 Received: from mail-ot0-x22b.google.com ([2607:f8b0:4003:c0f::22b]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1fDAKr-0000MI-4D for pgadmin-hackers@postgresql.org; Mon, 30 Apr 2018 15:03:28 +0000 Received: by mail-ot0-x22b.google.com with SMTP id l22-v6so9810493otj.0 for ; Mon, 30 Apr 2018 08:03:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=dpgrXzg2EPyoq4ot15kfNdH3pW9vBxldmOMu2L/Bokk=; b=xEK2cXp4ew4NdWKOiV2GrNVp2NJZIDhg0FjIVE82OBMxruUYuPaSHAUacxbzVUeSEo vNJbw1bh1r0oy0k8TH1QKgHmpTaDa3MMoX67oPqL5rgnkJf/aZu9WMhAv/3U82uCtBqY jgfDkipw6ZxwhUjLUvILWt+e0coS8gfygfUNZl0IeJiH47xsrQdVKnvXKZj0OBajSsAS 7MZlWll9BsjN/n2PfXt1HqWjBtXbu0EtSk9yCUwM4BVLsXL2JBo3BI4DF1JuW0pDt5OY 1f2KOOs/Qqz+Czhw5AZVPfAjqG+3Ss1FviXJU5D1k3afhmpf82hyeML4IAsCp/3SzGvY 0Q4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=dpgrXzg2EPyoq4ot15kfNdH3pW9vBxldmOMu2L/Bokk=; b=fMO5qXMJ8EG+Qz9NaBWwgIpwzHY127N8sQ/sYa18zRfQ/uQiX0wUul5CRLAX6zi/IB XmH4c8VSxjy9su/vXiYqp+QqFtXRXQPCDyDkqqp7bcnYppnp34St9fnRksn0njLuJSyT ZEP4IqPdxruZFGYAOKHshE+vpGzslSCrm8YLoeEjQBYSblwodEnHyYPHTR8flI1Smrc7 Zuzueod0ptDnT48brbaNTc8mWU2AhrdEF5rgyOXqrkipLkIkw8NkqNNWuewZeK0kjEY1 +6ppmXuv5Glkla5OidXhhFI8sbK6vg7FEW5OD7y2k6zea/xvwGwYxz+poxsi7BBTlLcv tb/Q== X-Gm-Message-State: ALQs6tDcHDe+nlJng/e6rJTnFZxjDQ5r5Fnfs7VE+yOvyLZ3mnTXntFE gnp5cGwZ1dn+j6Uo17qw7wL0q350SQz507HZDaXftw== X-Google-Smtp-Source: AB8JxZq6DHn+6Ai92iLv/+yx9WTWj7gKuZcOivvz9QcE1a7rzTOp010ESZZ9adFPDWialpNqSyeUPC7ibMMP87wB+ZQ= X-Received: by 2002:a9d:3f6:: with SMTP id f109-v6mr8085862otf.228.1525100604090; Mon, 30 Apr 2018 08:03:24 -0700 (PDT) MIME-Version: 1.0 Received: by 10.138.5.130 with HTTP; Mon, 30 Apr 2018 08:03:03 -0700 (PDT) In-Reply-To: References: From: Ashesh Vashi Date: Mon, 30 Apr 2018 20:33:03 +0530 Message-ID: Subject: Re: [pgadmin4][patch] Initial patch to decouple from ACI Tree To: Joao De Almeida Pereira Cc: Dave Page , Khushboo Vashi , Murtuza Zabuawala , pgadmin-hackers Content-Type: multipart/mixed; boundary="000000000000c11f78056b122756" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --000000000000c11f78056b122756 Content-Type: multipart/alternative; boundary="000000000000c11f74056b122754" --000000000000c11f74056b122754 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Apr 30, 2018 at 8:30 PM, Ashesh Vashi wrote: > On Sat, Apr 28, 2018 at 3:55 AM, Joao De Almeida Pereira < > jdealmeidapereira@pivotal.io> wrote: > >> Hi Hackers, >> As you are aware we kept on working on the patch, so we are attaching to >> this email a new version of the patch. >> This new version contains all the changes in the previous one plus more >> extractions of functions and refactoring of code. >> >> The objective of this patch is to create a separation between pgAdmin an= d >> the ACI Tree. We are doing this because we realized that at this point i= n >> time we have the ACI Tree all over the code of pgAdmin. I found a very >> interesting article that really talks about this: >> https://medium.freecodecamp.org/code-dependencies-are-the-de >> vil-35ed28b556d >> >> In this patch there are some visions and ideas about the location of the >> code, the way to organize it and also try to pave the future for a >> application that is stable, easy to develop on and that can be release a= t a >> times notice. >> >> We are investing a big chunk of our time in doing this refactoring, but >> while doing that we also try to respond to the patches sent to the maili= ng >> list. We would like the feedback from the community because we believe t= his >> is a changing point for the application. The idea is to change the way w= e >> develop this application, instead of only correcting a bug of developing= a >> feature, with every commit we should correct the bug or develop a featur= e >> but leave the code a little better than we found it (Refactoring, >> refactoring, refactoring). This is hard work but that is what the users >> from pgAdmin expect from this community of developers. >> >> >> =3D=3D=3D=3D=3D=3D >> >> >> >> It is a huge patch >> 86 files changed, 5492 inserts, 1840 deletions >> and we would like to get your feedback as soon as possible, because we >> are continuing to work on it which means it is going to grow in size. >> >> >> At this point in time we still have 124 of 176 calls to the function >> itemData from ACITree. >> >> What does each patch contain: >> 0001: >> Very simple patch, we found out that the linter was not looking into >> all the javascript test files, so this patch will ensure it is >> > Committed the patch along with the regression introduced because of this > patch. > >> >> 0002: >> New Tree abstraction. This patch contains the new Tree that works as a= n >> adaptor for ACI Tree and is going to be used on all the extractions that= we >> are doing. >> > > I was expecting a separate layer between the tree implementation, and > aciTree adaptor. > Please find the patch for the example. > > It will separate the two layers, and easy to replace with the new > implemenation in future. > Oops forgot to attach the patch. Please find the patch attached. -- Thanks, Ashesh > >> 0003: >> Code that extracts, wrap with tests and replace ACI Tree invocations. >> > There are many small cases left in the patches. > Hence - I would like to know the TODO list created by you. > > e.g. When we remove any of the object from the database server, we're not > yet removing the respective node from the new implementation, and its > children. > >> >> We start creating new pattern for the location of Javascript files and >> their structure. >> > I would not like to see that changes in this patch. > I would like us to come up with the actual design about the hot > pluggability before going in this direction. > >> Create patterns for creation of dialogs (backup and restore) >> > It's better - we don't change the directory structure at the moment. > > I am not against dividing the big javascript files in small chunks, but - > I would like us to discuss first about the hot plugins design first. > > -- Thanks, Ashesh > >> >> > >> >> Thanks >> Joao >> >> >> On Fri, Apr 27, 2018 at 5:34 AM Ashesh Vashi < >> ashesh.vashi@enterprisedb.com> wrote: >> >>> I have quite a few comments for the patch. >>> I will send them soon. >>> >>> On Fri, Apr 27, 2018, 14:45 Dave Page wrote: >>> >>>> How is your work on this going Ashesh? Will you be committing today? >>>> >>>> On Wed, Apr 25, 2018 at 8:52 AM, Dave Page wrote: >>>> >>>>> Ashesh; you had agreed to work on this early this week. Please ensure >>>>> you do so today. >>>>> >>>>> Thanks. >>>>> >>>>> On Tue, Apr 24, 2018 at 8:13 PM, Joao De Almeida Pereira < >>>>> jdealmeidapereira@pivotal.io> wrote: >>>>> >>>>>> Hi Hackers, >>>>>> >>>>>> Can someone review and merge this patch? >>>>>> >>>>>> Thanks >>>>>> Joao >>>>>> >>>>>> On Wed, Apr 18, 2018 at 10:23 AM Joao De Almeida Pereira < >>>>>> jdealmeidapereira@pivotal.io> wrote: >>>>>> >>>>>>> Hi Hackers, >>>>>>> Any other comment about this patch? >>>>>>> >>>>>>> Thanks >>>>>>> Joao >>>>>>> >>>>>>> On Tue, Apr 10, 2018 at 12:00 PM Joao De Almeida Pereira < >>>>>>> jdealmeidapereira@pivotal.io> wrote: >>>>>>> >>>>>>>> Hello Khushboo >>>>>>>> >>>>>>>> On Mon, Apr 9, 2018 at 1:59 AM Khushboo Vashi < >>>>>>>> khushboo.vashi@enterprisedb.com> wrote: >>>>>>>> >>>>>>>>> Hi Joao, >>>>>>>>> >>>>>>>>> I have reviewed your patch and have some suggestions. >>>>>>>>> >>>>>>>>> On Sat, Apr 7, 2018 at 12:43 AM, Joao De Almeida Pereira < >>>>>>>>> jdealmeidapereira@pivotal.io> wrote: >>>>>>>>> >>>>>>>>>> Hello Murtuza/Dave, >>>>>>>>>> Yes now the extracted functions are spread into different files. >>>>>>>>>> The intent would be to make the files as small as possible, and = also to >>>>>>>>>> group and name them in a way that would be easy to understand wh= at each >>>>>>>>>> file is doing without the need of opening it. >>>>>>>>>> As a example: >>>>>>>>>> static/js/backup will contain all the backup related >>>>>>>>>> functionality inside of this folder we can see the file: >>>>>>>>>> >>>>>>>>> menu_utils.js At this moment in time we decided to group all the >>>>>>>>>> functions that are related to the menu, but we can split that al= so if we >>>>>>>>>> believe it is easier to see. >>>>>>>>>> >>>>>>>>> It's really very good to see the separated code for backup module= . >>>>>>>>> As we have done for backup, we would like do it for other PG util= ities like >>>>>>>>> restore, maintenance etc. >>>>>>>>> Considering this, we should separate the code in a way that some >>>>>>>>> of the common functionalities can be used for other modules like= menu (as >>>>>>>>> you have mentioned above), dialogue factory etc. >>>>>>>>> Also, I think these functionalities should be in their respective >>>>>>>>> static folder instead of pgadmin/static. >>>>>>>>> >>>>>>>> >>>>>>>> About the location of the files. The move of the files to >>>>>>>> pgadmin/static/js was made on purpose in order to clearly separate >>>>>>>> Javascript from python code. >>>>>>>> The rational behind it was >>>>>>>> - Create a clear separation between the backend and frontend >>>>>>>> - Having Javascript code concentrated in a single place, hopefully= , >>>>>>>> will encourage to developers to look for a functionality, that is = already >>>>>>>> implemented in another modules, because they are right there. (Whe= n we >>>>>>>> started this journey we realized that the 'nodes' have a big group= s of code >>>>>>>> that could be shared, but because the Javascript is spread everywh= ere it is >>>>>>>> much harder to look for it) >>>>>>>> >>>>>>>> >>>>>>>> There are some drawbacks of this separation: >>>>>>>> - When creating a new module we will need to put the javascript in >>>>>>>> a separate location from the backend code >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> static/js/datagrid folder contains all the datagrid related >>>>>>>>>> functionality >>>>>>>>>> >>>>>>>>> Same as backup module, this should be in it's respective >>>>>>>>> static/js folder. >>>>>>>>> >>>>>>>>>> Inside of the folder we can see the files: >>>>>>>>>> get_panel_title.js is responsible for retrieving the name of the >>>>>>>>>> panel >>>>>>>>>> show_data.js is responsible for showing the datagrid >>>>>>>>>> show_query_tool.js is responsible for showing the query tool >>>>>>>>>> >>>>>>>>>> Does this structure make sense? >>>>>>>>>> Can you give an example of a comment that you think is missing >>>>>>>>>> and that could help? >>>>>>>>>> >>>>>>>>>> As a personal note, unless the algorithm is very obscure or very >>>>>>>>>> complicated, I believe that if the code needs comments it is a s= ignal that >>>>>>>>>> something needs to change in terms of naming, structure of the p= art in >>>>>>>>>> question. This being said, I am open to add some comments that m= ight help >>>>>>>>>> people. >>>>>>>>>> >>>>>>>>> You are right, with the help of naming convention and structure o= f >>>>>>>>> the code, any one can get the idea about the code. But it is very= useful to >>>>>>>>> understand the code >>>>>>>>> very easily with the proper comments especially when there are >>>>>>>>> multiple developers working on a single project. >>>>>>>>> >>>>>>>>> I found some of the places where it would be great to have >>>>>>>>> comments. >>>>>>>>> >>>>>>>>> - treeMenu: new tree.Tree() in a browser.js >>>>>>>>> - tree.js (especially Tree class) >>>>>>>>> >>>>>>>> About the comment point I need a more clear understanding on what >>>>>>>> kind of comments you are looking for. Because when you read the fu= nction >>>>>>>> names you understand the intent, what they are doing. The paramete= rs also >>>>>>>> explain what you need to pass into them. >>>>>>>> >>>>>>>> If what you are looking for in these comments is the reasoning >>>>>>>> being the change itself, then that should be present in the commit= message. >>>>>>>> Specially because this is going to be a very big patch with a very= big >>>>>>>> number of changes. >>>>>>>> >>>>>>>>> >>>>>>>>> Thanks >>>>>>>>>> Joao >>>>>>>>>> =E2=80=8B >>>>>>>>>> >>>>>>>>>> Thanks, >>>>>>>>> Khushboo >>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Fri, Apr 6, 2018 at 4:48 AM Murtuza Zabuawala < >>>>>>>>>> murtuza.zabuawala@enterprisedb.com> wrote: >>>>>>>>>> >>>>>>>>>>> Hi Joao, >>>>>>>>>>> >>>>>>>>>>> Patch looks good and working as expected. >>>>>>>>>>> >>>>>>>>>>> I also agree with Dave, Can we please add some comments in each >>>>>>>>>>> file which can help us to understand the flow, I'm saying becau= se now the >>>>>>>>>>> code is segregated in so many separate files it will be hard to= keep track >>>>>>>>>>> of the flow from one file to another when debugging. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Regards, >>>>>>>>>>> Murtuza Zabuawala >>>>>>>>>>> EnterpriseDB: http://www.enterprisedb.com >>>>>>>>>>> The Enterprise PostgreSQL Company >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Thu, Apr 5, 2018 at 7:08 PM, Joao De Almeida Pereira < >>>>>>>>>>> jdealmeidapereira@pivotal.io> wrote: >>>>>>>>>>> >>>>>>>>>>>> Hi Khushboo, >>>>>>>>>>>> Attached you can find both patches rebased >>>>>>>>>>>> >>>>>>>>>>>> Thanks >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Thu, Apr 5, 2018 at 6:31 AM Khushboo Vashi < >>>>>>>>>>>> khushboo.vashi@enterprisedb.com> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Hi Joao, >>>>>>>>>>>>> >>>>>>>>>>>>> Can you please rebase the second patch? >>>>>>>>>>>>> >>>>>>>>>>>>> Thanks, >>>>>>>>>>>>> Khushboo >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>>> On Tue, Apr 3, 2018 at 12:15 AM, Joao De Almeida Pereira < >>>>>>>>>>>>> jdealmeidapereira@pivotal.io> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> Hi Hackers, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Attached you can find the patch that will start to decouple >>>>>>>>>>>>>> pgAdmin from ACITree library. >>>>>>>>>>>>>> This patch is intended to be merged after 3.0, because we do >>>>>>>>>>>>>> not want to cause any entropy or delay the release, but we w= ant to start >>>>>>>>>>>>>> the discussion and show some code. >>>>>>>>>>>>>> >>>>>>>>>>>>>> This job that we started is a massive tech debt chore that >>>>>>>>>>>>>> will take some time to finalize and we would love the help o= f the community >>>>>>>>>>>>>> to do it. >>>>>>>>>>>>>> >>>>>>>>>>>>>> *Summary of the patch:* >>>>>>>>>>>>>> 0001 patch: >>>>>>>>>>>>>> - Creates a new tree that will allow us to create a >>>>>>>>>>>>>> separation between the application and ACI Tree >>>>>>>>>>>>>> - Creates a Fake Tree (Test double, for reference on the >>>>>>>>>>>>>> available test doubles: https://martinfowler. >>>>>>>>>>>>>> com/bliki/TestDouble.html) that can be used to inplace to >>>>>>>>>>>>>> replace the ACITree and also encapsulate the new tree behavi= or on our tests >>>>>>>>>>>>>> - Adds tests for all the tree functionalities >>>>>>>>>>>>>> >>>>>>>>>>>>>> 0002 patch: >>>>>>>>>>>>>> - Extracts, refactors, adds tests and remove dependency fro= m >>>>>>>>>>>>>> ACI Tree on: >>>>>>>>>>>>>> - getTreeNodeHierarchy >>>>>>>>>>>>>> - on backup.js: menu_enabled, menu_enabled_server, >>>>>>>>>>>>>> start_backup_global_server, backup_objects >>>>>>>>>>>>>> - on datagrid.js: show_data_grid, get_panel_title, >>>>>>>>>>>>>> show_query_tool >>>>>>>>>>>>>> - Start using sprintf-js as Underscore.String is deprecating >>>>>>>>>>>>>> sprintf function >>>>>>>>>>>>>> >>>>>>>>>>>>>> This patch represents only 10 calls to ACITree.itemData out >>>>>>>>>>>>>> of 176 that are spread around our code >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> *In Depth look on the process behind the patch:* >>>>>>>>>>>>>> >>>>>>>>>>>>>> We started writing this patch with the idea that we need to >>>>>>>>>>>>>> decouple pgAdmin4 from ACITree, because ACITree is no longer= supported, the >>>>>>>>>>>>>> documentation is non existent and ACITree is no longer being= actively >>>>>>>>>>>>>> developed. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Our process: >>>>>>>>>>>>>> 1. We "randomly" selected a function that is part of the >>>>>>>>>>>>>> ACITree. From this point we decided to replace that function= with our own >>>>>>>>>>>>>> version. The function that we choose was "itemData". >>>>>>>>>>>>>> The function gives us all the "data" that a specific node of >>>>>>>>>>>>>> the tree find. >>>>>>>>>>>>>> Given in order to replace the tree we would need to have a >>>>>>>>>>>>>> function that would give us the same information. We had 2 o= ptions: >>>>>>>>>>>>>> a) Create a tree with a function called itemData >>>>>>>>>>>>>> Pros: >>>>>>>>>>>>>> - At first view this was the simpler solution >>>>>>>>>>>>>> - Would keep the status quo >>>>>>>>>>>>>> Cons: >>>>>>>>>>>>>> - Not a OOP approach >>>>>>>>>>>>>> - Not very flexible >>>>>>>>>>>>>> b) Create a tree that would return a node given an ID and >>>>>>>>>>>>>> then the node would be responsible for giving it's data. >>>>>>>>>>>>>> Pros: >>>>>>>>>>>>>> - OOP Approach >>>>>>>>>>>>>> - More flexible and we do not need to bring the tree around= , >>>>>>>>>>>>>> just a node >>>>>>>>>>>>>> Cons: >>>>>>>>>>>>>> - Break the current status quo >>>>>>>>>>>>>> >>>>>>>>>>>>>> Given these 2 options we decided to go for a more OOP >>>>>>>>>>>>>> approach creating a Tree and a TreeNode classes, that in the= future will be >>>>>>>>>>>>>> renamed to ACITreeWrapper and TreeNode. >>>>>>>>>>>>>> >>>>>>>>>>>>>> 2. After we decided on the starting point we searched for >>>>>>>>>>>>>> occurrences of the function "itemData" and we found out that= there were 303 >>>>>>>>>>>>>> occurrences of "itemData" in the code and roughly 176 calls = to the function >>>>>>>>>>>>>> itself (some of the hits were variable names). >>>>>>>>>>>>>> >>>>>>>>>>>>>> 3. We selected the first file on the search and found the >>>>>>>>>>>>>> function that was responsible for calling the itemData funct= ion. >>>>>>>>>>>>>> >>>>>>>>>>>>>> 4. Extracted the function to a separate file >>>>>>>>>>>>>> >>>>>>>>>>>>>> 5. Wrap this function with tests >>>>>>>>>>>>>> >>>>>>>>>>>>>> 6. Refactor the function to ES6, give more declarative names >>>>>>>>>>>>>> to variables and break the functions into smaller chunks >>>>>>>>>>>>>> >>>>>>>>>>>>>> 7. When all the tests were passing we replaced ACITree with >>>>>>>>>>>>>> our Tree >>>>>>>>>>>>>> >>>>>>>>>>>>>> 8. We ensured that all tests were passing >>>>>>>>>>>>>> >>>>>>>>>>>>>> 9. Remove function from the original file and use the new >>>>>>>>>>>>>> function >>>>>>>>>>>>>> >>>>>>>>>>>>>> 10. Ensure everything still works >>>>>>>>>>>>>> >>>>>>>>>>>>>> 11. Find the next function and execute from step 4 until all >>>>>>>>>>>>>> the functions are replaced, refactored and tested. >>>>>>>>>>>>>> >>>>>>>>>>>>>> As you can see by the process this is a pretty huge >>>>>>>>>>>>>> undertake, because of the number of calls to the function. T= his is just the >>>>>>>>>>>>>> first step on the direction of completely isolating the ACIT= ree so that we >>>>>>>>>>>>>> can solve the problem with a large number of elements on the= tree. >>>>>>>>>>>>>> >>>>>>>>>>>>>> *What is on our radar that we need to address:* >>>>>>>>>>>>>> - Finish the complete decoupling of the ACITree >>>>>>>>>>>>>> - Performance of the current tree implementation >>>>>>>>>>>>>> - Tweak the naming of the Tree class to explicitly tell us >>>>>>>>>>>>>> this is to use only with ACITree. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Thanks >>>>>>>>>>>>>> Joao >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>> >>>>> >>>>> >>>>> -- >>>>> Dave Page >>>>> Blog: http://pgsnake.blogspot.com >>>>> Twitter: @pgsnake >>>>> >>>>> EnterpriseDB UK: http://www.enterprisedb.com >>>>> The Enterprise PostgreSQL Company >>>>> >>>> >>>> >>>> >>>> -- >>>> Dave Page >>>> Blog: http://pgsnake.blogspot.com >>>> Twitter: @pgsnake >>>> >>>> EnterpriseDB UK: http://www.enterprisedb.com >>>> The Enterprise PostgreSQL Company >>>> >>> > --000000000000c11f74056b122754 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable



On Mon, Apr 30, 2018 at 8:30 PM, Ashesh Vash= i <ashesh.vashi@enterprisedb.com> wrote:
On Sat, Apr 28, 2018 at 3:55 AM, Joao De Almeida Pe= reira <jdealmeidapereira@pivotal.io> wrote:
Hi Hackers,
As you a= re aware we kept on working on the patch, so we are attaching to this email= a new version of the patch.
This new version contains all the changes i= n the previous one plus more extractions of functions and refactoring of co= de.

The objective of this patch is to create a separation between pg= Admin and the ACI Tree. We are doing this because we realized that at this = point in time we have the ACI Tree all over the code of pgAdmin. I found a = very interesting article that really talks about this: https://medium.freecodecamp.org/code-dependencies-are-the-= devil-35ed28b556d

In this patch there are some visions and ideas about the lo= cation of the code, the way to organize it and also try to pave the future = for a application that is stable, easy to develop on and that can be releas= e at a times notice.

We are investing a big chunk= of our time in doing this refactoring, but while doing that we also try to= respond to the patches sent to the mailing list. We would like the feedbac= k from the community because we believe this is a changing point for the ap= plication. The idea is to change the way we develop this application, inste= ad of only correcting a bug of developing a feature, with every commit we s= hould correct the bug or develop a feature but leave the code a little bett= er than we found it (Refactoring, refactoring, refactoring). This is hard w= ork but that is what the users from pgAdmin expect from this community of d= evelopers.


=3D=3D=3D=3D=3D=3D
=



It is a huge patch
<= div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 86 files changed, 5492 inserts, 1840 deletions
and we would like to get your feedback as soon as possible, because = we are continuing to work on it which means it is going to grow in size.=C2= =A0


At this point in time we still = have 124 of 176 calls to the function itemData from ACITree.

What do= es each patch contain:
0001:
=C2=A0 Very simple patch, we fou= nd out that the linter was not looking into all the javascript test files, = so this patch will ensure it is
=
Committed the patch along with the regression introduced because of th= is patch.=C2=A0
<= div>

0002:
=C2=A0 New Tree abstraction. This patch co= ntains the new Tree that works as an adaptor for ACI Tree and is going to b= e used on all the extractions that we are doing.

I was expecting a separate layer between the = tree implementation, and aciTree adaptor.
Please find the patch f= or the example.

It will separate the two layers, a= nd easy to replace with the new implemenation in future.=C2=A0

Oops forgot to attach the p= atch.
Please find the patch attached.

--= Thanks, Ashesh=C2=A0
=

<= /div>
0003:
=C2=A0 Code that extracts, wrap with tests and re= place ACI Tree invocations.
There are many small cases left in the patches.
Hence - I would = like to know the TODO list created by you.

e.g. Wh= en we remove any of the object from the database server, we're not yet = removing the respective node from the new implementation, and its children.= =C2=A0
=C2=A0
=C2=A0 We start creating new pattern for = the location of Javascript files and their structure.
I would not like to see that changes in this pat= ch.
I would like us to come up with the actual design about the h= ot pluggability before going in this direction.=C2=A0
=C2=A0 Crea= te patterns for creation of dialogs (backup and restore)
<= /div>
It's better - we don't change the dir= ectory structure at the moment.

I am not against d= ividing the big javascript files in small chunks, but - I would like us to = discuss first about the hot plugins design first.

= -- Thanks, Ashesh=C2=A0
=C2=A0
=C2= =A0=C2=A0

Thanks
Joao
=


On Fri, = Apr 27, 2018 at 5:34 AM Ashesh Vashi <ashesh.vashi@enterprisedb.com>= wrote:
I have qu= ite a few comments for the patch.
I will send them soon.= =C2=A0

On Fri, A= pr 27, 2018, 14:45 Dave Page <dpage@pgadmin.org> wrote:
How is your work on this going Ashesh? Will you= be committing today?

On Wed, Apr 25, 2018 at 8:52 AM, Dave Page <= d= page@pgadmin.org> wrote:
Ashesh; you had agreed to work on this early this week. Plea= se ensure you do so today.

Thanks.

On Tue, Apr 24, 2018 at 8:13 PM, Joao De Almeida Pereira <jdealmeidapereira@pivotal.io> wrote:
Hi Hackers,

Can someone review and merge this patch?

Tha= nks
Joao

On Wed, Apr 18, 2018 a= t 10:23 AM Joao De Almeida Pereira <jdealmeidapereira@pivotal.= io> wrote:
= Hi Hackers,
Any other comment about this patch?

Thanks
Joao

On Tue, Apr 10, 2018 at 12:00 PM Joao De Alm= eida Pereira <jdealmeidapereira@pivotal.io> wrote:
<= /div>
Hello Khushboo

=
On Mon, Apr 9, 2018 at 1:59 AM Khushboo Vashi <= khushboo.vashi@enterprisedb.com> wrote:
<= /div>
Hi Joao,

I have reviewed your patch and = have some suggestions.

On Sat, Apr 7, 2018 at 12= :43 AM, Joao De Almeida Pereira <jdealmeidap= ereira@pivotal.io> wrote:

Hello Murtuza/Dave,
Yes = now the extracted functions are spread into different files. The intent wou= ld be to make the files as small as possible, and also to group and name th= em in a way that would be easy to understand what each file is doing withou= t the need of opening it.
As a example:
static/js/ba= ckup will contain all the backup related functionality inside of thi= s folder we can see the file:

menu_utils.js At this moment in time we decided to group all t= he functions that are related to the menu, but we can split that also if we= believe it is easier to see.

It's really very good to see the separated code for backup module. As = we have done for backup, we would like do it for other PG utilities like re= store, maintenance etc.
Considering this, we should separate the code i= n a way that some of the common functionalities can be used for other modul= es=C2=A0 like menu (as you have mentioned above), dialogue factory etc.
Also, I think these functionalities should be in their respective static f= older instead of pgadmin/static.
=

About the location of the fi= les. The move of the files to pgadmin/static/js was made on purpose in orde= r to clearly separate Javascript from python code.
The rational b= ehind it was
- Create a clear separation between the backend and = frontend
- Having Javascript code concentrated in a single place,= hopefully, will encourage to developers to look for a functionality, that = is already implemented in another modules, because they are right there. (W= hen we started this journey we realized that the 'nodes' have a big= groups of code that could be shared, but because the Javascript is spread = everywhere it is much harder to look for it)

<= br>
There are some drawbacks of this separation:
- When= creating a new module we will need to put the javascript in a separate loc= ation from the backend code=C2=A0=C2=A0
<= div class=3D"gmail_quote">
=C2=A0
<= div dir=3D"ltr">
= =C2=A0
<= div class=3D"gmail_quote">

static/js/datagrid folder contains all the datagrid related functionality

Same as backup module,=C2=A0 this should b= e in it's respective static/js folder.

Inside = of the folder we can see the files:
get_panel_title.js<= /code> is responsible for retrieving the name of the panel
show_data.js is responsible for showing the datagrid
show_query_tool.js is responsible for showing the query t= ool

Does this structure make sense?
Can yo= u give an example of a comment that you think is missing and that could hel= p?

As a personal note, unless the algorithm = is very obscure or very complicated, I believe that if the code needs comme= nts it is a signal that something needs to change in terms of naming, struc= ture of the part in question. This being said, I am open to add some commen= ts that might help people.

Y= ou are right, with the help of naming convention and structure of the code,= any one can get the idea about the code. But it is very useful to understa= nd the code=C2=A0
very easily with the proper comments especially= when there are multiple developers working on a single project.
=
I found some of the places where it would be great to have c= omments.

- treeMenu: new tree.Tree()=C2=A0 in a br= owser.js
- tree.js=C2=A0 (especially Tree class)
About the comment point I need a more clear understanding on what kin= d of comments you are looking for. Because when you read the function names= you understand the intent, what they are doing. The parameters also explai= n what you need to pass into them.

If what you are= looking for in these comments is the reasoning being the change itself, th= en that should be present in the commit message. Specially because this is = going to be a very big patch with a very big number of changes.
=

Thanks
Joao

=E2=80=8B

Thanks,
Khushboo=C2=A0
=
<= /div>

On Fri, Apr 6, 2018 at 4:48 AM Murtuza Zabuawala <murtuza.zabuawala@enterprisedb.com> wrote:
Hi Joao,

Patch looks g= ood and working as expected.

I also agree with Dave, Can we please add some co= mments in each file which can help us to understand the flow, I'm sayin= g because now the code is segregated in so many separate files it will be h= ard to keep track of the flow from one file to another when debugging.


<= div dir=3D"ltr">
--
Regards,
Murtuza Zabuawala
EnterpriseDB:=C2= =A0http://www.enterprisedb.com
The Enterprise Pos= tgreSQL Company


On Thu, Apr 5, 2018 at 7:08 PM, Joao De Alme= ida Pereira <jdealmeidapereira@pivotal.io> wrote:
Hi Khushboo,
Attached you can find both patches rebased<= /div>

Thanks


<= blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l= eft:1px solid rgb(204,204,204);padding-left:1ex">
Hi Joao,<= div>
Can you please rebase the second patch?

Thanks,
Khushboo


On Tue, Apr 3, 2018= at 12:15 AM, Joao De Almeida Pereira <jdeal= meidapereira@pivotal.io> wrote:
Hi Hackers,

Att= ached you can find the patch that will start to decouple pgAdmin from ACITr= ee library.
This patch is intended to be merged after 3.0, becaus= e we do not want to cause any entropy or delay the release, but we want to = start the discussion and show some code.

This job = that we started is a massive tech debt chore that will take some time to fi= nalize and we would love the help of the community to do it.

=
Summary of the patch:
0001 patch:=C2=A0
=C2=A0- Creates a new tree that will allow us to create a separation bet= ween the application and ACI Tree
=C2=A0- Creates a Fake Tree (Te= st double, for reference on the available test doubles:=C2=A0https://martinfowler.com/bliki/TestDouble.html) that can be= used to inplace to replace the ACITree and also encapsulate the new tree b= ehavior on our tests
=C2=A0- Adds tests for all the tree function= alities

0002 patch:
=C2=A0- Extracts, re= factors, adds tests and remove dependency from ACI Tree on:
- getTr= eeNodeHierarchy
- on backup.js: menu_enabled, menu_enabled_server, = start_backup_global_server, backup_objects
- on datagrid.js: show_da= ta_grid, get_panel_title, show_query_tool
- Start using sprintf-js as U= nderscore.String is deprecating sprintf function
=C2=A0=C2=A0
=
This patch represents only 10 calls to ACITree.itemData out of 176 tha= t are spread around our code


In Depth look on the process behind the patch:

=
We started writing this patch with the idea that we need to decouple p= gAdmin4 from ACITree, because ACITree is no longer supported, the documenta= tion is non existent and ACITree is no longer being actively developed.

Our process:
1. We "randomly" sel= ected a function that is part of the ACITree. From this point we decided to= replace that function with our own version. The function that we choose wa= s "itemData".
The function gives us all the "data&= quot; that a specific node of the tree find.
Given in order to re= place the tree we would need to have a function that would give us the same= information. We had 2 options:
=C2=A0 a) Create a tree with a fu= nction called itemData
Pros:
=C2=A0- At first view this= was the simpler solution
=C2=A0- Would keep the status quo
Cons:<= /div>
=C2=A0- Not a OOP approach
=C2=A0- Not very flexible
=C2=A0 b) Create a tree that would return a node given an ID and th= en the node would be responsible for giving it's data.
Pros:= =C2=A0
=C2=A0- OOP Approach
=C2=A0- More flexible and w= e do not need to bring the tree around, just a node
Cons:
=C2=A0- Break the current status quo

Given thes= e 2 options we decided to go for a more OOP approach creating a Tree and a = TreeNode classes, that in the future will be renamed to ACITreeWrapper and = TreeNode.

2. After we decided on the starting poin= t we searched for occurrences of the function "itemData" and we f= ound out that there were 303 occurrences of "itemData" in the cod= e and roughly 176 calls to the function itself (some of the hits were varia= ble names).

3. We selected the first file on the s= earch and found the function that was responsible for calling the itemData = function.

4. Extracted the function to a separate = file

5. Wrap this function with tests
6. Refactor the function to ES6, give more declarative names t= o variables and break the functions into smaller chunks

7. When all the tests were passing we replaced ACITree with our Tree<= /div>

8. We ensured that all tests were passing

9. Remove function from the original file and use the new = function

10. Ensure everything still works

11. Find the next function and execute from step 4 until = all the functions are replaced, refactored and tested.

=
As you can see by the process this is a pretty huge undertake, because= of the number of calls to the function. This is just the first step on the= direction of completely isolating the ACITree so that we can solve the pro= blem with a large number of elements on the tree.

= What is on our radar that we need to address:
=C2=A0- Fini= sh the complete decoupling of the ACITree
=C2=A0- Performance of = the current tree implementation
=C2=A0- Tweak the naming of the T= ree class to explicitly tell us this is to use only with ACITree.


Thanks
Joao






<= /div>--
Dave Page
Blog: http://pgsna= ke.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: h= ttp://www.enterprisedb.com
The Enterprise PostgreSQL Company



--
Dave Pa= ge
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

E= nterpriseDB UK: http://www.enterprisedb.com
The Enterprise Postgre= SQL Company


--000000000000c11f74056b122754-- --000000000000c11f78056b122756 Content-Type: application/octet-stream; name="0002-New-tree-implemenation.patch" Content-Disposition: attachment; filename="0002-New-tree-implemenation.patch" Content-Transfer-Encoding: base64 X-Attachment-Id: f_jgmdiab80 ZGlmZiAtLWdpdCBhL3dlYi9wZ2FkbWluL2Jyb3dzZXIvc3RhdGljL2pzL2Jyb3dzZXIuanMgYi93 ZWIvcGdhZG1pbi9icm93c2VyL3N0YXRpYy9qcy9icm93c2VyLmpzCmluZGV4IDg5N2QyNzAuLmZj NjgwODkgMTAwNjQ0Ci0tLSBhL3dlYi9wZ2FkbWluL2Jyb3dzZXIvc3RhdGljL2pzL2Jyb3dzZXIu anMKKysrIGIvd2ViL3BnYWRtaW4vYnJvd3Nlci9zdGF0aWMvanMvYnJvd3Nlci5qcwpAQCAtMSw0 ICsxLDUgQEAKIGRlZmluZSgncGdhZG1pbi5icm93c2VyJywgWworICAnc291cmNlcy90cmVlL3Ry ZWUnLAogICAnc291cmNlcy9nZXR0ZXh0JywgJ3NvdXJjZXMvdXJsX2ZvcicsICdyZXF1aXJlJywg J2pxdWVyeScsICd1bmRlcnNjb3JlJywgJ3VuZGVyc2NvcmUuc3RyaW5nJywKICAgJ2Jvb3RzdHJh cCcsICdzb3VyY2VzL3BnYWRtaW4nLCAncGdhZG1pbi5hbGVydGlmeWpzJywgJ2J1bmRsZWRfY29k ZW1pcnJvcicsCiAgICdzb3VyY2VzL2NoZWNrX25vZGVfdmlzaWJpbGl0eScsICdzb3VyY2VzL21v ZGlmeV9hbmltYXRpb24nLCAncGdhZG1pbi5icm93c2VyLnV0aWxzJywgJ3djZG9ja2VyJywKQEAg LTEwLDYgKzExLDcgQEAgZGVmaW5lKCdwZ2FkbWluLmJyb3dzZXInLCBbCiAgICdzb3VyY2VzL2Nv ZGVtaXJyb3IvYWRkb24vZm9sZC9wZ2FkbWluLXNxbGZvbGRjb2RlJywKICAgJ3BnYWRtaW4uYnJv d3Nlci5rZXlib2FyZCcsCiBdLCBmdW5jdGlvbigKKyAgdHJlZSwKICAgZ2V0dGV4dCwgdXJsX2Zv ciwgcmVxdWlyZSwgJCwgXywgUywgQm9vdHN0cmFwLCBwZ0FkbWluLCBBbGVydGlmeSwKICAgY29k ZW1pcnJvciwgY2hlY2tOb2RlVmlzaWJpbGl0eSwgbW9kaWZ5QW5pbWF0aW9uCiApIHsKQEAgLTg2 LDYgKzg4LDcgQEAgZGVmaW5lKCdwZ2FkbWluLmJyb3dzZXInLCBbCiAgICAgICB9KTsKIAogICAg ICAgYi50cmVlID0gJCgnI3RyZWUnKS5hY2lUcmVlKCdhcGknKTsKKyAgICAgIGIudHJlZU1lbnUu cmVnaXN0ZXIoJCgnI3RyZWUnKSk7CiAgICAgfTsKIAogICAvLyBFeHRlbmQgdGhlIGJyb3dzZXIg Y2xhc3MgYXR0cmlidXRlcwpAQCAtMTAwLDYgKzEwMyw3IEBAIGRlZmluZSgncGdhZG1pbi5icm93 c2VyJywgWwogICAgIGVkaXRvcjpudWxsLAogICAgIC8vIExlZnQgaGFuZCBicm93c2VyIHRyZWUK ICAgICB0cmVlOm51bGwsCisgICAgdHJlZU1lbnU6IG5ldyB0cmVlLlRyZWUoKSwKICAgICAvLyBs aXN0IG9mIHNjcmlwdCB0byBiZSBsb2FkZWQsIHdoZW4gYSBjZXJ0YWluIHR5cGUgb2Ygbm9kZSBp cyBsb2FkZWQKICAgICAvLyBJdCB3aWxsIGJlIHVzZWQgdG8gcmVnaXN0ZXIgZXh0ZW5zaW9ucywg dG9vbHMsIGNoaWxkIG5vZGUgc2NyaXB0cywKICAgICAvLyBldGMuCmRpZmYgLS1naXQgYS93ZWIv cGdhZG1pbi9zdGF0aWMvanMvdHJlZS90cmVlLmpzIGIvd2ViL3BnYWRtaW4vc3RhdGljL2pzL3Ry ZWUvdHJlZS5qcwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi44MDQ4NzcxCi0t LSAvZGV2L251bGwKKysrIGIvd2ViL3BnYWRtaW4vc3RhdGljL2pzL3RyZWUvdHJlZS5qcwpAQCAt MCwwICsxLDI3NSBAQAorLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KKy8vCisvLyBwZ0FkbWluIDQgLSBQb3N0 Z3JlU1FMIFRvb2xzCisvLworLy8gQ29weXJpZ2h0IChDKSAyMDEzIC0gMjAxOCwgVGhlIHBnQWRt aW4gRGV2ZWxvcG1lbnQgVGVhbQorLy8gVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciB0 aGUgUG9zdGdyZVNRTCBMaWNlbmNlCisvLworLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KKworCitjbGFzcyBC YXNlVHJlZU5vZGUgeworICBjb25zdHJ1Y3RvcihpZCwgZGF0YSwgZG9tTm9kZSwgcGFyZW50KSB7 CisgICAgdGhpcy5pZCA9IGlkOworICAgIHRoaXMuZGF0YSA9IGRhdGE7CisgICAgdGhpcy5zZXRQ YXJlbnQocGFyZW50KTsKKyAgICB0aGlzLmNoaWxkcmVuID0gW107CisgICAgdGhpcy5kb21Ob2Rl ID0gZG9tTm9kZTsKKyAgfQorCisgIGhhc1BhcmVudCgpIHsKKyAgICByZXR1cm4gaXNOb3ROdWxs T3JVbmRlZmluZWQodGhpcy5wYXJlbnROb2RlKTsKKyAgfQorCisgIHBhcmVudCgpIHsKKyAgICBy ZXR1cm4gdGhpcy5wYXJlbnROb2RlOworICB9CisKKyAgc2V0UGFyZW50KHBhcmVudCkgeworICAg IHRoaXMucGFyZW50Tm9kZSA9IHBhcmVudDsKKyAgICBpZiAoaXNOb3ROdWxsT3JVbmRlZmluZWQo cGFyZW50KSkgeworICAgICAgdGhpcy5wYXRoID0gdGhpcy5pZDsKKyAgICAgIGlmIChpc05vdE51 bGxPclVuZGVmaW5lZChwYXJlbnQpICYmIGlzTm90TnVsbE9yVW5kZWZpbmVkKHBhcmVudC5wYXRo KSkgeworICAgICAgICB0aGlzLnBhdGggPSBwYXJlbnQucGF0aCArICcuJyArIHRoaXMuaWQ7Cisg ICAgICB9CisgICAgfSBlbHNlIHsKKyAgICAgIHRoaXMucGF0aCA9IG51bGw7CisgICAgfQorICB9 CisKKyAgZ2V0RGF0YSgpIHsKKyAgICBpZiAodGhpcy5kYXRhID09PSB1bmRlZmluZWQpIHsKKyAg ICAgIHJldHVybiB1bmRlZmluZWQ7CisgICAgfSBlbHNlIGlmICh0aGlzLmRhdGEgPT09IG51bGwp IHsKKyAgICAgIHJldHVybiBudWxsOworICAgIH0KKyAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7 fSwgdGhpcy5kYXRhKTsKKyAgfQorCisgIGdldEh0bWxJZGVudGlmaWVyKCkgeworICAgIHJldHVy biB0aGlzLmRvbU5vZGU7CisgIH0KKworICByZWxvYWQodHJlZSkgeworICAgIC8vIEltcGxlbWVu dCBpdCBpbiB0aGUgYWN0dWFsIGltcGxlbWVudGF0aW9uCisgICAgLy8gVGhpcyBpcyBtb3JlIG9m IGEgc2hlbGwgb2JqZWN0LgorICAgIHRocm93ICdOb3QgSW1wbGVtZW50ZWQnLCB0cmVlOworICB9 CisKKyAgdW5sb2FkKHRyZWUpIHsKKyAgICB0aGlzLmNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24o Y2hpbGQpIHsKKyAgICAgIGNoaWxkLnVubG9hZCh0cmVlKTsKKyAgICAgIGNoaWxkLnNldFBhcmVu dChudWxsKTsKKyAgICB9KTsKKyAgICB0aGlzLmNoaWxkcmVuID0gW107CisgIH0KKworICBhbnlQ YXJlbnQoY29uZGl0aW9uKSB7CisgICAgbGV0IG5vZGUgPSB0aGlzOworCisgICAgd2hpbGUgKG5v ZGUuaGFzUGFyZW50KCkpIHsKKyAgICAgIG5vZGUgPSBub2RlLnBhcmVudCgpOworICAgICAgaWYg KGNvbmRpdGlvbihub2RlKSkgeworICAgICAgICByZXR1cm4gdHJ1ZTsKKyAgICAgIH0KKyAgICB9 CisKKyAgICByZXR1cm4gZmFsc2U7CisgIH0KKworICBhbnlGYW1pbHlNZW1iZXIoY29uZGl0aW9u KSB7CisgICAgaWYoY29uZGl0aW9uKHRoaXMpKSB7CisgICAgICByZXR1cm4gdHJ1ZTsKKyAgICB9 CisKKyAgICByZXR1cm4gdGhpcy5hbnlQYXJlbnQoY29uZGl0aW9uKTsKKyAgfQorfQorCisKK2Ns YXNzIEJhc2VUcmVlIHsKKyAgY29uc3RydWN0b3IoKSB7CisgICAgdGhpcy5yb290Tm9kZSA9IHRo aXMuX2NyZWF0ZU5ld1RyZWVOb2RlKHVuZGVmaW5lZCwge30pOworICB9CisKKyAgYWRkTmV3Tm9k ZShpZCwgZGF0YSwgZG9tTm9kZSwgcGFyZW50UGF0aCkgeworICAgIGNvbnN0IHBhcmVudCA9IHRo aXMuZmluZE5vZGUocGFyZW50UGF0aCk7CisgICAgcmV0dXJuIHRoaXMuY3JlYXRlT3JVcGRhdGVO b2RlKGlkLCBkYXRhLCBwYXJlbnQsIGRvbU5vZGUpOworICB9CisKKyAgZmluZE5vZGUocGF0aCkg eworICAgIGlmIChwYXRoID09PSBudWxsIHx8IHBhdGggPT09IHVuZGVmaW5lZCB8fCBwYXRoLmxl bmd0aCA9PT0gMCkgeworICAgICAgcmV0dXJuIHRoaXMucm9vdE5vZGU7CisgICAgfQorICAgIHJl dHVybiBmaW5kSW5UcmVlKHRoaXMucm9vdE5vZGUsIHBhdGguam9pbignLicpKTsKKyAgfQorCisg IGZpbmROb2RlQnlEb21FbGVtZW50KC8qIGRvbUVsZW1lbnQgKi8pIHsKKyAgICAvLyBUT0RPOjoK KyAgICAvLyBUaGluayB0aHJvdWdoIHRoZSBuZXcgaW1wbGVtZW50YXRpb24gLSBIb3cgaXMgaXQg Z29pbmcgdG8gd29yayB3aXRoIHJlYWwKKyAgICAvLyBkb21FbGVtZW50PworICAgIC8vCisgICAg Ly8gTk9URTogV2UgYWxyZWFkeSBoYXZlIGltcGxlbWVudGF0aW9uIGZvciB0aGUgYWNpVHJlZS4K KyAgICB0aHJvdyAnTm90IEltcGxlbWVudGVkJzsKKyAgfQorCisgIHNlbGVjdGVkKCkgeworICAg IHRocm93ICdOb3QgSW1wbGVtZW50ZWQnOworICB9CisKKyAgc2VsZWN0Tm9kZSgvKiBub2RlICov KSB7CisgICAgdGhyb3cgJ05vdCBJbXBsZW1lbnRlZCc7CisgIH0KKworICByZWdpc3RlcigvKiAk dHJlZUpRdWVyeSAqLykgeworICAgIHRocm93ICdOb3QgSW1wbGVtZW50ZWQnOworICB9CisKKyAg X2NyZWF0ZU5ld1RyZWVOb2RlKC8qIGlkLCBkYXRhLCBkb21Ob2RlLCBwYXJlbnQgKi8pIHsKKyAg ICB0aHJvdyAnTm90IEltcGxlbWVudGVkJzsKKyAgfQorCisgIGNyZWF0ZU9yVXBkYXRlTm9kZShp ZCwgZGF0YSwgcGFyZW50LCBkb21Ob2RlKSB7CisgICAgbGV0IG9sZE5vZGVQYXRoID0gW2lkXTsK KyAgICBpZihwYXJlbnQgIT09IG51bGwgJiYgcGFyZW50ICE9PSB1bmRlZmluZWQpIHsKKyAgICAg IG9sZE5vZGVQYXRoID0gW3BhcmVudC5wYXRoLCBpZF07CisgICAgfQorICAgIGNvbnN0IG9sZE5v ZGUgPSB0aGlzLmZpbmROb2RlKG9sZE5vZGVQYXRoKTsKKyAgICBpZiAob2xkTm9kZSAhPT0gbnVs bCkgeworICAgICAgb2xkTm9kZS5kYXRhID0gT2JqZWN0LmFzc2lnbih7fSwgZGF0YSk7CisgICAg ICByZXR1cm4gb2xkTm9kZTsKKyAgICB9CisKKyAgICBjb25zdCBub2RlID0gdGhpcy5fY3JlYXRl TmV3VHJlZU5vZGUoaWQsIGRhdGEsIGRvbU5vZGUsIHBhcmVudCk7CisgICAgaWYgKHBhcmVudCA9 PT0gdGhpcy5yb290Tm9kZSkgeworICAgICAgbm9kZS5wYXJlbnROb2RlID0gbnVsbDsKKyAgICB9 CisgICAgaWYgKGlzTm90TnVsbE9yVW5kZWZpbmVkKHBhcmVudCkpIHsKKyAgICAgIHBhcmVudC5j aGlsZHJlbi5wdXNoKG5vZGUpOworICAgIH0KKyAgICByZXR1cm4gbm9kZTsKKyAgfQorfQorCisK K2Z1bmN0aW9uIGZpbmRJblRyZWUocm9vdE5vZGUsIHBhdGgpIHsKKyAgaWYgKHBhdGggPT09IG51 bGwpIHsKKyAgICByZXR1cm4gcm9vdE5vZGU7CisgIH0KKyAgcmV0dXJuIChmdW5jdGlvbiBmaW5k SW5Ob2RlKGN1cnJlbnROb2RlKSB7CisgICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGN1cnJl bnROb2RlLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CisgICAgICBjb25zdCBj YWxjdWxhdGVkTm9kZSA9IGZpbmRJbk5vZGUoY3VycmVudE5vZGUuY2hpbGRyZW5baV0pOworICAg ICAgaWYgKGNhbGN1bGF0ZWROb2RlICE9PSBudWxsKSB7CisgICAgICAgIHJldHVybiBjYWxjdWxh dGVkTm9kZTsKKyAgICAgIH0KKyAgICB9CisKKyAgICBpZiAoY3VycmVudE5vZGUucGF0aCA9PT0g cGF0aCkgeworICAgICAgcmV0dXJuIGN1cnJlbnROb2RlOworICAgIH0gZWxzZSB7CisgICAgICBy ZXR1cm4gbnVsbDsKKyAgICB9CisgIH0pKHJvb3ROb2RlKTsKK30KKworCitjbGFzcyBBQ0lUcmVl Tm9kZSBleHRlbmRzIEJhc2VUcmVlTm9kZSB7CisgIGNvbnN0cnVjdG9yKGlkLCBkYXRhLCBkb21O b2RlLCBwYXJlbnQpIHsKKyAgICBzdXBlcihpZCwgZGF0YSwgZG9tTm9kZSwgcGFyZW50KTsKKyAg fQorCisgIHJlbG9hZCh0cmVlKSB7CisgICAgdGhpcy51bmxvYWQodHJlZSk7CisgICAgdHJlZS5h Y2lUcmVlQXBpLnNldElub2RlKHRoaXMuZG9tTm9kZSk7CisgICAgdHJlZS5hY2lUcmVlQXBpLmRl c2VsZWN0KHRoaXMuZG9tTm9kZSk7CisKKyAgICBzZXRUaW1lb3V0KCgpID0+IHsKKyAgICAgIHRy ZWUuc2VsZWN0Tm9kZSh0aGlzLmRvbU5vZGUpOworICAgIH0sIDApOworICB9CisKKyAgdW5sb2Fk KHRyZWUpIHsKKyAgICAvLyBEbyBub3QgcGFzcyBvbiB0cmVlIG9iamVjdCB0byAnc3VwZXInIG9i amVjdCB0byBhdm9pZCB1bmxvYWRpbmcgdGhlCisgICAgLy8gY2hpbGRyZW4gcmVjdXJzaXZlbHkg Zm9yIHBlcmZvcm1hbmNlIHJlYXNvbi4KKyAgICAvLworICAgIC8vIEFueSB3YXkgLSB1bmxvYWRp bmcgdXNpbmcgJ2FjaVRyZWVBcGkudW5sb2FkKC4uLiknIHdpbGwgYW55IHdheSB1bmxvYWQKKyAg ICAvLyBhbGwgY2hpbGRyZW4uCisgICAgc3VwZXIudW5sb2FkKG51bGwpOworCisgICAgaWYgKGlz Tm90TnVsbE9yVW5kZWZpbmVkKHRyZWUpICYmIGlzTm90TnVsbE9yVW5kZWZpbmVkKHRyZWUuYWNp VHJlZUFwaSkpIHsKKyAgICAgIHRyZWUuYWNpVHJlZUFwaS51bmxvYWQodGhpcy5kb21Ob2RlKTsK KyAgICB9IGVsc2UgeworICAgICAgdGhpcy5kb21Ob2RlID0gbnVsbDsKKyAgICB9CisgIH0KK30K KworCitmdW5jdGlvbiBpc05vdE51bGxPclVuZGVmaW5lZCh2YWwpIHsKKyAgcmV0dXJuICh2YWwg IT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IG51bGwpOworfQorCisKKworY2xhc3MgQUNJVHJlZSBl eHRlbmRzIEJhc2VUcmVlIHsKKyAgY29uc3RydWN0b3IoKSB7CisgICAgc3VwZXIoYXJndW1lbnRz KTsKKyAgICB0aGlzLmFjaVRyZWVBcGkgPSBudWxsOworICB9CisKKyAgX2NyZWF0ZU5ld1RyZWVO b2RlKGlkLCBkYXRhLCBkb21Ob2RlLCBwYXJlbnQpIHsKKyAgICBsZXQgbm9kZSA9IG5ldyBBQ0lU cmVlTm9kZShpZCwgZGF0YSwgZG9tTm9kZSwgcGFyZW50KTsKKyAgICByZXR1cm4gbm9kZTsKKyAg fQorCisgIGZpbmROb2RlQnlEb21FbGVtZW50KGRvbUVsZW1lbnQpIHsKKyAgICBjb25zdCBwYXRo ID0gdGhpcy50cmFuc2xhdGVUcmVlTm9kZUlkRnJvbUFDSVRyZWUoZG9tRWxlbWVudCk7CisgICAg aWYoIXBhdGggfHwgIXBhdGhbMF0pIHsKKyAgICAgIHJldHVybiB1bmRlZmluZWQ7CisgICAgfQor CisgICAgcmV0dXJuIHRoaXMuZmluZE5vZGUocGF0aCk7CisgIH0KKworICBzZWxlY3RlZCgpIHsK KyAgICByZXR1cm4gdGhpcy5hY2lUcmVlQXBpLnNlbGVjdGVkKCk7CisgIH0KKworICBzZWxlY3RO b2RlKGFjaVRyZWVJZGVudGlmaWVyKSB7CisgICAgdGhpcy5hY2lUcmVlQXBpLnNlbGVjdChhY2lU cmVlSWRlbnRpZmllcik7CisgIH0KKworICByZWdpc3RlcigkdHJlZUpRdWVyeSkgeworICAgICR0 cmVlSlF1ZXJ5Lm9uKCdhY2l0cmVlJywgZnVuY3Rpb24gKGV2ZW50LCBhcGksIGl0ZW0sIGV2ZW50 TmFtZSkgeworICAgICAgaWYgKGFwaS5pc0l0ZW0oaXRlbSkpIHsKKyAgICAgICAgaWYgKGV2ZW50 TmFtZSA9PT0gJ2FkZGVkJykgeworICAgICAgICAgIGNvbnN0IGlkID0gYXBpLmdldElkKGl0ZW0p OworICAgICAgICAgIGNvbnN0IGRhdGEgPSBhcGkuaXRlbURhdGEoaXRlbSk7CisgICAgICAgICAg Y29uc3QgcGFyZW50SWQgPSB0aGlzLnRyYW5zbGF0ZVRyZWVOb2RlSWRGcm9tQUNJVHJlZShhcGku cGFyZW50KGl0ZW0pKTsKKyAgICAgICAgICB0aGlzLmFkZE5ld05vZGUoaWQsIGRhdGEsIGl0ZW0s IHBhcmVudElkKTsKKyAgICAgICAgfQorICAgICAgfQorICAgIH0uYmluZCh0aGlzKSk7CisgICAg dGhpcy5hY2lUcmVlQXBpID0gJHRyZWVKUXVlcnkuYWNpVHJlZSgnYXBpJyk7CisgIH0KKworICB0 cmFuc2xhdGVUcmVlTm9kZUlkRnJvbUFDSVRyZWUoYWNpVHJlZU5vZGUpIHsKKyAgICBsZXQgY3Vy cmVudFRyZWVOb2RlID0gYWNpVHJlZU5vZGU7CisgICAgbGV0IHBhdGggPSBbXTsKKyAgICB3aGls ZSAoY3VycmVudFRyZWVOb2RlICE9PSBudWxsICYmIGN1cnJlbnRUcmVlTm9kZSAhPT0gdW5kZWZp bmVkICYmIGN1cnJlbnRUcmVlTm9kZS5sZW5ndGggPiAwKSB7CisgICAgICBwYXRoLnVuc2hpZnQo dGhpcy5hY2lUcmVlQXBpLmdldElkKGN1cnJlbnRUcmVlTm9kZSkpOworICAgICAgaWYgKHRoaXMu YWNpVHJlZUFwaS5oYXNQYXJlbnQoY3VycmVudFRyZWVOb2RlKSkgeworICAgICAgICBjdXJyZW50 VHJlZU5vZGUgPSB0aGlzLmFjaVRyZWVBcGkucGFyZW50KGN1cnJlbnRUcmVlTm9kZSk7CisgICAg ICB9IGVsc2UgeworICAgICAgICBicmVhazsKKyAgICAgIH0KKyAgICB9CisgICAgcmV0dXJuIHBh dGg7CisgIH0KKworICBzdGF0aWMgdGVzdCgpIHsKKyAgICByZXR1cm4gJ0FDSVRyZWUnOworICB9 Cit9CisKK2V4cG9ydCB7IEFDSVRyZWUgYXMgVHJlZSwgQUNJVHJlZU5vZGUgYXMgVHJlZU5vZGUg fTsKZGlmZiAtLWdpdCBhL3dlYi9yZWdyZXNzaW9uL2phdmFzY3JpcHQvdHJlZS90cmVlX2Zha2Uu anMgYi93ZWIvcmVncmVzc2lvbi9qYXZhc2NyaXB0L3RyZWUvdHJlZV9mYWtlLmpzCm5ldyBmaWxl IG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmIyODVhNDUKLS0tIC9kZXYvbnVsbAorKysgYi93 ZWIvcmVncmVzc2lvbi9qYXZhc2NyaXB0L3RyZWUvdHJlZV9mYWtlLmpzCkBAIC0wLDAgKzEsNjkg QEAKKy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8KKy8vCisvLyBwZ0FkbWluIDQgLSBQb3N0Z3JlU1FMIFRvb2xzCisvLworLy8gQ29w eXJpZ2h0IChDKSAyMDEzIC0gMjAxOCwgVGhlIHBnQWRtaW4gRGV2ZWxvcG1lbnQgVGVhbQorLy8g VGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciB0aGUgUG9zdGdyZVNRTCBMaWNlbmNlCisv LworLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8KKworaW1wb3J0IHtUcmVlfSBmcm9tICcuLi8uLi8uLi9wZ2FkbWluL3N0YXRpYy9q cy90cmVlL3RyZWUnOworCitleHBvcnQgY2xhc3MgVHJlZUZha2UgZXh0ZW5kcyBUcmVlIHsKKyAg Y29uc3RydWN0b3IoKSB7CisgICAgc3VwZXIoKTsKKyAgICB0aGlzLmFjaVRyZWVUb091clRyZWVU cmFuc2xhdG9yID0ge307CisgICAgdGhpcy5hY2lUcmVlQXBpID0gamFzbWluZS5jcmVhdGVTcHlP YmooCisgICAgICBbJ0FDSVRyZWVBcGknXSwgWydzZXRJbm9kZScsICd1bmxvYWQnLCAnZGVzZWxl Y3QnLCAnc2VsZWN0J10pOworICB9CisKKyAgYWRkTmV3Tm9kZShpZCwgZGF0YSwgZG9tTm9kZSwg cGF0aCkgeworICAgIHRoaXMuYWNpVHJlZVRvT3VyVHJlZVRyYW5zbGF0b3JbaWRdID0gW2lkXTsK KyAgICBpZiAocGF0aCAhPT0gbnVsbCAmJiBwYXRoICE9PSB1bmRlZmluZWQpIHsKKyAgICAgIHRo aXMuYWNpVHJlZVRvT3VyVHJlZVRyYW5zbGF0b3JbaWRdID0gcGF0aC5jb25jYXQoaWQpOworICAg IH0KKyAgICByZXR1cm4gc3VwZXIuYWRkTmV3Tm9kZShpZCwgZGF0YSwgZG9tTm9kZSwgcGF0aCk7 CisgIH0KKworICBhZGRDaGlsZChwYXJlbnQsIGNoaWxkKSB7CisgICAgY2hpbGQuc2V0UGFyZW50 KHBhcmVudCk7CisgICAgdGhpcy5hY2lUcmVlVG9PdXJUcmVlVHJhbnNsYXRvcltjaGlsZC5pZF0g PSB0aGlzLmFjaVRyZWVUb091clRyZWVUcmFuc2xhdG9yW3BhcmVudC5pZF0uY29uY2F0KGNoaWxk LmlkKTsKKyAgICBwYXJlbnQuY2hpbGRyZW4ucHVzaChjaGlsZCk7CisgIH0KKworICBoYXNQYXJl bnQoYWNpVHJlZU5vZGUpIHsKKyAgICByZXR1cm4gdGhpcy50cmFuc2xhdGVUcmVlTm9kZUlkRnJv bUFDSVRyZWUoYWNpVHJlZU5vZGUpLmxlbmd0aCA+IDE7CisgIH0KKworICBwYXJlbnQoYWNpVHJl ZU5vZGUpIHsKKyAgICBpZiAodGhpcy5oYXNQYXJlbnQoYWNpVHJlZU5vZGUpKSB7CisgICAgICBs ZXQgcGF0aCA9IHRoaXMudHJhbnNsYXRlVHJlZU5vZGVJZEZyb21BQ0lUcmVlKGFjaVRyZWVOb2Rl KTsKKyAgICAgIHJldHVybiBbe2lkOiB0aGlzLmZpbmROb2RlKHBhdGgpLnBhcmVudCgpLmlkfV07 CisgICAgfQorCisgICAgcmV0dXJuIG51bGw7CisgIH0KKworICB0cmFuc2xhdGVUcmVlTm9kZUlk RnJvbUFDSVRyZWUoYWNpVHJlZU5vZGUpIHsKKyAgICBpZihhY2lUcmVlTm9kZSA9PT0gdW5kZWZp bmVkIHx8IGFjaVRyZWVOb2RlWzBdID09PSB1bmRlZmluZWQpIHsKKyAgICAgIHJldHVybiBudWxs OworICAgIH0KKyAgICByZXR1cm4gdGhpcy5hY2lUcmVlVG9PdXJUcmVlVHJhbnNsYXRvclthY2lU cmVlTm9kZVswXS5pZF07CisgIH0KKworICBpdGVtRGF0YShhY2lUcmVlTm9kZSkgeworICAgIGxl dCBub2RlID0gdGhpcy5maW5kTm9kZUJ5RG9tRWxlbWVudChhY2lUcmVlTm9kZSk7CisgICAgaWYg KG5vZGUgPT09IHVuZGVmaW5lZCB8fCBub2RlID09PSBudWxsKSB7CisgICAgICByZXR1cm4gdW5k ZWZpbmVkOworICAgIH0KKyAgICByZXR1cm4gbm9kZS5nZXREYXRhKCk7CisgIH0KKworICBzZWxl Y3RlZCgpIHsKKyAgICByZXR1cm4gdGhpcy5zZWxlY3RlZE5vZGU7CisgIH0KKworICBzZWxlY3RO b2RlKHNlbGVjdGVkTm9kZSkgeworICAgIHRoaXMuc2VsZWN0ZWROb2RlID0gc2VsZWN0ZWROb2Rl OworICB9Cit9CmRpZmYgLS1naXQgYS93ZWIvcmVncmVzc2lvbi9qYXZhc2NyaXB0L3RyZWUvdHJl ZV9zcGVjLmpzIGIvd2ViL3JlZ3Jlc3Npb24vamF2YXNjcmlwdC90cmVlL3RyZWVfc3BlYy5qcwpu ZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi4xNjRjZWI1Ci0tLSAvZGV2L251bGwK KysrIGIvd2ViL3JlZ3Jlc3Npb24vamF2YXNjcmlwdC90cmVlL3RyZWVfc3BlYy5qcwpAQCAtMCww ICsxLDQyMSBAQAorLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KKy8vCisvLyBwZ0FkbWluIDQgLSBQb3N0Z3Jl U1FMIFRvb2xzCisvLworLy8gQ29weXJpZ2h0IChDKSAyMDEzIC0gMjAxOCwgVGhlIHBnQWRtaW4g RGV2ZWxvcG1lbnQgVGVhbQorLy8gVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciB0aGUg UG9zdGdyZVNRTCBMaWNlbmNlCisvLworLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KKworaW1wb3J0IHtUcmVl LCBUcmVlTm9kZX0gZnJvbSAnLi4vLi4vLi4vcGdhZG1pbi9zdGF0aWMvanMvdHJlZS90cmVlJzsK K2ltcG9ydCB7VHJlZUZha2V9IGZyb20gJy4vdHJlZV9mYWtlJzsKKworY29uc3QgY29udGV4dCA9 IGRlc2NyaWJlOworCitjb25zdCB0cmVlVGVzdHMgPSAodHJlZUNsYXNzLCBzZXREZWZhdWx0Q2Fs bEJhY2spID0+IHsKKyAgbGV0IHRyZWU7CisgIGJlZm9yZUVhY2goKCkgPT4geworICAgIHRyZWUg PSBuZXcgdHJlZUNsYXNzKCk7CisgIH0pOworCisgIGRlc2NyaWJlKCcjYWRkTmV3Tm9kZScsICgp ID0+IHsKKyAgICBkZXNjcmliZSgnd2hlbiBhZGQgYSBuZXcgcm9vdCBlbGVtZW50JywgKCkgPT4g eworICAgICAgY29udGV4dCgndXNpbmcgW10gYXMgdGhlIHBhcmVudCcsICgpID0+IHsKKyAgICAg ICAgYmVmb3JlRWFjaCgoKSA9PiB7CisgICAgICAgICAgdHJlZS5hZGROZXdOb2RlKCdzb21lIG5l dyBub2RlJywge2RhdGE6ICdpbnRlcmVzdGluZyd9LCB1bmRlZmluZWQsIFtdKTsKKyAgICAgICAg fSk7CisKKyAgICAgICAgaXQoJ2NhbiBiZSByZXRyaWV2ZWQnLCAoKSA9PiB7CisgICAgICAgICAg Y29uc3Qgbm9kZSA9IHRyZWUuZmluZE5vZGUoWydzb21lIG5ldyBub2RlJ10pOworICAgICAgICAg IGV4cGVjdChub2RlLmRhdGEpLnRvRXF1YWwoe2RhdGE6ICdpbnRlcmVzdGluZyd9KTsKKyAgICAg ICAgfSk7CisKKyAgICAgICAgaXQoJ3JldHVybiBmYWxzZSBmb3IgI2hhc1BhcmVudCgpJywgKCkg PT4geworICAgICAgICAgIGNvbnN0IG5vZGUgPSB0cmVlLmZpbmROb2RlKFsnc29tZSBuZXcgbm9k ZSddKTsKKyAgICAgICAgICBleHBlY3Qobm9kZS5oYXNQYXJlbnQoKSkudG9CZShmYWxzZSk7Cisg ICAgICAgIH0pOworCisgICAgICAgIGl0KCdyZXR1cm4gbnVsbCBmb3IgI3BhcmVudCgpJywgKCkg PT4geworICAgICAgICAgIGNvbnN0IG5vZGUgPSB0cmVlLmZpbmROb2RlKFsnc29tZSBuZXcgbm9k ZSddKTsKKyAgICAgICAgICBleHBlY3Qobm9kZS5wYXJlbnQoKSkudG9CZU51bGwoKTsKKyAgICAg ICAgfSk7CisgICAgICB9KTsKKworICAgICAgY29udGV4dCgndXNpbmcgbnVsbCBhcyB0aGUgcGFy ZW50JywgKCkgPT4geworICAgICAgICBiZWZvcmVFYWNoKCgpID0+IHsKKyAgICAgICAgICB0cmVl LmFkZE5ld05vZGUoJ3NvbWUgbmV3IG5vZGUnLCB7ZGF0YTogJ2ludGVyZXN0aW5nJ30sIHVuZGVm aW5lZCwgbnVsbCk7CisgICAgICAgIH0pOworCisgICAgICAgIGl0KCdjYW4gYmUgcmV0cmlldmVk JywgKCkgPT4geworICAgICAgICAgIGNvbnN0IG5vZGUgPSB0cmVlLmZpbmROb2RlKFsnc29tZSBu ZXcgbm9kZSddKTsKKyAgICAgICAgICBleHBlY3Qobm9kZS5kYXRhKS50b0VxdWFsKHtkYXRhOiAn aW50ZXJlc3RpbmcnfSk7CisgICAgICAgIH0pOworCisgICAgICAgIGl0KCdyZXR1cm4gZmFsc2Ug Zm9yICNoYXNQYXJlbnQoKScsICgpID0+IHsKKyAgICAgICAgICBjb25zdCBub2RlID0gdHJlZS5m aW5kTm9kZShbJ3NvbWUgbmV3IG5vZGUnXSk7CisgICAgICAgICAgZXhwZWN0KG5vZGUuaGFzUGFy ZW50KCkpLnRvQmUoZmFsc2UpOworICAgICAgICB9KTsKKworICAgICAgICBpdCgncmV0dXJuIG51 bGwgZm9yICNwYXJlbnQoKScsICgpID0+IHsKKyAgICAgICAgICBjb25zdCBub2RlID0gdHJlZS5m aW5kTm9kZShbJ3NvbWUgbmV3IG5vZGUnXSk7CisgICAgICAgICAgZXhwZWN0KG5vZGUucGFyZW50 KCkpLnRvQmVOdWxsKCk7CisgICAgICAgIH0pOworICAgICAgfSk7CisKKyAgICAgIGNvbnRleHQo J3VzaW5nIHVuZGVmaW5lZCBhcyB0aGUgcGFyZW50JywgKCkgPT4geworICAgICAgICBiZWZvcmVF YWNoKCgpID0+IHsKKyAgICAgICAgICB0cmVlLmFkZE5ld05vZGUoJ3NvbWUgbmV3IG5vZGUnLCB7 ZGF0YTogJ2ludGVyZXN0aW5nJ30pOworICAgICAgICB9KTsKKworICAgICAgICBpdCgnY2FuIGJl IHJldHJpZXZlZCcsICgpID0+IHsKKyAgICAgICAgICBjb25zdCBub2RlID0gdHJlZS5maW5kTm9k ZShbJ3NvbWUgbmV3IG5vZGUnXSk7CisgICAgICAgICAgZXhwZWN0KG5vZGUuZGF0YSkudG9FcXVh bCh7ZGF0YTogJ2ludGVyZXN0aW5nJ30pOworICAgICAgICB9KTsKKworICAgICAgICBpdCgncmV0 dXJuIGZhbHNlIGZvciAjaGFzUGFyZW50KCknLCAoKSA9PiB7CisgICAgICAgICAgY29uc3Qgbm9k ZSA9IHRyZWUuZmluZE5vZGUoWydzb21lIG5ldyBub2RlJ10pOworICAgICAgICAgIGV4cGVjdChu b2RlLmhhc1BhcmVudCgpKS50b0JlKGZhbHNlKTsKKyAgICAgICAgfSk7CisKKyAgICAgICAgaXQo J3JldHVybiBudWxsIGZvciAjcGFyZW50KCknLCAoKSA9PiB7CisgICAgICAgICAgY29uc3Qgbm9k ZSA9IHRyZWUuZmluZE5vZGUoWydzb21lIG5ldyBub2RlJ10pOworICAgICAgICAgIGV4cGVjdChu b2RlLnBhcmVudCgpKS50b0JlTnVsbCgpOworICAgICAgICB9KTsKKyAgICAgIH0pOworICAgIH0p OworCisgICAgZGVzY3JpYmUoJ3doZW4gYWRkIGEgbmV3IGVsZW1lbnQgYXMgYSBjaGlsZCcsICgp ID0+IHsKKyAgICAgIGxldCBwYXJlbnROb2RlOworICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7Cisg ICAgICAgIHBhcmVudE5vZGUgPSB0cmVlLmFkZE5ld05vZGUoJ3BhcmVudCBub2RlJywge2RhdGE6 ICdwYXJlbnQgZGF0YSd9LCB1bmRlZmluZWQsIFtdKTsKKyAgICAgICAgdHJlZS5hZGROZXdOb2Rl KCdzb21lIG5ldyBub2RlJywge2RhdGE6ICdpbnRlcmVzdGluZyd9LCB1bmRlZmluZWQsIFsncGFy ZW50JyArCisgICAgICAgICcgbm9kZSddKTsKKyAgICAgIH0pOworCisgICAgICBpdCgnY2FuIGJl IHJldHJpZXZlZCcsICgpID0+IHsKKyAgICAgICAgY29uc3Qgbm9kZSA9IHRyZWUuZmluZE5vZGUo WydwYXJlbnQgbm9kZScsICdzb21lIG5ldyBub2RlJ10pOworICAgICAgICBleHBlY3Qobm9kZS5k YXRhKS50b0VxdWFsKHtkYXRhOiAnaW50ZXJlc3RpbmcnfSk7CisgICAgICB9KTsKKworICAgICAg aXQoJ3JldHVybiB0cnVlIGZvciAjaGFzUGFyZW50KCknLCAoKSA9PiB7CisgICAgICAgIGNvbnN0 IG5vZGUgPSB0cmVlLmZpbmROb2RlKFsncGFyZW50IG5vZGUnLCAnc29tZSBuZXcgbm9kZSddKTsK KyAgICAgICAgZXhwZWN0KG5vZGUuaGFzUGFyZW50KCkpLnRvQmUodHJ1ZSk7CisgICAgICB9KTsK KworICAgICAgaXQoJ3JldHVybiAicGFyZW50IG5vZGUiIG9iamVjdCBmb3IgI3BhcmVudCgpJywg KCkgPT4geworICAgICAgICBjb25zdCBub2RlID0gdHJlZS5maW5kTm9kZShbJ3BhcmVudCBub2Rl JywgJ3NvbWUgbmV3IG5vZGUnXSk7CisgICAgICAgIGV4cGVjdChub2RlLnBhcmVudCgpKS50b0Vx dWFsKHBhcmVudE5vZGUpOworICAgICAgfSk7CisgICAgfSk7CisKKyAgICBkZXNjcmliZSgnd2hl biBhZGQgYW4gZWxlbWVudCB0aGF0IGFscmVhZHkgZXhpc3RzIHVuZGVyIGEgcGFyZW50JywgKCkg PT4geworICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7CisgICAgICAgIHRyZWUuYWRkTmV3Tm9kZSgn cGFyZW50IG5vZGUnLCB7ZGF0YTogJ3BhcmVudCBkYXRhJ30sIHVuZGVmaW5lZCwgW10pOworICAg ICAgICB0cmVlLmFkZE5ld05vZGUoJ3NvbWUgbmV3IG5vZGUnLCB7ZGF0YTogJ2ludGVyZXN0aW5n J30sIHVuZGVmaW5lZCwgWydwYXJlbnQnICsKKyAgICAgICAgJyBub2RlJ10pOworICAgICAgfSk7 CisKKyAgICAgIGl0KCdkb2VzIG5vdCBhZGQgYSBuZXcgY2hpbGQnLCAoKSA9PiB7CisgICAgICAg IHRyZWUuYWRkTmV3Tm9kZSgnc29tZSBuZXcgbm9kZScsIHtkYXRhOiAnaW50ZXJlc3RpbmcgMSd9 LCB1bmRlZmluZWQsIFsncGFyZW50JyArCisgICAgICAgICcgbm9kZSddKTsKKyAgICAgICAgY29u c3QgcGFyZW50Tm9kZSA9IHRyZWUuZmluZE5vZGUoWydwYXJlbnQgbm9kZSddKTsKKyAgICAgICAg ZXhwZWN0KHBhcmVudE5vZGUuY2hpbGRyZW4ubGVuZ3RoKS50b0JlKDEpOworICAgICAgfSk7CisK KyAgICAgIGl0KCd1cGRhdGVzIHRoZSBleGlzdGluZyBub2RlIGRhdGEnLCAoKSA9PiB7CisgICAg ICAgIHRyZWUuYWRkTmV3Tm9kZSgnc29tZSBuZXcgbm9kZScsIHtkYXRhOiAnaW50ZXJlc3Rpbmcg MSd9LCB1bmRlZmluZWQsIFsncGFyZW50JyArCisgICAgICAgICcgbm9kZSddKTsKKyAgICAgICAg Y29uc3Qgbm9kZSA9IHRyZWUuZmluZE5vZGUoWydwYXJlbnQgbm9kZScsICdzb21lIG5ldyBub2Rl J10pOworICAgICAgICBleHBlY3Qobm9kZS5kYXRhKS50b0VxdWFsKHtkYXRhOiAnaW50ZXJlc3Rp bmcgMSd9KTsKKyAgICAgIH0pOworICAgIH0pOworICB9KTsKKworICBkZXNjcmliZSgnI3RyYW5z bGF0ZVRyZWVOb2RlSWRGcm9tQUNJVHJlZScsICgpID0+IHsKKyAgICBsZXQgYWNpVHJlZUFwaTsK KyAgICBiZWZvcmVFYWNoKCgpID0+IHsKKyAgICAgIGFjaVRyZWVBcGkgPSBqYXNtaW5lLmNyZWF0 ZVNweU9iaignQUNJVHJlZUFwaScsIFsKKyAgICAgICAgJ2hhc1BhcmVudCcsCisgICAgICAgICdw YXJlbnQnLAorICAgICAgICAnZ2V0SWQnLAorICAgICAgXSk7CisKKyAgICAgIGFjaVRyZWVBcGku Z2V0SWQuYW5kLmNhbGxGYWtlKChub2RlKSA9PiB7CisgICAgICAgIHJldHVybiBub2RlWzBdLmlk OworICAgICAgfSk7CisgICAgICB0cmVlLmFjaVRyZWVBcGkgPSBhY2lUcmVlQXBpOworICAgIH0p OworCisgICAgZGVzY3JpYmUoJ1doZW4gdHJlZSBhcyBhIHNpbmdsZSBsZXZlbCcsICgpID0+IHsK KyAgICAgIGJlZm9yZUVhY2goKCkgPT4geworICAgICAgICBhY2lUcmVlQXBpLmhhc1BhcmVudC5h bmQucmV0dXJuVmFsdWUoZmFsc2UpOworICAgICAgfSk7CisKKyAgICAgIGl0KCdyZXR1cm5zIGFu IGFycmF5IHdpdGggdGhlIElEIG9mIHRoZSBmaXJzdCBsZXZlbCcsICgpID0+IHsKKyAgICAgICAg bGV0IG5vZGUgPSBbeworICAgICAgICAgIGlkOiAnc29tZSBpZCcsCisgICAgICAgIH1dOworICAg ICAgICB0cmVlLmFkZE5ld05vZGUoJ3NvbWUgaWQnLCB7fSwgdW5kZWZpbmVkLCBbXSk7CisKKyAg ICAgICAgZXhwZWN0KHRyZWUudHJhbnNsYXRlVHJlZU5vZGVJZEZyb21BQ0lUcmVlKG5vZGUpKS50 b0VxdWFsKFsnc29tZSBpZCddKTsKKyAgICAgIH0pOworICAgIH0pOworCisgICAgZGVzY3JpYmUo J1doZW4gdHJlZSBhcyBhIDIgbGV2ZWxzJywgKCkgPT4geworICAgICAgZGVzY3JpYmUoJ1doZW4g d2UgdHJ5IHRvIHJldHJpZXZlIHRoZSBub2RlIGluIHRoZSBzZWNvbmQgbGV2ZWwnLCAoKSA9PiB7 CisgICAgICAgIGl0KCdyZXR1cm5zIGFuIGFycmF5IHdpdGggdGhlIElEIG9mIHRoZSBmaXJzdCBs ZXZlbCBhbmQgc2Vjb25kIGxldmVsJywgKCkgPT4geworICAgICAgICAgIGFjaVRyZWVBcGkuaGFz UGFyZW50LmFuZC5yZXR1cm5WYWx1ZXModHJ1ZSwgZmFsc2UpOworICAgICAgICAgIGFjaVRyZWVB cGkucGFyZW50LmFuZC5yZXR1cm5WYWx1ZShbeworICAgICAgICAgICAgaWQ6ICdwYXJlbnQgaWQn LAorICAgICAgICAgIH1dKTsKKyAgICAgICAgICBsZXQgbm9kZSA9IFt7CisgICAgICAgICAgICBp ZDogJ3NvbWUgaWQnLAorICAgICAgICAgIH1dOworCisgICAgICAgICAgdHJlZS5hZGROZXdOb2Rl KCdwYXJlbnQgaWQnLCB7fSwgdW5kZWZpbmVkLCBbXSk7CisgICAgICAgICAgdHJlZS5hZGROZXdO b2RlKCdzb21lIGlkJywge30sIHVuZGVmaW5lZCwgWydwYXJlbnQgaWQnXSk7CisKKyAgICAgICAg ICBleHBlY3QodHJlZS50cmFuc2xhdGVUcmVlTm9kZUlkRnJvbUFDSVRyZWUobm9kZSkpCisgICAg ICAgICAgICAudG9FcXVhbChbJ3BhcmVudCBpZCcsICdzb21lIGlkJ10pOworICAgICAgICB9KTsK KyAgICAgIH0pOworICAgIH0pOworICB9KTsKKworICBkZXNjcmliZSgnI3NlbGVjdGVkJywgKCkg PT4geworICAgIGNvbnRleHQoJ2Egbm9kZSBpbiB0aGUgdHJlZSBpcyBzZWxlY3RlZCcsICgpID0+ IHsKKyAgICAgIGl0KCdyZXR1cm5zIHRoYXQgbm9kZSBvYmplY3QnLCAoKSA9PiB7CisgICAgICAg IGxldCBzZWxlY3RlZE5vZGUgPSBuZXcgVHJlZU5vZGUoJ2JhbW0nLCB7fSwgW10pOworICAgICAg ICBzZXREZWZhdWx0Q2FsbEJhY2sodHJlZSwgc2VsZWN0ZWROb2RlKTsKKyAgICAgICAgZXhwZWN0 KHRyZWUuc2VsZWN0ZWQoKSkudG9FcXVhbChzZWxlY3RlZE5vZGUpOworICAgICAgfSk7CisgICAg fSk7CisgIH0pOworCisgIGRlc2NyaWJlKCcjZmluZE5vZGVCeVRyZWVFbGVtZW50JywgKCkgPT4g eworICAgIGNvbnRleHQoJ3JldHJpZXZlIGRhdGEgZnJvbSBub2RlIG5vdCBmb3VuZCcsICgpID0+ IHsKKyAgICAgIGl0KCdyZXR1cm4gdW5kZWZpbmVkJywgKCkgPT4geworICAgICAgICBsZXQgYWNp VHJlZUFwaSA9IGphc21pbmUuY3JlYXRlU3B5T2JqKCdBQ0lUcmVlQXBpJywgWworICAgICAgICAg ICdoYXNQYXJlbnQnLAorICAgICAgICAgICdwYXJlbnQnLAorICAgICAgICAgICdnZXRJZCcsCisg ICAgICAgIF0pOworCisgICAgICAgIGFjaVRyZWVBcGkuZ2V0SWQuYW5kLmNhbGxGYWtlKChub2Rl KSA9PiB7CisgICAgICAgICAgcmV0dXJuIG5vZGVbMF0uaWQ7CisgICAgICAgIH0pOworICAgICAg ICB0cmVlLmFjaVRyZWVBcGkgPSBhY2lUcmVlQXBpOworICAgICAgICBleHBlY3QodHJlZS5maW5k Tm9kZUJ5RG9tRWxlbWVudChbJzxsaT5zb21ldGhpbmc8L2xpPiddKSkudG9CZVVuZGVmaW5lZCgp OworICAgICAgfSk7CisgICAgfSk7CisgIH0pOworfTsKKworZGVzY3JpYmUoJ3RyZWUgdGVzdHMn LCAoKSA9PiB7CisgIGRlc2NyaWJlKCdUcmVlTm9kZScsICgpID0+IHsKKyAgICBkZXNjcmliZSgn I2hhc1BhcmVudCcsICgpID0+IHsKKyAgICAgIGNvbnRleHQoJ3BhcmVudCBpcyBudWxsJywgKCkg PT4geworICAgICAgICBpdCgncmV0dXJucyBmYWxzZScsICgpID0+IHsKKyAgICAgICAgICBsZXQg dHJlZU5vZGUgPSBuZXcgVHJlZU5vZGUoJzEyMycsIHt9LCBbXSwgbnVsbCk7CisgICAgICAgICAg ZXhwZWN0KHRyZWVOb2RlLmhhc1BhcmVudCgpKS50b0JlKGZhbHNlKTsKKyAgICAgICAgfSk7Cisg ICAgICB9KTsKKyAgICAgIGNvbnRleHQoJ3BhcmVudCBpcyB1bmRlZmluZWQnLCAoKSA9PiB7Cisg ICAgICAgIGl0KCdyZXR1cm5zIGZhbHNlJywgKCkgPT4geworICAgICAgICAgIGxldCB0cmVlTm9k ZSA9IG5ldyBUcmVlTm9kZSgnMTIzJywge30sIFtdLCB1bmRlZmluZWQpOworICAgICAgICAgIGV4 cGVjdCh0cmVlTm9kZS5oYXNQYXJlbnQoKSkudG9CZShmYWxzZSk7CisgICAgICAgIH0pOworICAg ICAgfSk7CisgICAgICBjb250ZXh0KCdwYXJlbnQgZXhpc3RzJywgKCkgPT4geworICAgICAgICBp dCgncmV0dXJucyB0cnVlJywgKCkgPT4geworICAgICAgICAgIGxldCBwYXJlbnROb2RlID0gbmV3 IFRyZWVOb2RlKCc0NTYnLCB7fSwgW10pOworICAgICAgICAgIGxldCB0cmVlTm9kZSA9IG5ldyBU cmVlTm9kZSgnMTIzJywge30sIFtdLCBwYXJlbnROb2RlKTsKKyAgICAgICAgICBleHBlY3QodHJl ZU5vZGUuaGFzUGFyZW50KCkpLnRvQmUodHJ1ZSk7CisgICAgICAgIH0pOworICAgICAgfSk7Cisg ICAgfSk7CisKKyAgICBkZXNjcmliZSgnI3JlbG9hZCcsICgpID0+IHsKKyAgICAgIGxldCB0cmVl OworICAgICAgbGV0IGxldmVsMjsKKyAgICAgIGJlZm9yZUVhY2goKCkgPT4geworICAgICAgICB0 cmVlID0gbmV3IFRyZWVGYWtlKCk7CisgICAgICAgIHRyZWUuYWRkTmV3Tm9kZSgnbGV2ZWwxJywg e2RhdGE6ICdpbnRlcmVzdGluZyd9LCBbe2lkOiAnbGV2ZWwxJ31dLCBbXSk7CisgICAgICAgIGxl dmVsMiA9IHRyZWUuYWRkTmV3Tm9kZSgnbGV2ZWwyJywge2RhdGE6ICdkYXRhJ30sIFt7aWQ6ICds ZXZlbDInfV0sIFsnbGV2ZWwxJ10pOworICAgICAgICB0cmVlLmFkZE5ld05vZGUoJ2xldmVsMycs IHtkYXRhOiAnbW9yZSBkYXRhJ30sIFt7aWQ6ICdsZXZlbDMnfV0sIFsnbGV2ZWwxJywgJ2xldmVs MiddKTsKKworICAgICAgICB0cmVlLmFjaVRyZWVBcGkgPSBqYXNtaW5lLmNyZWF0ZVNweU9iaigK KyAgICAgICAgICAnQUNJVHJlZUFwaScsIFsnc2V0SW5vZGUnLCAndW5sb2FkJywgJ2Rlc2VsZWN0 JywgJ3NlbGVjdCddKTsKKyAgICAgIH0pOworCisgICAgICBpdCgncmVsb2FkcyB0aGUgbm9kZSBh bmQgaXRzIGNoaWxkcmVuJywgKCkgPT4geworICAgICAgICBsZXZlbDIucmVsb2FkKHRyZWUpOwor ICAgICAgICBleHBlY3QodHJlZS5maW5kTm9kZUJ5RG9tRWxlbWVudChbe2lkOiAnbGV2ZWwyJ31d KSkudG9FcXVhbChsZXZlbDIpOworICAgICAgfSk7CisKKyAgICAgIGl0KCdkb2VzIG5vdCByZWxv YWQgdGhlIGNoaWxkcmVuIG9mIG5vZGUnLCAoKSA9PiB7CisgICAgICAgIGxldmVsMi5yZWxvYWQo dHJlZSk7CisgICAgICAgIGV4cGVjdCh0cmVlLmZpbmROb2RlQnlEb21FbGVtZW50KFt7aWQ6ICds ZXZlbDMnfV0pKS50b0JlTnVsbCgpOworICAgICAgfSk7CisKKyAgICAgIGl0KCdzZWxlY3QgdGhl IG5vZGUnLCAoZG9uZSkgPT4geworICAgICAgICBsZXZlbDIucmVsb2FkKHRyZWUpOworICAgICAg ICBzZXRUaW1lb3V0KCgpID0+IHsKKyAgICAgICAgICBleHBlY3QodHJlZS5zZWxlY3RlZCgpKS50 b0VxdWFsKFt7aWQ6ICdsZXZlbDInfV0pOworICAgICAgICAgIGRvbmUoKTsKKyAgICAgICAgfSwg MjApOworICAgICAgfSk7CisKKyAgICAgIGRlc2NyaWJlKCdBQ0lUcmVlIHNwZWNpZmljJywgKCkg PT4geworICAgICAgICBpdCgnc2V0cyB0aGUgY3VycmVudCBub2RlIGFzIGEgSW5vZGUsIGNoYW5n aW5nIHRoZSBJY29uIGJhY2sgdG8gKycsICgpID0+IHsKKyAgICAgICAgICBsZXZlbDIucmVsb2Fk KHRyZWUpOworICAgICAgICAgIGV4cGVjdCh0cmVlLmFjaVRyZWVBcGkuc2V0SW5vZGUpLnRvSGF2 ZUJlZW5DYWxsZWRXaXRoKFt7aWQ6ICdsZXZlbDInfV0pOworICAgICAgICB9KTsKKworICAgICAg ICBpdCgnZGVzZWxlY3QgdGhlIG5vZGUgYW5kIHNlbGVjdHMgaXQgYWdhaW4gdG8gdHJpZ2dlciBB Q0kgdHJlZScgKworICAgICAgICAgICcgZXZlbnRzJywgKGRvbmUpID0+IHsKKyAgICAgICAgICBs ZXZlbDIucmVsb2FkKHRyZWUpOworICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4geworICAgICAg ICAgICAgZXhwZWN0KHRyZWUuYWNpVHJlZUFwaS5kZXNlbGVjdCkudG9IYXZlQmVlbkNhbGxlZFdp dGgoW3tpZDogJ2xldmVsMid9XSk7CisgICAgICAgICAgICBkb25lKCk7CisgICAgICAgICAgfSwg MjApOworICAgICAgICB9KTsKKyAgICAgIH0pOworICAgIH0pOworCisgICAgZGVzY3JpYmUoJyN1 bmxvYWQnLCAoKSA9PiB7CisgICAgICBsZXQgdHJlZTsKKyAgICAgIGxldCBsZXZlbDI7CisgICAg ICBiZWZvcmVFYWNoKCgpID0+IHsKKyAgICAgICAgdHJlZSA9IG5ldyBUcmVlRmFrZSgpOworICAg ICAgICB0cmVlLmFkZE5ld05vZGUoJ2xldmVsMScsIHtkYXRhOiAnaW50ZXJlc3RpbmcnfSwgWyc8 bGk+bGV2ZWwxPC9saT4nXSwgW10pOworICAgICAgICBsZXZlbDIgPSB0cmVlLmFkZE5ld05vZGUo J2xldmVsMicsIHtkYXRhOiAnZGF0YSd9LCBbJzxsaT5sZXZlbDI8L2xpPiddLCBbJ2xldmVsMSdd KTsKKyAgICAgICAgdHJlZS5hZGROZXdOb2RlKCdsZXZlbDMnLCB7ZGF0YTogJ21vcmUgZGF0YSd9 LCBbJzxsaT5sZXZlbDM8L2xpPiddLCBbJ2xldmVsMScsICdsZXZlbDInXSk7CisgICAgICAgIHRy ZWUuYWNpVHJlZUFwaSA9IGphc21pbmUuY3JlYXRlU3B5T2JqKCdBQ0lUcmVlQXBpJywgWyd1bmxv YWQnXSk7CisgICAgICB9KTsKKworICAgICAgaXQoJ3VubG9hZHMgdGhlIGNoaWxkcmVuIG9mIHRo ZSBjdXJyZW50IG5vZGUnLCAoKSA9PiB7CisgICAgICAgIGxldmVsMi51bmxvYWQodHJlZSk7Cisg ICAgICAgIGV4cGVjdCh0cmVlLmZpbmROb2RlQnlEb21FbGVtZW50KFt7aWQ6ICdsZXZlbDInfV0p KS50b0VxdWFsKGxldmVsMik7CisgICAgICAgIGV4cGVjdCh0cmVlLmZpbmROb2RlQnlEb21FbGVt ZW50KFt7aWQ6ICdsZXZlbDMnfV0pKS50b0JlTnVsbCgpOworICAgICAgfSk7CisKKyAgICAgIGl0 KCdjYWxscyB1bmxvYWQgb24gdGhlIEFDSSBUcmVlJywgKCkgPT4geworICAgICAgICBsZXZlbDIu dW5sb2FkKHRyZWUpOworICAgICAgICBleHBlY3QodHJlZS5hY2lUcmVlQXBpLnVubG9hZCkudG9I YXZlQmVlbkNhbGxlZFdpdGgoWyc8bGk+bGV2ZWwyPC9saT4nXSk7CisgICAgICB9KTsKKyAgICB9 KTsKKyAgfSk7CisKKyAgZGVzY3JpYmUoJ1RyZWUnLCAoKSA9PiB7CisgICAgZnVuY3Rpb24gcmVh bFRyZWVTZWxlY3ROb2RlKHRyZWUsIHNlbGVjdGVkTm9kZSkgeworICAgICAgbGV0IGFjaVRyZWVB cGkgPSBqYXNtaW5lLmNyZWF0ZVNweU9iaignQUNJVHJlZUFwaScsIFsKKyAgICAgICAgJ3NlbGVj dGVkJywKKyAgICAgIF0pOworICAgICAgdHJlZS5hY2lUcmVlQXBpID0gYWNpVHJlZUFwaTsKKyAg ICAgIGFjaVRyZWVBcGkuc2VsZWN0ZWQuYW5kLnJldHVyblZhbHVlKHNlbGVjdGVkTm9kZSk7Cisg ICAgfQorCisgICAgdHJlZVRlc3RzKFRyZWUsIHJlYWxUcmVlU2VsZWN0Tm9kZSk7CisgIH0pOwor CisgIGRlc2NyaWJlKCdUcmVlRmFrZScsICgpID0+IHsKKyAgICBmdW5jdGlvbiBmYWtlVHJlZVNl bGVjdE5vZGUodHJlZSwgc2VsZWN0ZWROb2RlKSB7CisgICAgICB0cmVlLnNlbGVjdE5vZGUoc2Vs ZWN0ZWROb2RlKTsKKyAgICB9CisKKyAgICB0cmVlVGVzdHMoVHJlZUZha2UsIGZha2VUcmVlU2Vs ZWN0Tm9kZSk7CisKKyAgICBkZXNjcmliZSgnI2hhc1BhcmVudCcsICgpID0+IHsKKyAgICAgIGNv bnRleHQoJ3RyZWUgY29udGFpbnMgbXVsdGlwbGUgbGV2ZWxzJywgKCkgPT4geworICAgICAgICBs ZXQgdHJlZTsKKyAgICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7CisgICAgICAgICAgdHJlZSA9IG5l dyBUcmVlRmFrZSgpOworICAgICAgICAgIHRyZWUuYWRkTmV3Tm9kZSgnbGV2ZWwxJywge2RhdGE6 ICdpbnRlcmVzdGluZyd9LCB1bmRlZmluZWQsIFtdKTsKKyAgICAgICAgICB0cmVlLmFkZE5ld05v ZGUoJ2xldmVsMicsIHtkYXRhOiAnaW50ZXJlc3RpbmcnfSwgdW5kZWZpbmVkLCBbJ2xldmVsMSdd KTsKKyAgICAgICAgfSk7CisKKyAgICAgICAgY29udGV4dCgnbm9kZSBpcyBhdCB0aGUgZmlyc3Qg bGV2ZWwnLCAoKSA9PiB7CisgICAgICAgICAgaXQoJ3JldHVybnMgZmFsc2UnLCAoKSA9PiB7Cisg ICAgICAgICAgICBleHBlY3QodHJlZS5oYXNQYXJlbnQoW3tpZDogJ2xldmVsMSd9XSkpLnRvQmUo ZmFsc2UpOworICAgICAgICAgIH0pOworICAgICAgICB9KTsKKworICAgICAgICBjb250ZXh0KCdu b2RlIGlzIGF0IHRoZSBzZWNvbmQgbGV2ZWwnLCAoKSA9PiB7CisgICAgICAgICAgaXQoJ3JldHVy bnMgdHJ1ZScsICgpID0+IHsKKyAgICAgICAgICAgIGV4cGVjdCh0cmVlLmhhc1BhcmVudChbe2lk OiAnbGV2ZWwyJ31dKSkudG9CZSh0cnVlKTsKKyAgICAgICAgICB9KTsKKyAgICAgICAgfSk7Cisg ICAgICB9KTsKKyAgICB9KTsKKworICAgIGRlc2NyaWJlKCcjcGFyZW50JywgKCkgPT4geworICAg ICAgbGV0IHRyZWU7CisgICAgICBiZWZvcmVFYWNoKCgpID0+IHsKKyAgICAgICAgdHJlZSA9IG5l dyBUcmVlRmFrZSgpOworICAgICAgICB0cmVlLmFkZE5ld05vZGUoJ2xldmVsMScsIHtkYXRhOiAn aW50ZXJlc3RpbmcnfSwgdW5kZWZpbmVkLCBbXSk7CisgICAgICAgIHRyZWUuYWRkTmV3Tm9kZSgn bGV2ZWwyJywge2RhdGE6ICdpbnRlcmVzdGluZyd9LCB1bmRlZmluZWQsIFsnbGV2ZWwxJ10pOwor ICAgICAgfSk7CisKKyAgICAgIGNvbnRleHQoJ25vZGUgaXMgdGhlIHJvb3QnLCAoKSA9PiB7Cisg ICAgICAgIGl0KCdyZXR1cm5zIG51bGwnLCAoKSA9PiB7CisgICAgICAgICAgZXhwZWN0KHRyZWUu cGFyZW50KFt7aWQ6ICdsZXZlbDEnfV0pKS50b0JlTnVsbCgpOworICAgICAgICB9KTsKKyAgICAg IH0pOworCisgICAgICBjb250ZXh0KCdub2RlIGlzIG5vdCByb290JywgKCkgPT4geworICAgICAg ICBpdCgncmV0dXJucyByb290IGVsZW1lbnQnLCAoKSA9PiB7CisgICAgICAgICAgZXhwZWN0KHRy ZWUucGFyZW50KFt7aWQ6ICdsZXZlbDInfV0pKS50b0VxdWFsKFt7aWQ6ICdsZXZlbDEnfV0pOwor ICAgICAgICB9KTsKKyAgICAgIH0pOworICAgIH0pOworCisgICAgZGVzY3JpYmUoJyNpdGVtRGF0 YScsICgpID0+IHsKKyAgICAgIGxldCB0cmVlOworICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7Cisg ICAgICAgIHRyZWUgPSBuZXcgVHJlZUZha2UoKTsKKyAgICAgICAgdHJlZS5hZGROZXdOb2RlKCds ZXZlbDEnLCB7ZGF0YTogJ2ludGVyZXN0aW5nJ30sIHVuZGVmaW5lZCwgW10pOworICAgICAgICB0 cmVlLmFkZE5ld05vZGUoJ2xldmVsMicsIHtkYXRhOiAnZXhwZWN0ZWQgZGF0YSd9LCB1bmRlZmlu ZWQsIFsnbGV2ZWwxJ10pOworICAgICAgfSk7CisKKyAgICAgIGNvbnRleHQoJ3JldHJpZXZlIGRh dGEgZnJvbSB0aGUgbm9kZScsICgpID0+IHsKKyAgICAgICAgaXQoJ3JldHVybiB0aGUgbm9kZSBk YXRhJywgKCkgPT4geworICAgICAgICAgIGV4cGVjdCh0cmVlLml0ZW1EYXRhKFt7aWQ6ICdsZXZl bDInfV0pKS50b0VxdWFsKHsKKyAgICAgICAgICAgIGRhdGE6ICdleHBlY3RlZCcgKworICAgICAg ICAgICAgJyBkYXRhJywKKyAgICAgICAgICB9KTsKKyAgICAgICAgfSk7CisgICAgICB9KTsKKwor ICAgICAgY29udGV4dCgncmV0cmlldmUgZGF0YSBmcm9tIG5vZGUgbm90IGZvdW5kJywgKCkgPT4g eworICAgICAgICBpdCgncmV0dXJuIHVuZGVmaW5lZCcsICgpID0+IHsKKyAgICAgICAgICBleHBl Y3QodHJlZS5pdGVtRGF0YShbe2lkOiAnYmFtbSd9XSkpLnRvQmVVbmRlZmluZWQoKTsKKyAgICAg ICAgfSk7CisgICAgICB9KTsKKyAgICB9KTsKKworICAgIGRlc2NyaWJlKCcjYWRkQ2hpbGQnLCAo KSA9PiB7CisgICAgICBsZXQgcm9vdCwgY2hpbGQ7CisgICAgICBiZWZvcmVFYWNoKCgpID0+IHsK KyAgICAgICAgbGV0IHRyZWUgPSBuZXcgVHJlZUZha2UoKTsKKyAgICAgICAgcm9vdCA9IHRyZWUu YWRkTmV3Tm9kZSgncm9vdCcsIHt9LCBbe2lkOiAncm9vdCd9XSk7CisgICAgICAgIGNoaWxkID0g bmV3IFRyZWVOb2RlKCdub2RlLjEnLCB7fSwgW3tpZDogJ25vZGUuMSd9XSk7CisgICAgICAgIHRy ZWUuYWRkQ2hpbGQocm9vdCwgY2hpbGQpOworICAgICAgfSk7CisKKyAgICAgIGl0KCdhZGRzIGEg bmV3IGNoaWxkIHRvIGEgbm9kZScsICgpID0+IHsKKyAgICAgICAgZXhwZWN0KHJvb3QuY2hpbGRy ZW4pLnRvRXF1YWwoW2NoaWxkXSk7CisgICAgICB9KTsKKworICAgICAgaXQoJ2NoYW5nZXMgdGhl IHBhcmVudCBvZiB0aGUgY2hpbGQgbm9kZScsICgpID0+IHsKKyAgICAgICAgZXhwZWN0KHJvb3Qu Y2hpbGRyZW5bMF0ucGFyZW50Tm9kZSkudG9FcXVhbChyb290KTsKKyAgICAgICAgZXhwZWN0KGNo aWxkLnBhcmVudE5vZGUpLnRvRXF1YWwocm9vdCk7CisgICAgICB9KTsKKworICAgICAgaXQoJ2No YW5nZXMgdGhlIHBhdGggb2YgdGhlIGNoaWxkJywgKCkgPT4geworICAgICAgICBleHBlY3QoY2hp bGQucGF0aCkudG9FcXVhbCgncm9vdC5ub2RlLjEnKTsKKyAgICAgIH0pOworICAgIH0pOworICB9 KTsKK30pOworCg== --000000000000c11f78056b122756--