package: reject duplicate manifest versions

This commit is contained in:
Hermes Agent
2026-09-04 19:04:20 +00:00
parent e66dded2e4
commit 20a181b631
6 changed files with 14 additions and 3 deletions
+1 -1
View File
@@ -641,7 +641,7 @@ static int lock_packages_match_project(void){ char *txt=read_file_text("claro.lo
static int package_manifest_version_matches(const char *text){ const char *p=text; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=17&&strncmp(line,"manifest-version:",17)==0){ const char *value=line+17; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; return (size_t)(end-value)==1&&value[0]=='1'; } while(*p=='\n'||*p=='\r') p++; } return 0; }
static int package_project_name_valid(const char *text){ const char *p=text; int fields=0; int nonempty=0; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=5&&strncmp(line,"name:",5)==0){ const char *value=line+5; fields++; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; if(value<end) nonempty++; } while(*p=='\n'||*p=='\r') p++; } return fields==1&&nonempty==1; }
static int package_manifest_name_matches(const char *text,const char *name){ const char *p=text; size_t n=strlen(name); int fields=0; int matches=0; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=5&&strncmp(line,"name:",5)==0){ const char *value=line+5; fields++; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; if((size_t)(end-value)==n&&strncmp(value,name,n)==0) matches++; } while(*p=='\n'||*p=='\r') p++; } return fields==1&&matches==1; }
static int package_manifest_version_value_matches(const char *text){ const char *p=text; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=8&&strncmp(line,"version:",8)==0){ const char *value=line+8; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; return (size_t)(end-value)==1&&value[0]=='1'; } while(*p=='\n'||*p=='\r') p++; } return 0; }
static int package_manifest_version_value_matches(const char *text){ const char *p=text; int fields=0; int matches=0; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=8&&strncmp(line,"version:",8)==0){ const char *value=line+8; fields++; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; if((size_t)(end-value)==1&&value[0]=='1') matches++; } while(*p=='\n'||*p=='\r') p++; } return fields==1&&matches==1; }
static int package_manifest_source_matches(const char *text){ const char *p=text; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=7&&strncmp(line,"source:",7)==0){ const char *value=line+7; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; return (size_t)(end-value)==5&&strncmp(value,"local",5)==0; } while(*p=='\n'||*p=='\r') p++; } return 0; }
static int package_manifest_checksum_matches(const char *text,const char *expected){ const char *p=text; size_t n=strlen(expected); int fields=0; int matches=0; while(p&&*p){ const char *line=p; const char *end; while(*p&&*p!='\n'&&*p!='\r') p++; end=p; if((size_t)(end-line)>=9&&strncmp(line,"checksum:",9)==0){ const char *value=line+9; fields++; while(value<end&&isspace((unsigned char)*value)) value++; while(end>value&&isspace((unsigned char)end[-1])) end--; if((size_t)(end-value)==n&&strncmp(value,expected,n)==0) matches++; } while(*p=='\n'||*p=='\r') p++; } return fields==1&&matches==1; }
static int package_doctor(void){ int ok=1; char *mainfile; char *txt; printf("%s\n",CLARO_VERSION); printf("Package/project doctor:\n"); printf(" %s claro.project\n",file_exists_simple("claro.project")?"OK":"MISSING"); if(!file_exists_simple("claro.project")) ok=0; mainfile=project_value("main"); if(mainfile&&*mainfile){ printf(" %s main script: %s\n",file_exists_simple(mainfile)?"OK":"MISSING",mainfile); if(!file_exists_simple(mainfile)) ok=0; } else { printf(" MISSING main setting\n"); ok=0; } printf(" %s packages folder\n",path_exists_simple("packages")?"OK":"MISSING"); if(!path_exists_simple("packages")) ok=0; printf(" %s claro.lock\n",file_exists_simple("claro.lock")?"OK":"MISSING"); if(!file_exists_simple("claro.lock")) ok=0; txt=read_file_text("claro.project"); if(txt&&!project_package_names_safe()){ ok=0; } if(txt&& !package_manifest_version_matches(txt)){ printf(" BAD project manifest version: expected 1\n"); ok=0; } if(txt&& !package_project_name_valid(txt)){ printf(" BAD project manifest name: expected a non-empty name\n"); ok=0; } if(txt){ char *p=txt; while(*p){ char *line=p; char save; while(*p&&*p!='\n'&&*p!='\r') p++; save=*p; *p=0; { char *t=trim_inplace(line); if(strnicmp2(t,"package:",8)==0){ char *pkg=trim_inplace(t+8); if(*pkg){ char meta[512], *mt, sum[32]; if(!package_name_safe(pkg)){ printf(" BAD package name: %s\n",pkg); ok=0; } else { snprintf(meta,sizeof(meta),"packages/%s/claro.package",pkg); mt=read_file_text(meta); if(mt&&!package_manifest_version_value_matches(mt)){ printf(" BAD package version: %s\n",pkg); ok=0; } else if(mt&&!package_manifest_source_matches(mt)){ printf(" BAD package source: %s\n",pkg); ok=0; } else if(mt&&package_manifest_version_matches(mt)&&strstr(mt,"checksum:")){ if(!package_manifest_name_matches(mt,pkg)){ printf(" BAD package manifest name: %s\n",pkg); ok=0; } else { printf(" OK package manifest: %s\n",pkg); package_checksum(pkg,sum,sizeof(sum)); if(package_manifest_checksum_matches(mt,sum)) printf(" OK package checksum: %s\n",pkg); else { printf(" BAD package checksum: %s\n",pkg); ok=0; } if(package_lock_checksum_ok(pkg)) printf(" OK lock checksum: %s\n",pkg); else { printf(" BAD lock checksum: %s\n",pkg); ok=0; } } } else { printf(" MISSING package manifest: %s\n",pkg); ok=0; } free(mt); } } } } if(save) p++; while(*p=='\n'||*p=='\r') p++; } free(txt); } if(!lock_packages_match_project()) ok=0; free(mainfile); printf("%s\n",ok?"Package/project files look ready.":"Package/project files need attention."); return ok?0:1; }