On Sat, May 30, 2020 at 3:08 PM Craig Russell <apache....@gmail.com> wrote:
>
> > On May 29, 2020, at 3:17 AM, sebb <seb...@gmail.com> wrote:
> >
> > On Fri, 29 May 2020 at 00:49, Craig Russell <apache....@gmail.com> wrote:
> >>
> >> It looks like the best approach is to do the svn operations in two steps:
> >>
> >> 1. Update the svn foundation/members.txt based on the request (active, 
> >> emeritus, deceased) which is already in place.
> >> 2. Perform the moves in svn documents 
> >> (emeritus-request-received>emeritus-request-rescinded, 
> >> emeritus-request-received->emeritus) which is new code to be written.
> >>
> >> These are two different svn repositories so they need to be in two svn 
> >> commits anyway.
> >
> > Not AFAIK. All the ASF documents are in the same SVN repo, which is rooted 
> > at:
> >
> > https://svn.apache.org/repos/private
>
> Thanks for that. I have each repository checked out and didn't think to look 
> to see if they shared a root.
> >
> >> And if the operations are retried on failure there is nothing to be done 
> >> to coordinate the two operations. Meanwhile, I am sure that I do not know 
> >> how to make the roster ruby/svn code retriable.
> >
> > A problem arises if the second request fails even after retry.
> > There will be an outstanding change which has to be performed at some
> > later stage.
>
> So if I understand you, we can do both updates with the same svn commit, and 
> should do so to avoid a partial commit that then needs to be corrected by 
> hand.

Correct.  In fact, if the commit is ONLY intended to have the move, it
can be done via a single svn move command where both the source and
destination are specified as URLs.

http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.move.html

> >> I plan to start on figuring out how to do svn move from emeritus to 
> >> emeritus-request-rescinded.
> >
> > Do you mean emeritus-request => emeritus-request-rescinded ?
>
> Yes. So I'm thinking that we should adapt the memstat.json.rb code to accept 
> another url parameter with the file name that we already know, and send that 
> file name to the _svn.update method.
>
> As long as we're looking at this method, isn't it a bit badly named? Its 
> purpose is specifically to modify the members.txt file to move an entry from 
> one place to another, so shouldn't it have a more specific name, like 
> update_members_info?
>
> Anyway, we now need to pass the emeritus_file_name from memstat.json.rb to 
> the update method. And then have the update method use that file name to move 
> the file from one emeritus directory to another, depending on the action:
> emeritus: move the file from emeritus-requests-received to emeritus
> rescind: move the file from emeritus-requests-received to 
> emeritus-requests-rescinded
> active: move the file from emeritus to emeritus-rescinded
>
> I'd like to understand how this method call works:
> _svn.update members_txt, message: message do |dir, text|
>
> Specifically, where did dir and text come from and why are they enclosed in 
> |...|?

the ```do |args|.... end``` effectively defines an anonymous function.
The parameters to that function are enclosed in vertical bars.  Ruby
calls this anonymous function a block.

There are two syntaxes for calling blocks.  In this case, the block is
called via a yield statement.  A more complete description can be
found here:

https://mixandgo.com/learn/mastering-ruby-blocks-in-less-than-5-minutes

Taking a step back, what is happening here is that the update method
does a checkout into a temporary directory, reads the current contents
of the file in question and passes that directory and contents to the
anonymous function which returns new contents.  A commit is then
attempted.

