Files
granthi-sync/client/__pycache__/granthi_sync_client.cpython-314.pyc
T

157 lines
23 KiB
Plaintext
Raw Normal View History

+
ë+…j)<ãóþRt^RIt^RIt^RIt^RIt^RIt^RIt^RIt^RIt^RI t ^RI
t ^RI t ^RI
t ^RIHtHtRt]P"P%]P&P)RR44t]P"P-]R4tRtRtR tR
tR tR"R ltR
tRtRR/Rlt Rt!Rt"R#Rlt#R#Rlt$Rt%Rt&Rt'Rt(Rt)Rs*Rt+Rt,Rt-Rt.R$R lt/]0R!8Xd]Pb!]/!44R#R#)%avgranthi-sync client daemon.
Commands:
link [--server URL] [--token ZITADEL_TOKEN] [--device NAME]
Zitadel OAuth device flow against https://id.shre.ai (or --token for
the headless path), then POST /v1/link on the granthi-link service.
Stores {server, gitea_base, login, token, token_name} in
~/.granthi-sync/config.json (0600).
add <folder> [--name N] [--private/--public]
git init (branch main) if needed, create the cloud repo via
/v1/repos, add remote 'granthi', initial commit + push. The token
is supplied via a git credential helper (this script's hidden
`git-credential` subcommand), never embedded in the remote URL.
watch [--interval 30] [--once]
Poll linked folders: autocommit local changes, fetch, ff-pull when
the remote is strictly ahead, push when local is strictly ahead.
DIVERGED branches are logged + recorded and SKIPPED -- never force,
never merge (same policy as the estate's gitea_sync.py mesh).
SIGTERM-clean.
status
Table of linked folders, last sync, divergence flags.
Stdlib + git CLI only.
N)ÚdatetimeÚtimezonez1.0.0ÚGRANTHI_SYNC_HOMEz~/.granthi-syncz config.jsonzhttps://id.shre.aiÚ386909715541590022zhttp://100.111.127.127:3042zopenid profile emailcó’\P!\P4P R4p\ RV RV 2RR7R#)z%Y-%m-%dT%H:%M:%SZÚ[z] T)ÚflushN)rÚnowrÚutcÚstrftimeÚprint)ÚmsgÚtss& Úˆ/private/tmp/claude-502/-Users-aibot/7c1e3ba6-d022-4b1b-8026-9f6da66762d2/scratchpad/granthi-sync/tests/../client/granthi_sync_client.pyÚlogr6s6Ü Š”h—llÓ #× ,Ñ ,Ð-AÓ B€BÜ ˆAˆbˆTC5ˆ/ ×cóÊRp\T;'g/4pVeA\PPV4P 4pVP RR4M:Ve7\ P!V4P 4pVP RR4\PPWWpR7p\PPW…R7;_uu_4p V P4V PrºRRR4X X
'd\ P&!T
43#/3# +'giL4;i \PPd&p T P4T PRp ? LvRp ? i\PP \"3dp RR\%T 4/3uRp ? #Rp ? ii;i \(dX R X
P+R
R 7/3u#i;i) z/Returns (status, parsed-json-or-{'raw': text}).Nz Content-Typez!application/x-www-form-urlencodedzapplication/json)ÚdataÚheadersÚmethod)ÚtimeoutiWÚerrorÚrawÚreplace)Úerrors)ÚdictÚurllibÚparseÚ urlencodeÚencodeÚ
setdefaultÚjsonÚdumpsÚrequestÚRequestÚurlopenÚreadÚstatusrÚ HTTPErrorÚcodeÚURLErrorÚOSErrorÚstrÚloadsÚ
ValueErrorÚdecode)
rÚurlrÚbodyÚformrrÚhdrsÚreqÚresprr'Úes
&&&&&& rÚ http_jsonr7?soà €DÜ 
˜2Ó €DØ ÒÜ|‰|×% dÓØ ˜Ð(KÕ
Ò ÜzŠz˜×(ˆØ ˜Ð(:Ô
.‰.×
Ñ
 ¸Ð
Ó
M€Cð
^‰^×
# 
#×
9¸TØŸ)™)+ t§{¡{÷ ¯#”t—z’z #“Ð5°2Ð
9ûä <‰<× —ff“h §¡VûÜ L‰L× !¤7Ð Wœc !%ûð&ûô ô˜˜sŸz™z°˜=úslÂ8(D;à D(Ã<D;ÄF>ÄF>Ä%F>Ä( D8 Ä3D;Ä8D;Ä;F;ÅE:Å:&F;Æ!F;Æ"F6Æ0F;Æ6F;Æ>!G"Ç!G"cóÂ\\4;_uu_4p\P!V4uuRRR4# +'giR#;i \d/u#i;i©N)ÚopenÚ CONFIG_PATHr!ÚloadÚFileNotFoundError)Úfs rÚ load_configr?[sAðÜ
”+×
Ô
 —99˜Q“<÷×
×
Ó
ûä ôØŠ ðús+A:¯
Aº A ÁAÁ AÁ
AÁAcóN\P!\RRR7\R,p\ VR4;_uu_4p\
P !W^R7RRR4\P!VR4\P!V\4R# +'giLD;i)T)ÚmodeÚexist_okz.tmpÚw)ÚindentNi€) ÚosÚmakedirsÚ
CONFIG_DIRr;r:r!ÚdumpÚchmodr)ÚcfgÚtmpr>s& rÚ save_configrLcs`܇KK”
 °Õ
˜Õ
€CÜ
ˆc3Œ˜ Š # Õ
ä‡H‚HˆS܇J‚Jˆs”KÖ ÷
ús ¿BÂ B$ ÚcheckTc óN\P!RRV.\V4,RRR7pV'dMVP^8wd<\ RRP V4 RV RVP P4 24hVPVPP43#) z<Run git in folder. Returns (rc, stdout). Never uses --force.Úgitz-CT)Úcapture_outputÚtextzgit Ú z failed in ú: ) Ú
subprocessÚrunÚlistÚ
returncodeÚ RuntimeErrorÚjoinÚstderrÚstripÚstdout)ÚfolderrMÚargsÚprocs&$* rrOrOpsä >Š>˜5 Ð/´$°t³*Õ<Ø)-°Dô :€Dç  AÔØ3—88˜D“>Ð" +¨f¨X°R¸¿ ¹ ×8IÑ8IÓ8KÐ7LÐ Oð Oà ?‰?˜DŸK™K× /rcóú\PP\PPVR44'dR#\ VRRRRR7wrV^8wd\ VR4\ VRRR 4R#R#)
ú.gitNÚinitz-bÚmainF©rMz symbolic-refÚHEADzrefs/heads/main)rEÚpathÚisdirrYrO)r]ÚrcÚ_s& rÚ ensure_reporjzs`Ü ‡ww‡}}”R—WW—\\ &¨&Ó1×Ü ˜  f°EÔ :E€BØ ˆQ„wÜ ˆFÜ ˆFN FÐ,=ÖrcóÜ\VRR4wrV'gR#\VRR4\P!\P4P RR7p\VRR R
V 24R #) zPCommit all local changes as 'sync: <ISO ts>'. Returns True if a
commit was made.r'z --porcelainFÚaddz-AÚseconds©ÚtimespecÚcommitz-mzsync: T)rOrr rr
Ú isoformat)r]rir'rs& rÚ
autocommitrrƒs]ôF˜H mÓ4I€Aß ÙÜˆÜ Š”h—llÓ #× -Ñ -°yÐ -Ó A€B܈˜$ ¨ 
Ô rc
ó$\VRRRRV RV 2RR7wr4V^8wdR#\VRV4wrE\VRRV RV 24wrFWV8XdR #\VR
VRV RV 2RR7wr7V^8wdR #VP4pWv8XdR #Wu8XdR
#R #)z†Classify local vs remote after a fetch.
Returns one of: 'no-remote-branch', 'in-sync', 'local-ahead',
'remote-ahead-ff', 'diverged'.
z rev-parsez--verifyz--quietú
refs/remotes/Ú/Frdúno-remote-branchúin-syncz
merge-baseÚdivergedú local-aheadúremote-ahead-ff)rOr[)r]ÚremoteÚbranchrhriÚlocalÚ
remote_shaÚbases&&& rÚ
sync_stater€ô
˜  Z°Ø ˜x q¨¨Ðô
@E€Bà ˆQ„wÙ6˜;¨Ó/H€Aܘ  ¨}¸V¸HÀAÀfÀXÐ-NÓOM€AØ ÔÙÜ6˜Ø" 6 (¨!¨F¨8Ð4¸CH€Bà ˆQ„wÙØ :‰:‹<€DØ ÔÙØ „}Ù Ù rc ó^\V4p\VRV4\WV4pRpVR8Xd#\VRRRV RV 24Rp\WV4pVR 8XdR#VR9d\VR
R W4R V'dR
3#R 3#V'dR#R# \dpR\ T43uRp?#Rp?ii;i)zºOne sync pass for one folder. Returns (outcome, detail).
outcome in {'synced', 'pushed', 'clean', 'diverged', 'error'}.
Policy: ff-only pulls, plain pushes. NEVER --force, NEVER merge.
ÚfetchFrzÚmergez --ff-onlyrtruTrxÚpushú-uÚpushedzcommitted+pushedrN)rxz=local and remote both advanced; skipping (no force, no merge))ryrv)Úsyncedz ff-pulled)Úcleanrw)rrrOr€rXr,)r]r{r|Ú committedÚstateÚ ff_pulledr6s&&& rÚ sync_folderrŒ©ð ܘvÓ&ˆ Ü ˆFG˜˜6¨6ÓØˆ Ø Ð ˜ °
¸f¸XÀQÀvÀhÐ.OÔ ˆIܘv¨vÓ6ˆEØ  Ø Ð ˜  fÔ ·9Ð JÀ(Ð Ø !øÜ ôØœ˜A›ˆÕûðús<AB
Á B
Á;B
Á>B
ÂB
ÂB
Â
B, B'Â!B,Â'B,cóV'd
V^,MRpVR8wd^#/p\PF5pVP4pV'gMVPR4wrEpWbV&K7 \ 4pVP RR4p\ PPV4p VP R4V P8Xd=\RVP RR4 24\RVP R R4 24^#)
éÚgetÚ
gitea_baseÚÚhostz username=Úloginz password=Útoken) ÚsysÚstdinr[Ú partitionr?rrrÚurlparseÚnetlocr )
ÚargvÚopÚattrsÚlineÚkriÚvrJÚgiteaÚwants
& rÚcmd_git_credentialr£É߈ˆaŽ˜e€BØ ˆU„{ÙØ €EÜ— ” ˆØz‰z‹|ˆßÙ Ø—.‘. Ó%‰ˆˆa؈a‹ñ ô -€CØ G‰GL  %€EÜ <‰<× Ñ  Ó '€DØ ‡yyÓ˜DŸK™KÔ
˜#Ÿ'™' '¨2Ó
˜#Ÿ'™' '¨2Ó rcó’R\P R\PP \
4 R2p\
VRRV4R#)Ú!rRz git-credentialÚconfigzcredential.helperN)rÚ
executablerErfÚabspathÚ__file__rO)r]Úhelpers& rÚinstall_credential_helperr«Ýs8ØÐ  ¤"§'¡'§/¡/´(Ó";Ð!<¸
L€F܈Ð-¨vÖ6rc
ó\R\ R2R\R\/R7wrV^È8wd\ RV RV 24h\ RVP
R 4;'gVP
R
4 R 24\ R VR
, R 24\VP
R^44p\P!4\VP
RR44,p\P!4V8\P!V4\R\ R2RRRVR,R\/R7wrV^È8Xd
VR,#VP
RR4pVR8XdVR8Xd V^,
pK•\ RV 24h\ R4h)zCZitadel OAuth 2.0 device authorization grant. Returns access token.ÚPOSTz/oauth/v2/device_authorizationÚ client_idÚscope)r2z"device authorization failed (HTTP ú): z
To link this device, open:
Úverification_uri_completeÚverification_uriÚ
zand enter code: Ú user_codeÚintervalÚ
expires_ini,z/oauth/v2/tokenÚ
grant_typez,urn:ietf:params:oauth:grant-type:device_codeÚ device_codeÚ access_tokenrrÚauthorization_pendingÚ slow_downzdevice flow failed: z$device flow timed out (code expired))
r7Ú ZITADEL_BASEÚDEVICE_CLIENT_IDÚ DEVICE_SCOPEÚ
SystemExitr rÚintÚtimeÚsleep)r'r5ÚdeadlineÚtokÚerrs rÚ device_flowrÆæs{䨔<.Ð >ÐÔ+¨W´
EL€Fð„}ÜÐ=¸f¸XÀSÈÈÐ Ð .¨t¯x©xÐ8SÓ/T×/tÐ/tÐX\×X`ÑX`ÐasÓXtÐ.uÐuwÐ
 Ð ˜T /¨rÐ
