@@ -295,42 +295,75 @@ void write_name_quotedpfx(const char *pfx, size_t pfxlen,
295295 fputc (terminator , fp );
296296}
297297
298- /* quote path as relative to the given prefix */
299- char * quote_path_relative (const char * in , int len ,
300- struct strbuf * out , const char * prefix )
298+ static const char * path_relative (const char * in , int len ,
299+ struct strbuf * sb , const char * prefix ,
300+ int prefix_len );
301+
302+ void write_name_quoted_relative (const char * name , size_t len ,
303+ const char * prefix , size_t prefix_len ,
304+ FILE * fp , int terminator )
301305{
302- int needquote ;
306+ struct strbuf sb = STRBUF_INIT ;
307+
308+ name = path_relative (name , len , & sb , prefix , prefix_len );
309+ write_name_quoted (name , fp , terminator );
310+
311+ strbuf_release (& sb );
312+ }
313+
314+ /*
315+ * Give path as relative to prefix.
316+ *
317+ * The strbuf may or may not be used, so do not assume it contains the
318+ * returned path.
319+ */
320+ static const char * path_relative (const char * in , int len ,
321+ struct strbuf * sb , const char * prefix ,
322+ int prefix_len )
323+ {
324+ int off , i ;
303325
304326 if (len < 0 )
305327 len = strlen (in );
328+ if (prefix && prefix_len < 0 )
329+ prefix_len = strlen (prefix );
330+
331+ off = 0 ;
332+ i = 0 ;
333+ while (i < prefix_len && i < len && prefix [i ] == in [i ]) {
334+ if (prefix [i ] == '/' )
335+ off = i + 1 ;
336+ i ++ ;
337+ }
338+ in += off ;
339+ len -= off ;
340+
341+ if (i >= prefix_len )
342+ return in ;
306343
307- /* "../" prefix itself does not need quoting, but "in" might. */
308- needquote = next_quote_pos (in , len ) < len ;
309- strbuf_setlen (out , 0 );
310- strbuf_grow (out , len );
311-
312- if (needquote )
313- strbuf_addch (out , '"' );
314- if (prefix ) {
315- int off = 0 ;
316- while (prefix [off ] && off < len && prefix [off ] == in [off ])
317- if (prefix [off ] == '/' ) {
318- prefix += off + 1 ;
319- in += off + 1 ;
320- len -= off + 1 ;
321- off = 0 ;
322- } else
323- off ++ ;
324-
325- for (; * prefix ; prefix ++ )
326- if (* prefix == '/' )
327- strbuf_addstr (out , "../" );
344+ strbuf_reset (sb );
345+ strbuf_grow (sb , len );
346+
347+ while (i < prefix_len ) {
348+ if (prefix [i ] == '/' )
349+ strbuf_addstr (sb , "../" );
350+ i ++ ;
328351 }
352+ strbuf_add (sb , in , len );
353+
354+ return sb -> buf ;
355+ }
329356
330- quote_c_style_counted (in , len , out , NULL , 1 );
357+ /* quote path as relative to the given prefix */
358+ char * quote_path_relative (const char * in , int len ,
359+ struct strbuf * out , const char * prefix )
360+ {
361+ struct strbuf sb = STRBUF_INIT ;
362+ const char * rel = path_relative (in , len , & sb , prefix , -1 );
363+ strbuf_reset (out );
364+ quote_c_style_counted (rel , strlen (rel ), out , NULL , 0 );
365+ strbuf_release (& sb );
331366
332- if (needquote )
333- strbuf_addch (out , '"' );
334367 if (!out -> len )
335368 strbuf_addstr (out , "./" );
336369
0 commit comments