quinjet 0.0.12

A fast, live, keyboard-first Git source-control interface for the terminal
�

jY�j���,�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
d\ZZejjdejj!d��ZGd�d�Zd�Zd	�Zd
�Zedk(rej.e��yy)aLDrive Quinjet through a real pty and read back what it drew.

Every terminal-level claim about the pull-request pane in this repository was
checked with this: it opens a pull request against live GitHub, so it needs a
working `gh` login and network and cannot run in CI. Keep it for the things a
unit test cannot see, such as which requests overlap and how long a pane waits.

    python3 scripts/drive.py open   <repo> <pr>
    python3 scripts/drive.py switch <repo> <first> <second>

`open` reports how long the pane takes to answer from a cold cache. `switch`
opens one pull request, waits for its log warm-up to start, then switches to
another and reports whether the second one had to queue behind the first.

Requires pyte:  python3 -m venv .venv && .venv/bin/pip install pyte
Set QUINJET to test a build other than the installed binary.
�N)��-�QUINJETz~/.cargo/bin/quinjetc�:�eZdZd�Zd�Zd�Zd	d�Zd�Zd
d�Zd�Z	y)�Sessionc��tj�\}}tj|tj
t
jdttdd��||_
tjtg||||ttj d��tj"��|_tj&|�t)j*tt�|_t)j.|j,�|_tj2|j$j4�|_|j9d�y)N�HHHHrzxterm-256color)�TERM)�cwd�stdin�stdout�stderr�env�
preexec_fng@)�pty�openpty�fcntl�ioctl�termios�
TIOCSWINSZ�struct�pack�ROWS�COLS�master�
subprocess�Popen�BINARY�dict�os�environ�setsid�process�close�pyte�Screen�screen�
ByteStream�stream�getpgid�pid�group�pump)�self�
repositoryr�slaves    �9/mnt/sandisk/codingAndFun/samaan/quinjet/scripts/drive.py�__init__zSession.__init__$s������
�
���
���E�7�-�-�v�{�{�6�4��q�RS�/T�U����!�'�'�
�H������R�Z�Z�&6�7��y�y�
���	������k�k�$��-����o�o�d�k�k�2����Z�Z���� 0� 0�1��
��	�	�#��c��tj�|z}tj�|kr�tj|jgggd�\}}}|s�A	tj|jd�}|sy|jj|�tj�|kr��yy#t
$rYywxYw)Ng{�G�z�?i)�time�selectrr �read�OSErrorr)�feed)r.�seconds�deadline�ready�_�chunks      r1r-zSession.pump8s����9�9�;��(���i�i�k�H�$� �-�-����
�r�2�t�D�K�E�1�a���
�������W�5�����K�K���U�#��i�i�k�H�$���
��
�s� B2�2	B>�=B>c�L�dj|jj�S)N�
)�joinr'�display�r.s r1�bodyzSession.bodyFs���y�y����,�,�-�-r3c��|D]E}tj|j|j��t	j
|��Gy�N)r �writer�encoder5�sleep)r.�text�settle�	characters    r1�typezSession.typeIs8���	�I��H�H�T�[�[�)�"2�"2�"4�5��J�J�v��	r3c�h�tjgd�dd��jj�}g}|ddD]u}|j	dd�}t|�dks|dt
|j�k7r�?|djd	�s�T|jt|d�|df��w|S)
z�What the workers are doing right now, which is the only way to see
        whether two reads overlapped or one queued behind the other.)�psz-eozpgid,etimes,argsT)�capture_outputrJ�N��rzgh )r�runr
�
splitlines�split�len�strr,�
startswith�append�int)r.�listing�running�line�partss     r1�gh_childrenzSession.gh_childrenNs����.�.�-�d��
�
�&����	����A�B�K�	6�D��J�J�t�Q�'�E��5�z�A�~��q��S����_�!<����8�&�&�u�-���N�N�C��a��M�5��8�4�5�
	6��r3c��|j|�|jd�|jdd��|jt|��|jd�td�D]Y}t	j
