66//
77
88#include "asprintf/asprintf.h"
9+ #include "common/clib-cache.h"
910#include "debug/debug.h"
11+ #include "fs/fs.h"
12+ #include "http-get/http-get.h"
13+ #include "logger/logger.h"
14+ #include "parson/parson.h"
15+ #include "path-join/path-join.h"
1016#include "str-flatten/str-flatten.h"
1117#include "strdup/strdup.h"
1218#include "trim/trim.h"
1319#include "version.h"
1420#include "which/which.h"
21+ #include <stdbool.h>
1522#include <stdio.h>
1623#include <stdlib.h>
1724#include <string.h>
2229#define realpath (a , b ) _fullpath(a, b, strlen(a))
2330#endif
2431
32+ #define LATEST_RELEASE_ENDPOINT \
33+ "https://api.github.com/repos/clibs/clib/releases/latest"
34+ #define RELEASE_NOTIFICATION_EXPIRATION 3 * 24 * 60 * 60 // 3 days
35+
2536debug_t debugger ;
2637
2738static const char * usage =
@@ -54,6 +65,77 @@ static const char *usage =
5465 } \
5566 })
5667
68+ static bool should_check_release (const char * path ) {
69+ fs_stats * stat = fs_stat (path );
70+
71+ if (!stat ) {
72+ return true;
73+ }
74+
75+ time_t modified = stat -> st_mtime ;
76+ time_t now = time (NULL );
77+ free (stat );
78+
79+ return now - modified >= RELEASE_NOTIFICATION_EXPIRATION ;
80+ }
81+
82+ static void compare_versions (const JSON_Object * response ,
83+ const char * marker_file_path ) {
84+ const char * latest_version = json_object_get_string (response , "tag_name" );
85+
86+ if (0 != strcmp (CLIB_VERSION , latest_version )) {
87+ logger_info ("info" ,
88+ "You are using clib %s, a new version is avalable. You can "
89+ "upgrade with the following command: clib upgrade --tag %s" ,
90+ CLIB_VERSION , latest_version );
91+ }
92+ }
93+
94+ static void notify_new_release (void ) {
95+ const char * marker_file_path =
96+ path_join (clib_cache_meta_dir (), "release-notification-checked" );
97+
98+ if (!marker_file_path ) {
99+ fs_write (marker_file_path , " " );
100+ return ;
101+ }
102+
103+ if (!should_check_release (marker_file_path )) {
104+ debug (& debugger , "No need to check for new release yet" );
105+ return ;
106+ }
107+
108+ JSON_Value * root_json = NULL ;
109+ JSON_Object * json_object = NULL ;
110+
111+ http_get_response_t * res = http_get (LATEST_RELEASE_ENDPOINT );
112+
113+ if (!res -> ok ) {
114+ debug (& debugger , "Couldn't lookup latest release" );
115+ goto cleanup ;
116+ }
117+
118+ if (!(root_json = json_parse_string (res -> data ))) {
119+ debug (& debugger , "Unable to parse release JSON response" );
120+ goto cleanup ;
121+ }
122+
123+ if (!(json_object = json_value_get_object (root_json ))) {
124+ debug (& debugger , "Unable to parse release JSON response object" );
125+ goto cleanup ;
126+ }
127+
128+ compare_versions (json_object , marker_file_path );
129+ fs_write (marker_file_path , " " );
130+
131+ cleanup :
132+ if (root_json )
133+ json_value_free (root_json );
134+
135+ free ((void * )marker_file_path );
136+ http_get_free (res );
137+ }
138+
57139int main (int argc , const char * * argv ) {
58140
59141 char * cmd = NULL ;
@@ -65,6 +147,10 @@ int main(int argc, const char **argv) {
65147
66148 debug_init (& debugger , "clib" );
67149
150+ clib_cache_meta_init ();
151+
152+ notify_new_release ();
153+
68154 // usage
69155 if (NULL == argv [1 ] || 0 == strncmp (argv [1 ], "-h" , 2 ) ||
70156 0 == strncmp (argv [1 ], "--help" , 6 )) {
0 commit comments