4—8‘8˜J¨Ó+€HÜyŠy{œS §¡¨,¸Ó!<Ó=€HÜ
)Š)+˜Ô
Ü
Š
ÜØ ”|n OÐÐ NØ  mÕ!4ØÔ2‰ ˆð
SŒ=Ø g‰gg˜"ˆØ Ð Ø  Ø ˜MˆHÙ ÜШuÐ
Ð
<rc
ó4VP;'g \4p\RVPP R4 R2RVRVP
/R7wr#V^È8wd\
RV RV 24h\4pVPRVPP R4R VR ,R
VR
,R VR ,R VR ,/4VPR
/4\V4\RVR
, RVR , RVR , R\ 24^#)r­ruz/v1/linkÚzitadel_access_tokenÚ device_name©r1zlink failed (HTTP r°Úserverrr”r•Ú
token_nameÚfoldersz
linked as z on ú (token z ); config: )
r•r7ÚrstripÚdevicer¿r?Úupdater rLrr;)r^Ú
zitadel_tokenr'r5rJs& rÚcmd_linkrÓsØ—J‘J×/¤+£-€MÜØ4—;‘;×% cÓ+¨8Ð$ ˜TŸ[™[ð+L€Fð„}ÜÐ-¨f¨X°S¸¸Ð
‹-€C؇JJ˜$Ÿ+™+×,¨SÓ˜d <Õ˜˜gؘ˜gؘd 
‡NN9˜bÔÔ܈*T˜'•]O ¨\Õ(:Ð';ð<Ø% [´°
ð@á rc
ó4\4pRV9d \R4h\PP VP