|jd�|jd�d	|j�vsd
|j�vs�Yyy)
N��?zg{�G�z�?)rK��?��
g�?�Source�StateTF)rMr-rX�ranger rGrrD)r.�number�focusr=s    r1�open_pull_requestzSession.open_pull_request^s����	�	�%���	�	�#���	�	�*�T�	�*��	�	�#�f�+���	�	�#���q��	�A��H�H�T�[�[�%�(��I�I�c�N��4�9�9�;�&�'�T�Y�Y�[�*@��		�
r3c��tj|jd�|jd�	|jjd��y#tj$r|jj�YywxYw)N�qrc�)�timeout)	r rGrr-r#�waitr�TimeoutExpired�killrCs r1r$z
Session.closels^��
������d�#��	�	�#��	 ��L�L���a��(���(�(�	 ��L�L����	 �s�A�-B�?BN)g���Q��?)�3)
�__name__�
__module__�__qualname__r2r-rDrMr`rkr$�r3r1rr#s%���($�.��
� � r3rc��t|�}	|j|�std�	|j�yt	j�}td�D]{}|j
d�d|j�vs�'tdt	j�|z
d�d��td	|j�vrd
nd�|j�ytd
�	|j�y#|j�wxYw)Nzthe pane never openedrQ�<g�?�Loading the conversationzconversation rendered �.1fzs after the pane opened�cachedzserved from cachez	read liverzthe conversation never rendered)rrk�printr$r5rhr-rD)r/ri�session�openedr=s     r1�command_openr�us����j�!�G���(�(��0��)�*��	�
�
��������r��	�A��L�L���)�����?��.�t�y�y�{�V�/C�C�.H�H_�`�a��X�����-G�)�[�Y��	�
�
��	�	�/�0���
�
����
�
��s�C5�AC5�AC5�C5�5Dc����t|�}	|j|�s!td|�d��	|j�yt	d�D]5}|jd�t
d�|j�D��s�5ntd�	|j�ytd����|j�d	�
�tj�}d}t	d�D]�}|jd�|j�D��cgc]\}}|��	}}}t
d
�|D��rt
�fd�|D��rd}d|j�vs�qtj�|z
dkDs��tj�|z
}	td��d|	d�d��t|rdnd�|rdndc|j�Std��d��	|j�ycc}}w#|j�wxYw)NzPR z
 never openedrQ�rbc3�*K�|]\}}d|v���
y�w�z/logsNrw)�.0r=�commands   r1�	<genexpr>z!command_switch.<locals>.<genexpr>�s����N�*�!�W�7�g�%�N�s�zBthe log warm-up never started, so there is nothing to queue behindzwarm-up running, switching to �/)rjF�xc3�$K�|]}d|v���
y�wr�rw)r��cs  r1r�z!command_switch.<locals>.<genexpr>�s����1�A�7�a�<�1�s�c3�8�K�|]}t��|v���y�wrF)rX)r�r��seconds  �r1r�z!command_switch.<locals>.<genexpr>�s�����9\�q�#�f�+��:J�9\�s�TrzrSz
 answered in r{�sz%the warm-up and the switch overlappedz*the switch waited for the warm-up to drainrz never answered)
rrkr}r$rhr-�anyr`r5rD)
r/�firstr�r~r=�started�
overlappedr�r]�elapseds
  `       r1�command_switchr��s�����j�!�G�!��(�(��/��C��w�m�,�-��<	�
�
��;�r��	�A��L�L����N��8K�8K�8M�N�N��	�

�V�W��.	�
�
��+	�.�v�h�7�8��!�!�&��!�4��)�)�+���
��s��
	.�A��L�L���18�1D�1D�1F�G�:�1�g�w�G�G�G��1��1�1�c�9\�T[�9\�6\�!�
�)�����?�D�I�I�K�RY�DY�\]�D]��)�)�+��/����F�8�=���
�Q�?�@��!�<�E��
'�q�A�-�	�
�
��#
	.�	��F�8�?�+�,���
�
���H��	�
�
��sC� G'�?G'�G'� A)G'�	G!�=G'�G'�.AG'�?G'�!G'�'G9c��ttj�dkrtt�ytjd}|dk(rJttj�dk(r.ttjdtjd�S|dk(r\ttj�dk(r@t
tjdtjdtjd�Stt�y)NrRrQ�openrdrS�switchrn)rW�sys�argvr}�__doc__r�r�)�actions r1�mainr��s���
�3�8�8�}�q��
�g���
�X�X�a�[�F�
���C����M�Q�.��C�H�H�Q�K����!��5�5�
���c�#�(�(�m�q�0��c�h�h�q�k�3�8�8�A�;������D�D�	�'�N�r3�__main__)r�rr rr6rrr�rr5r%rrr!�get�path�
expanduserrrr�r�r�rt�exitrwr3r1�<module>r�s����$
�	�
�
�
��
����
�
��d�	�����	�2�7�7�#5�#5�6L�#M�	N��O �O �d�*#�L

��z���C�H�H�T�V��r3