Making the code that converts old contents into new contants a block
means that the overall process (starting with the creating of a
temporary directory to commit potentially common code that is
independent of the update operation being attempted.

> It looks like the code in memstat.json.rb is a co-routine with the code in 
> lib...svn.rb, where the svn.rb code opens the members_txt file, passes 
> control to the code in memstat.json.rb to update the members.txt data and 
> when that's done, svn.rb takes over and completes the commit operation.
>
> So now we are in the _svn.update do block and need to execute an svn mv 
> command.
>
>   # determine where to put the entry
>   if @action == 'emeritus'
>     index = text.index(/^\s\*\)\s/, text.index(/^Emeritus/))
>     entry.sub! %r{\s*/\* deceased, .+?\*/},'' # drop the deceased comment if 
> necessary
>
> dir = ASF:SVN:find!('documents') # this is the root directory
> from = 'emeritus-requests-received'
> to = 'emeritus'
> # execute the code to move the file from one directory to another
> svn.move(dir, from, to, @emeritus-file-name)
>
> Over to you...
>
> Craig
> >
> >> Thanks,
> >> Craig
> >>
> >>> On May 26, 2020, at 10:37 PM, Sam Ruby <ru...@intertwingly.net> wrote:
> >>>
> >>> On Wed, May 27, 2020 at 12:38 AM Craig Russell <apache....@gmail.com> 
> >>> wrote:
> >>>>
> >>>> I'm not having any success understanding the memstat.json.rb code:
> >>>> # update members.txt
> >>>> _svn.update members_txt, message: message do |dir, text|
> >>>>
> >>>> Does this call the code in svn.rb?
> >>>>   def self.update(path, msg, env, _, options={})
> >>>>
> >>>> I guess I'm not so good at reading the ruby...
> >>>
> >>> The definition of _svn is here:
> >>>
> >>> https://github.com/apache/whimsy/blob/4e89c0e2a1069fbe7b6f4472722836c12a846e6c/www/roster/models/svn.rb#L29
> >>>
> >>> It does indeed call the update method in lib/whimsy/asf/svn.rb.
> >>>
> >>> As an aside, the JavaScript module system, like Python, requires each
> >>> module to explicitly import what it needs, this makes it easier to
> >>> identify where the definition of a given method is.  Enough so that
> >>> IDEs like VSCode allow you to control-click (or command-click on
> >>> MacOS) on a function call and it will take you to its definition.
> >>>
> >>>> I'm more used to the read/update/write/repeat/commit style of database 
> >>>> access, where the memstat.json.rb would
> >>>> - read the members.txt
> >>>> - using the action (emeritus, active, deceased, request_emeritus, 
> >>>> rescind_emeritus) edit the members.txt
> >>>> - move the file from emeritus-requests-received to emeritus (emeritus)
> >>>> - remove the file from emeritus-requests-received (rescind)
> >>>> - svn commit the changes
> >>>
> >>> That's indeed how it was done on the original whimsy_vm (effectively
> >>> whimsy_vm1).  It routinely would get 'wedged' (that's the term you
> >>> used at the time) and I would have to ssh into that machine, run a
> >>> combination of svn reverts and svn cleanups until the directory was
> >>> clean again, then the operation could be attempted again.  Perhaps you
> >>> might remember this happening.
> >>>
> >>> The second iteration creates a fresh checkout of the directory in
> >>> question, runs your block against that directory and commits the
> >>> results.  Should the directory get 'wedged', the operation will fail,
> >>> but no matter what happens that temporary directory will be thrown
> >>> away, so the operation can be attempted again.  This is the code you
> >>> are now looking at.
> >>>
> >>> The third iteration (present only in the Ruby board agenda tool at the
> >>> moment) takes this a step further and retries operations.  Unlike the
> >>> secretary workbench and even to some extent the roster tool, the board
> >>> agenda tool is often used by multiple people concurrently, often with
> >>> changes to the same lines (most notably, the approval lines) on the
> >>> day before the board meeting.  If a commit fails, a sleep for a random
> >>> time occurs and the operation is attempted again with a fresh checkout
> >>> and re-invoking the same block.  I even have a test tool that
> >>> simulates 9 directors committing at once:
> >>>
> >>> https://github.com/apache/whimsy/blob/master/www/board/agenda/test/stresstest.rb
> >>>
> >>> The fourth iteration (currently being prototyped in
> >>> JavaScript/Node.js) is intended to incorporate the above retry logic
> >>> in production, but will also employ different strategies in
> >>> development and test.
> >>>
> >>> In the fullness of time, all of this should hopefully converge.
> >>> Meanwhile, build on the strategy that you feel most comfortable with,
> >>> and over time it will likely be rewritten as new strategies emerge.
> >>>
> >>>> Craig
> >>>
> >>> - Sam Ruby
> >>>
> >>>>> On May 26, 2020, at 6:09 PM, Sam Ruby <ru...@intertwingly.net> wrote:
> >>>>>
> >>>>> On Tue, May 26, 2020 at 8:44 PM Craig Russell <apache....@gmail.com> 
> >>>>> wrote:
> >>>>>>
> >>>>>> Sorry for not being clear. In the whimsy/lib there is a helper file 
> >>>>>> svn.rb that has a number of functions including update(path, msg, env, 
> >>>>>> _, options={}) that is used by roster memstat.json.rb and it contains 
> >>>>>> the commit in the function.
> >>>>>>
> >>>>>> I did not see a move or remove function in svn.rb. Should I be looking 
> >>>>>> somewhere else for examples of svn commands? Should I look at adding 
> >>>>>> move and remove functions to svn.rb?
> >>>>>
> >>>>> Not currently.
> >>>>>
> >>>>> I'm convinced that the right way forward is for all svn access to be
> >>>>> done via what you are calling helpers.  This not only makes the code
> >>>>> cleaner
> >>>>>
> >>>>> Ruby: File.read(File.join(ASF::SVN['foundation_board'],
> >>>>> 'board_agenda_06_17.txt')
> >>>>> JS: Board.read('board_agenda_06_17.txt')
> >>>>>
> >>>>> ... it also enables redirecting all commits to a local repository in
> >>>>> development, and mocking the repository in test.
> >>>>>
> >>>>> In any case, all of the svn operations should be updated to make use
> >>>>> of --password-from-stdin where available, which unfortunately won't be
> >>>>> until whimsy-vm is upgraded to Ubuntu 20.04.
> >>>>>
> >>>>>> Thanks,
> >>>>>> Craig
> >>>>>
> >>>>> - Sam Ruby
> >>>>>
> >>>>>>> On May 26, 2020, at 5:23 PM, Sam Ruby <ru...@intertwingly.net> wrote:
> >>>>>>>
> >>>>>>> On Tue, May 26, 2020 at 8:15 PM Craig Russell <apache....@gmail.com> 
> >>>>>>> wrote:
> >>>>>>>>
> >>>>>>>> The cancel button now works (thanks, Sam). On to the server side.
> >>>>>>>>
> >>>>>>>> To implement active->emeritus we need to update members.txt and move 
> >>>>>>>> the request file from emeritus-requests-received to emeritus.
> >>>>>>>>
> >>>>>>>> - Is there an svn function to move a file from one directory to 
> >>>>>>>> another?
> >>>>>>>
> >>>>>>> http://svnbook.red-bean.com/en/1.6/svn.ref.svn.c.move.html
> >>>>>>>
> >>>>>>>> - Is there a way to have both things done in the same svn commit?
> >>>>>>>
> >>>>>>> If both the source and target have a common parent, do the svn commit
> >>>>>>> from that parent.
> >>>>>>>
> >>>>>>> When the secretary files board minutes,
> >>>>>>> 1) the minutes are moved to the website.  Those source and target
> >>>>>>> don't share a common parent, so two commits are required.
> >>>>>>> 2) the agenda is moved to a subdirectory.  The source and target share
> >>>>>>> a common parent, so one commit suffices.
> >>>>>>>
> >>>>>>>> To implement request_emeritus_status we need to create an email. 
> >>>>>>>> Easy..
> >>>>>>>>
> >>>>>>>> To implement rescind_emeritus_request we need to svn rm the file 
> >>>>>>>> from emeritus-requests-received.
> >>>>>>>>
> >>>>>>>> - Is there an svn function to delete a file?
> >>>>>>>
> >>>>>>> http://svnbook.red-bean.com/en/1.6/svn.ref.svn.c.delete.html
> >>>>>>>
> >>>>>>>> Thanks,
> >>>>>>>> Craig
> >>>>>>>
> >>>>>>> - Sam Ruby
> >>>>>>>
> >>>>>>>>> On May 26, 2020, at 3:20 PM, Craig Russell <apache....@gmail.com> 
> >>>>>>>>> wrote:
> >>>>>>>>>
> >>>>>>>>> Here are the files.
> >>>>>>>>> <main.js.rb><memstat.js.rb>
> >>>>>>>>> And the console logs:
> >>>>>>>>> [Log]  dblclick event.currentTarget: [object HTMLDivElement] 
> >>>>>>>>> (app.js, line 3268)
> >>>>>>>>> [Log]  dblclick event.currentTarget.dataset: [object DOMStringMap] 
> >>>>>>>>> (app.js, line 3269)
> >>>>>>>>> [Log]  dblclick event.currentTarget.dataset.edit: memstat (app.js, 
> >>>>>>>>> line 3270)
> >>>>>>>>> [Log] canx called from Cancel button (app.js, line 4021)
> >>>>>>>>> [Log] event: [object MouseEvent] parent: [object HTMLButtonElement] 
> >>>>>>>>> (app.js, line 4024)
> >>>>>>>>> [Log] parent: [object HTMLButtonElement] memstatElement: [object 
> >>>>>>>>> HTMLDivElement] (app.js, line 4025)
> >>>>>>>>> [Log] preventing default (app.js, line 4026)
> >>>>>>>>> [Log] memstatElement.dataset: [object DOMStringMap] (app.js, line 
> >>>>>>>>> 4027)
> >>>>>>>>> [Log] memstatElement.dataset.edit: memstat (app.js, line 4028)
> >>>>>>>>> [Log]  submit event: [object Object] (app.js, line 3291)
> >>>>>>>>> [Log]  submit target: [object HTMLButtonElement] (app.js, line 3292)
> >>>>>>>>> [Log]  submit parent: [object HTMLButtonElement] (app.js, line 3293)
> >>>>>>>>> [Log]  submit parent.getAttribute(data_cancel): null (app.js, line 
> >>>>>>>>> 3294)
> >>>>>>>>> [Log]  submit target.dataset_edit: undefined (app.js, line 3295)
> >>>>>>>>> [Log]  submit target.dataset: [object DOMStringMap] (app.js, line 
> >>>>>>>>> 3296)
> >>>>>>>>> [Log]  submit target.dataset.edit: undefined (app.js, line 3297)
> >>>>>>>>> [Log]  submit memstatElement.dataset.edit: memstat (app.js, line 
> >>>>>>>>> 3298)
> >>>>>>>>> [Log]  submit cancel_submit: null (app.js, line 3300)
> >>>>>>>>>
> >>>>>>>>>> On May 26, 2020, at 2:19 PM, Sam Ruby <ru...@intertwingly.net> 
> >>>>>>>>>> wrote:
> >>>>>>>>>>
> >>>>>>>>>> On Tue, May 26, 2020 at 1:32 AM Craig Russell 
> >>>>>>>>>> <apache....@gmail.com> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>> But calling preventDefault on the event doesn't appear to do 
> >>>>>>>>>>> anything. It still calls the POST behavior, and does not cause 
> >>>>>>>>>>> the inline edit menu to disappear. And setting the edit function 
> >>>>>>>>>>> to nil doesn't do anything either.
> >>>>>>>>>>>
> >>>>>>>>>>> Maybe there is something else that I need to do?
> >>>>>>>>>>
> >>>>>>>>>> I'll admit that I'm not clear on what you are trying to accomplish,
> >>>>>>>>>> but apparently the problem here is that there is another piece of 
> >>>>>>>>>> code
> >>>>>>>>>> that attaches an event handler (and calls preventDefault):
> >>>>>>>>>>
> >>>>>>>>>> https://github.com/apache/whimsy/blob/d3246f107a35f4d989350f4c1ca64366c98ef423/www/roster/views/person/main.js.rb#L341
> >>>>>>>>>>
> >>>>>>>>>> Perhaps it would be best to add an attribute to the button, and 
> >>>>>>>>>> have
> >>>>>>>>>> the submit method remove the buttons and exit early:
> >>>>>>>>>>
> >>>>>>>>>> diff --git a/www/roster/views/person/main.js.rb
> >>>>>>>>>> b/www/roster/views/person/main.js.rb
> >>>>>>>>>> index 1b5ffdb8..f498489f 100644
> >>>>>>>>>> --- a/www/roster/views/person/main.js.rb
> >>>>>>>>>> +++ b/www/roster/views/person/main.js.rb
> >>>>>>>>>> @@ -355,6 +355,12 @@ class Person < Vue
> >>>>>>>>>> form = jQuery(event.currentTarget).closest('form')
> >>>>>>>>>> target = event.target
> >>>>>>>>>>
> >>>>>>>>>> +    # if button is a cancel button, don't submit and remove 
> >>>>>>>>>> buttons
> >>>>>>>>>> +    if target.getAttribute('data-cancel')
> >>>>>>>>>> +      @edit = null
> >>>>>>>>>> +      return
> >>>>>>>>>> +    end
> >>>>>>>>>> +
> >>>>>>>>>> # serialize form
> >>>>>>>>>> formData = form.serializeArray();
> >>>>>>>>>>
> >>>>>>>>>> diff --git a/www/roster/views/person/memstat.js.rb
> >>>>>>>>>> b/www/roster/views/person/memstat.js.rb
> >>>>>>>>>> index 39367c40..e8d3d318 100644
> >>>>>>>>>> --- a/www/roster/views/person/memstat.js.rb
> >>>>>>>>>> +++ b/www/roster/views/person/memstat.js.rb
> >>>>>>>>>> @@ -35,6 +35,8 @@ class PersonMemberStatus < Vue
> >>>>>>>>>>           _button.btn.btn_primary 'move to emeritus',
> >>>>>>>>>>             name: 'action', value: 'emeritus'
> >>>>>>>>>>         end
> >>>>>>>>>> +
> >>>>>>>>>> +              _button.btn.btn_secondary 'cancel', data_cancel: 
> >>>>>>>>>> true
> >>>>>>>>>>       end
> >>>>>>>>>>     end
> >>>>>>>>>>    end
> >>>>>>>>>>
> >>>>>>>>>> - Sam Ruby
> >>>>>>>>>
> >>>>>>>>> Craig L Russell
> >>>>>>>>> c...@apache.org
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> Craig L Russell
> >>>>>>>> c...@apache.org
> >>>>>>>>
> >>>>>>
> >>>>>> Craig L Russell
> >>>>>> c...@apache.org
> >>>>>>
> >>>>
> >>>> Craig L Russell
> >>>> c...@apache.org
> >>>>
> >>
> >> Craig L Russell
> >> c...@apache.org
> >>
>
> Craig L Russell
> c...@apache.org
>

Reply via email to