{"thread":{"id":"65329","subject":"[RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","startedAt":"2026-03-22T06:55:27Z","lastAt":"2026-03-29T05:23:58Z","messageCount":6,"participants":["Mateo Patino","Eric Sunshine"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"539638","messageId":"20260322065509.5384-1-mateopatinodev@gmail.com","threadId":"65329","inReplyTo":null,"subject":"[RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Mateo Patino","fromEmail":"mateopatinodev@gmail.com","sentAt":"2026-03-22T06:55:09Z","receivedAt":"2026-03-22T06:55:27Z","isPatch":false,"body":"\nHello,\n\nMy name is Mateo, and I'm a new contributor to Git. I'm a 1st year\nundergrad at Columbia University studying CS and applied math.\n\nI wanted to ask the community for feedback on a project proposal\nregarding the `strbuf` API. Seven years ago, a macro to initialize a \n`strbuf` to a constant string literal was proposed in GitGitGadget [1]\ncalled `STRBUF_INIT_CONST`. This macro would work just like `STRBUF_INIT`\nbut it would set `alloc` to 0 (i.e. the buffer would not be \nheap-allocated).\n\nSomeone made a pull request to implement this feature [2], but their\nchanges were not merged. Later, Robear Selwans made a patch series [3]\nattempting to implement this same feature. Robear got extensive \nfeedback, but his patches were not accepted. The same GitHub user from\n[2] sent a patch here [4], but his changes were not accepted.\n\nMore recently, the potential need for `STRBUF_INIT_CONST` was mentioned \nin this patch series [5] by Patrick Steinhardt, though it was marked\nas a #leftoverbit and not directly addressed.\n\n`STRBUF_INIT_CONST` has been mentioned for a long time in this list,\nbut it has not been implemented yet. My Request For Comment is the\nfollowing: is `STRBUF_INIT_CONST` a feature that is still of interest\nto the community? If so, I would like to make a GSoC proposal around it.\nThe past email threads have already laid out the considerations of \nimplementing `STRBUF_INIT_CONST` or something equivalent, so I would\nlike to propose this as GSoC idea if the community would find it \nworthwhile.\n\nI would love to hear any thoughts about this.\n\nThanks!\n\nMateo <mateopatinodev@gmail.com>\n\n[1] https://github.com/gitgitgadget/git/issues/398\n[2] https://github.com/gitgitgadget/git/pull/824\n[3] https://lore.kernel.org/git/20200218041805.10939-1-robear.selwans@outlook.com/\n[4] https://lore.kernel.org/git/20210105064502.725307-1-adlternative@gmail.com/\n[5] https://lore.kernel.org/git/Zrm9ix5aN_g76Qxq@tanuki/\n"},{"id":"539639","messageId":"CAPig+cRAsEgeT+OgCSpTuY_Q6dMpXrfadrB=ujkAUyF-ocu2-g@mail.gmail.com","threadId":"65329","inReplyTo":"20260322065509.5384-1-mateopatinodev@gmail.com","subject":"Re: [RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2026-03-22T08:59:09Z","receivedAt":"2026-03-22T08:59:25Z","isPatch":false,"body":"On Sun, Mar 22, 2026 at 2:55 AM Mateo Patino <mateopatinodev@gmail.com> wrote:\n> My name is Mateo, and I'm a new contributor to Git. I'm a 1st year\n> undergrad at Columbia University studying CS and applied math.\n>\n> I wanted to ask the community for feedback on a project proposal\n> regarding the `strbuf` API. Seven years ago, a macro to initialize a\n> `strbuf` to a constant string literal was proposed in GitGitGadget [1]\n> called `STRBUF_INIT_CONST`. This macro would work just like `STRBUF_INIT`\n> but it would set `alloc` to 0 (i.e. the buffer would not be\n> heap-allocated).\n>\n> Someone made a pull request to implement this feature [2], but their\n> changes were not merged. Later, Robear Selwans made a patch series [3]\n> attempting to implement this same feature. Robear got extensive\n> feedback, but his patches were not accepted. The same GitHub user from\n> [2] sent a patch here [4], but his changes were not accepted.\n\nYou probably didn't intend for it to sound this way, but this summary\nmakes it seem as if the Git project rejected these patch submissions\nwithout proper justification. However, having studied the threads\nwhich you referenced, it becomes clear that the reason these patches\nwere never accepted is because the submitters never followed through\nby addressing reviewer comments. For instance, in my review[*1*] of\nthe patch [4] which you referenced, I pointed out several significant\nproblems with the patch, but the patch author never responded, so it\nmakes sense that the submission was never accepted into the project.\n\n> More recently, the potential need for `STRBUF_INIT_CONST` was mentioned\n> in this patch series [5] by Patrick Steinhardt, though it was marked\n> as a #leftoverbit and not directly addressed.\n>\n> `STRBUF_INIT_CONST` has been mentioned for a long time in this list,\n> but it has not been implemented yet. My Request For Comment is the\n> following: is `STRBUF_INIT_CONST` a feature that is still of interest\n> to the community? If so, I would like to make a GSoC proposal around it.\n> The past email threads have already laid out the considerations of\n> implementing `STRBUF_INIT_CONST` or something equivalent, so I would\n> like to propose this as GSoC idea if the community would find it\n> worthwhile.\n>\n> I would love to hear any thoughts about this.\n\nAlthough feedback to Robear Selwans's submission from some reviewers\nwas subjective, Peff's review[*2*] pointed at a major roadblock;\nspecifically, that strbuf has always promoted strbuf.buf is a\nwriteable C-style string, so it is not safe simply to assign a pointer\nto a literal string to the \"buf\" member, and it's not practical to\nexpect that all consumers of strbufs can be audited and modified to\nwork correctly with the \"new world order\" that STRBUF_INIT_CONST would\nintroduce.\n\nThus, the issue is deeper than it may seem at first glance, and unless\nyou have some fundamentally new ideas to address the sort of critical\nissues identified by such feedback, it is likely that a patch which\ntakes an approach similar to what has previously been submitted will\nlikewise fail.\n\n[*1*]: https://lore.kernel.org/git/CAPig+cQL=b-nF6nADaWueJaDmxCgmZbUwWj6=dAwYQ=vVrkifg@mail.gmail.com/\n[*2*]: https://lore.kernel.org/git/20200218062124.GF1641086@coredump.intra.peff.net/\n\n> [1] https://github.com/gitgitgadget/git/issues/398\n> [2] https://github.com/gitgitgadget/git/pull/824\n> [3] https://lore.kernel.org/git/20200218041805.10939-1-robear.selwans@outlook.com/\n> [4] https://lore.kernel.org/git/20210105064502.725307-1-adlternative@gmail.com/\n> [5] https://lore.kernel.org/git/Zrm9ix5aN_g76Qxq@tanuki/\n"},{"id":"539757","messageId":"20260323161101.9142-1-mateopatinodev@gmail.com","threadId":"65329","inReplyTo":"CAPig+cRAsEgeT+OgCSpTuY_Q6dMpXrfadrB=ujkAUyF-ocu2-g@mail.gmail.com","subject":"Re: [RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Mateo Patino","fromEmail":"mateopatinodev@gmail.com","sentAt":"2026-03-23T16:10:51Z","receivedAt":"2026-03-23T16:11:27Z","isPatch":false,"body":"(Note: resending this because it had HTML the first time and the list rejected \nit. Apologies if it becomes a  duplicate for someone).\n\n>\n> You probably didn't intend for it to sound this way, but this summary\n> makes it seem as if the Git project rejected these patch submissions\n> without proper justification. However, having studied the threads\n> which you referenced, it becomes clear that the reason these patches\n> were never accepted is because the submitters never followed through\n> by addressing reviewer comments. For instance, in my review[*1*] of\n> the patch [4] which you referenced, I pointed out several significant\n> problems with the patch, but the patch author never responded, so it\n> makes sense that the submission was never accepted into the project.\n\nYes, I saw that they did not reply to reviewer feedback. Here I meant to say \nthat previous patches had already been attempted in this area and could be\nused as guidance for future attempts.\n\n>\n> Although feedback to Robear Selwans's submission from some reviewers\n> was subjective, Peff's review[*2*] pointed at a major roadblock;\n> specifically, that strbuf has always promoted strbuf.buf is a\n> writeable C-style string, so it is not safe simply to assign a pointer\n> to a literal string to the \"buf\" member, and it's not practical to\n> expect that all consumers of strbufs can be audited and modified to\n> work correctly with the \"new world order\" that STRBUF_INIT_CONST would\n> introduce.\n\nSince the Git codebase widely assumes strbuf.buf is writable, I wonder whether \nwe could create a new struct that is specifically documented as a read-only, \nnon-owning view into memory, something lightweight like `string_view` in C++, \nwhich is an object that simply holds a pointer to a string in memory and the length. \nFor example, in C,\n\nstruct strview {\n    const char *buf;\n    size_t len;\n};\n\nThis struct would not care where the memory that `buf` points to exists. The\nmemory would be owned elsewhere and the caller would be responsible for \nensuring that the memory is valid throughout the lifetime of the struct. I think\nthis could help pass around string data without requiring ownership or \nallocation, particularly in cases where the data is already available.\n\nA small downside I see to this approach is that we'd need to write a few helper\nfunctions that accompany this struct, and they would likely share similar names\nto the helper functions of `strbuf`, though I think this has been accepted in the \npast in other places throughout the codebase.\n\nAnother consideration is that this proposed `strview` would not address the\nlifetime and ownership issue in [4], but having a safer way to pass read-only \nstrings seems like a step in the right direction.\n"},{"id":"539799","messageId":"CAPig+cQcLJxxtsH0OeSP2DVUbSg8x95B-7n18fK9BVTJVywEtQ@mail.gmail.com","threadId":"65329","inReplyTo":"CAFRsFoV+k-8GMf=62GJwxP=o0Fy5RRBGW+h4NqOLjFbU6z96tw@mail.gmail.com","subject":"Re: [RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2026-03-24T03:33:35Z","receivedAt":"2026-03-24T03:33:48Z","isPatch":false,"body":"On Mon, Mar 23, 2026 at 1:11 AM Mateo Patino <mateopatinodev@gmail.com> wrote:\n> On Sun, Mar 22, 2026 at 4:59 AM Eric Sunshine <sunshine@sunshineco.com> wrote:\n>> Although feedback to Robear Selwans's submission from some reviewers\n>> was subjective, Peff's review[*2*] pointed at a major roadblock;\n>> specifically, that strbuf has always promoted strbuf.buf is a\n>> writeable C-style string, so it is not safe simply to assign a pointer\n>> to a literal string to the \"buf\" member, and it's not practical to\n>> expect that all consumers of strbufs can be audited and modified to\n>> work correctly with the \"new world order\" that STRBUF_INIT_CONST would\n>> introduce.\n>\n> Since the Git codebase widely assumes strbuf.buf is writable, I wonder whether\n> we could create a new struct that is specifically documented as a read-only,\n> non-owning view into memory, something lightweight like `string_view` in C++,\n> which is an object that simply holds a pointer to a string in memory and the length.\n> For example, in C,\n>\n> struct strview {\n>     const char *buf;\n>     size_t len;\n> };\n>\n> This struct would not care where the memory that `buf` points to exists. The\n> memory would be owned elsewhere and the caller would be responsible for\n> ensuring that the memory is valid throughout the lifetime of the struct. I think\n> this could help pass around string data without requiring ownership or\n> allocation, particularly in cases where the data is already available.\n>\n> A small downside I see to this approach is that we'd need to write a few helper\n> functions that accompany this struct, and they would likely share similar names\n> to the helper functions of `strbuf`, though I think this has been accepted in the\n> past in other places throughout the codebase.\n>\n> Another consideration is that this proposed `strview` would not address the\n> lifetime and ownership issue in [4], but having a safer way to pass read-only\n> strings seems like a step in the right direction.\n>\n> What do you think?\n\nI think this is a solution to a non-existent problem. Being written in\nC, Git does not (generally) have a need for this sort of structure.\nWhen Git code wants to \"pass around\" an immutable string to functions,\nthose functions simply declare themselves as accepting a const string,\nas in:\n\n    void do_something(const char *s) {...}\n\nIn the less common case that the string is not NUL-terminated or only\na portion of the string should be processed, the function also takes a\nlength:\n\n    void do_something(const char *s, size_t n) {...}\n\nThis is a common idiom in the Git codebase, it's perfectly safe,\ndoesn't involve ownership concerns, and there is no reason to stray\naway from it. The proposed `strview` is not safer and is probably not\nas convenient, thus adds no apparent value.\n\nBut, having reread the threads which your initial email referenced, I\nthink the bigger issue is that we're dealing with an XY Problem[1].\nThe original problem \"X\" being discussed was how to achieve static\ninitialization of some string variables while still allowing the\nvariables to be later pointed at heap-allocated memory, but at the\nsame time avoiding memory leaks when those reassignments occur. The\nproposed solution \"Y\" was to somehow employ `strbuf` to solve X,\nhowever, it turns out that `strbuf` is utterly unsuitable for this\nuse-case. Unfortunately, this \"Y\" proposal was then turned into a\nGitHub issue[2] which has led to this email thread as well as those\naborted and misdirected submissions which you referenced earlier.\n\nIf we take a step back and focus on the original problem rather than\nfocusing on how to twist strbuf into something it was never meant to\nbe, then a potential solution becomes clearer. Let's restate the\noriginal problem:\n\n  static const char *global_var = \"thimble\";\n\n  void maybe_assign(const char **var, ...) {\n    if (...some_condition...) {\n      /* ??? free((void *)*var) ??? */\n      *var = some_heap_allocated_str;\n    }\n  }\n\n  maybe_assign(&global_var, ...);\n  ...\n  maybe_assign(&global_var, ...);\n\nWhen maybe_assign() is called, it doesn't know whether or not the\nincoming `var` points at a static string literal (\"thimble\") or at\nsome heap-allocated string, so it doesn't know whether or not to first\nfree() `var` before assigning the new value. To solve this, we need a\nflag which indicates whether the string stored in the variable needs\nto be freed before the variable is reassigned. So, this suggests a\ndedicated, simple structure and a few related functions and a macro or\ntwo. For instance, something like this:\n\n  struct str {\n    char *s;\n    int free_me;\n  };\n\n  /* initialize `str` from a literal string (i.e. \"foo\") */\n  #define STR_INIT(X) { .s = (char *)(X), .free_me = 0 }\n\n  void str_release(str *x) {\n    if (x.free_me)\n      FREE_AND_NULL(x.s);\n    x.free_me = 0;\n  }\n\n  /* take ownership of a heap-allocated string */\n  void str_take(str *x, char * s) {\n    str_release(x);\n    x.s = s;\n    x.free_me = 1;\n  }\n\n  /* assign a string literal (i.e. \"foo\") */\n  void str_assign(str *x, const char *s) {\n    str_release(x);\n    x.s = (char *)s;\n    x.free_me = 0;\n  }\n\nThat's probably about all you need to solve the stated problem. Given\nthe above, the original problem statement can be \"fixed\" by taking\nadvantage of the above structure and functions:\n\n  static struct str global_var = STR_INIT(\"thimble\");\n\n  void maybe_assign(str *var, ...) {\n    if (...some_condition...)\n      str_assign(var, some_heap_allocated_str);\n  }\n\n  maybe_assign(&global_var, ...);\n\nClients which need the value simply access the `.s` member directly.\nAnd there is no need to have any functions to morph the string in any\nway. If a client needs that functionality, it is easy enough to create\nand populate a proper `strbuf` from the `.s` member.\n\n[1]: https://xyproblem.info/\n[2]: https://github.com/gitgitgadget/git/issues/398\n"},{"id":"540305","messageId":"CAFRsFoWRRnbrJdp_HVuoW-AEMqz_XjoP5yFAFP73VVN9nhdp2w@mail.gmail.com","threadId":"65329","inReplyTo":"CAPig+cQcLJxxtsH0OeSP2DVUbSg8x95B-7n18fK9BVTJVywEtQ@mail.gmail.com","subject":"Re: [RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Mateo Patino","fromEmail":"mateopatinodev@gmail.com","sentAt":"2026-03-28T21:40:59Z","receivedAt":"2026-03-28T21:41:10Z","isPatch":false,"body":">\n> But, having reread the threads which your initial email referenced, I\n> think the bigger issue is that we're dealing with an XY Problem[1].\n> The original problem \"X\" being discussed was how to achieve static\n> initialization of some string variables while still allowing the\n> variables to be later pointed at heap-allocated memory, but at the\n> same time avoiding memory leaks when those reassignments occur. The\n> proposed solution \"Y\" was to somehow employ `strbuf` to solve X,\n> however, it turns out that `strbuf` is utterly unsuitable for this\n> use-case. Unfortunately, this \"Y\" proposal was then turned into a\n> GitHub issue[2] which has led to this email thread as well as those\n> aborted and misdirected submissions which you referenced earlier.\n\nI didn't know this concept of an XY problem. It seems very useful to describe\nthis kind of mistake in software development. I will keep it in mind from now\non. Thanks for sharing it!\n\n>\n> If we take a step back and focus on the original problem rather than\n> focusing on how to twist strbuf into something it was never meant to\n> be, then a potential solution becomes clearer. Let's restate the\n> original problem:\n>\n>   static const char *global_var = \"thimble\";\n>\n>   void maybe_assign(const char **var, ...) {\n>     if (...some_condition...) {\n>       /* ??? free((void *)*var) ??? */\n>       *var = some_heap_allocated_str;\n>     }\n>   }\n>\n>   maybe_assign(&global_var, ...);\n>   ...\n>   maybe_assign(&global_var, ...);\n>\n> When maybe_assign() is called, it doesn't know whether or not the\n> incoming `var` points at a static string literal (\"thimble\") or at\n> some heap-allocated string, so it doesn't know whether or not to first\n> free() `var` before assigning the new value. To solve this, we need a\n> flag which indicates whether the string stored in the variable needs\n> to be freed before the variable is reassigned. So, this suggests a\n> dedicated, simple structure and a few related functions and a macro or\n> two. For instance, something like this:\n>\n>   struct str {\n>     char *s;\n>     int free_me;\n>   };\n\nThanks for explaining the original problem in such detail, I see I really\nhadn't completely understood what the original problem \"X\" was.\n\nTo clarify, you are imagining this `struct str` more as a \"smart pointer\"\nthan a full string abstraction, correct? I was going to propose including a\n`size_t len` member for this struct, but after some thought, I feel like that\nwould somewhat transform `struct str` into a string abstraction, which `strbuf`\nalready is. The way you're imagining `struct str` could be used around in the\nGit codebase is as a wrapper whose only purpose is to inform clients of\na string's ownership, correct?\n\n>\n>   /* initialize `str` from a literal string (i.e. \"foo\") */\n>   #define STR_INIT(X) { .s = (char *)(X), .free_me = 0 }\n>\n>   void str_release(str *x) {\n>     if (x.free_me)\n>       FREE_AND_NULL(x.s);\n>     x.free_me = 0;\n>   }\n>\n>   /* take ownership of a heap-allocated string */\n>   void str_take(str *x, char * s) {\n>     str_release(x);\n>     x.s = s;\n>     x.free_me = 1;\n>   }\n>\n>   /* assign a string literal (i.e. \"foo\") */\n>   void str_assign(str *x, const char *s) {\n>     str_release(x);\n>     x.s = (char *)s;\n>     x.free_me = 0;\n>   }\n>\n> That's probably about all you need to solve the stated problem.\n> Given the above, the original problem statement can be \"fixed\" by taking\n> advantage of the above structure and functions:\n>\n>   static struct str global_var = STR_INIT(\"thimble\");\n>\n>   void maybe_assign(str *var, ...) {\n>     if (...some_condition...)\n>       str_assign(var, some_heap_allocated_str);\n>   }\n>\n>   maybe_assign(&global_var, ...);\n>\n> Clients which need the value simply access the `.s` member directly.\n> And there is no need to have any functions to morph the string in any\n> way. If a client needs that functionality, it is easy enough to create\n> and populate a proper `strbuf` from the `.s` member.\n\nSo if we were to make this into a patch, would we implement this as a local\nhelper in config.c, where the original problem started? I imagine this small\nownership interface could likely be used in multiple places around the codebase,\nso my first instinct would be to not restrict it to config.c. Would it be\ntoo premature to give this `struct str` its own module? If so, then how would an\nidea of this sort be first presented to the community as a patch?\n\nThanks again for the detailed explanations!\n\n> [1]: https://xyproblem.info/\n> [2]: https://github.com/gitgitgadget/git/issues/398\n"},{"id":"540310","messageId":"CAPig+cTmvu+tmuvb-h+VsA8NL5xJgf6XPZGnERVqh1cp40hV_w@mail.gmail.com","threadId":"65329","inReplyTo":"CAFRsFoWRRnbrJdp_HVuoW-AEMqz_XjoP5yFAFP73VVN9nhdp2w@mail.gmail.com","subject":"Re: [RFC] [GSoC]: STRBUF_INIT_CONST: initialize `strbuf` to constant string","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2026-03-29T05:23:46Z","receivedAt":"2026-03-29T05:23:58Z","isPatch":false,"body":"On Sat, Mar 28, 2026 at 5:41 PM Mateo Patino <mateopatinodev@gmail.com> wrote:\n> > [...] So, this suggests a\n> > dedicated, simple structure and a few related functions and a macro or\n> > two. For instance, something like this:\n> >\n> >   struct str {\n> >     char *s;\n> >     int free_me;\n> >   };\n>\n> Thanks for explaining the original problem in such detail, I see I really\n> hadn't completely understood what the original problem \"X\" was.\n>\n> To clarify, you are imagining this `struct str` more as a \"smart pointer\"\n> than a full string abstraction, correct? I was going to propose including a\n> `size_t len` member for this struct, but after some thought, I feel like that\n> would somewhat transform `struct str` into a string abstraction, which `strbuf`\n> already is. The way you're imagining `struct str` could be used around in the\n> Git codebase is as a wrapper whose only purpose is to inform clients of\n> a string's ownership, correct?\n\nYou're correct that I'm not proposing a full string abstraction;\nhowever, I wouldn't exactly call it a smart-pointer or say that it\n\"informs\" clients of a string's ownership. It's just a tool which\nmakes it simple for clients to reassign the string without having to\nworry about the ownership.\n\nWhether or not it would be generally helpful throughout the Git\ncodebase remains to be seen.\n\n> >   /* initialize `str` from a literal string (i.e. \"foo\") */\n> >   #define STR_INIT(X) { .s = (char *)(X), .free_me = 0 }\n> >\n> >   void str_release(str *x) {\n> >     if (x.free_me)\n> >       FREE_AND_NULL(x.s);\n> >     x.free_me = 0;\n> >   }\n> >\n> >   /* take ownership of a heap-allocated string */\n> >   void str_take(str *x, char * s) {\n> >     str_release(x);\n> >     x.s = s;\n> >     x.free_me = 1;\n> >   }\n> >\n> >   /* assign a string literal (i.e. \"foo\") */\n> >   void str_assign(str *x, const char *s) {\n> >     str_release(x);\n> >     x.s = (char *)s;\n> >     x.free_me = 0;\n> >   }\n\nBy the way, the above example using the \"free_me\" member was just for\nillustration purposes since \"free_me\" makes the ownership concerns\nobvious. However, in practice, a better approach would be to employ\nthe \"to_free\" idiom which is used elsewhere in the Git codebase since\nit avoids all the ugly casts. Something like this:\n\n  struct str {\n    const char *s;\n    char *to_free; /* private */\n  };\n\n  /* initialize `str` from a literal string (i.e. \"foo\") */\n  #define STR_INIT(X) { .s = (X), .to_free = NULL }\n\n  void str_release(struct str *x) {\n    x.s = NULL;\n    FREE_AND_NULL(x.to_free);\n  }\n\n  /* take ownership of a heap-allocated string */\n  void str_take(struct str *x, char *s) {\n    str_release(x);\n    x.s = s;\n    x.to_free = s;\n  }\n\n  /* assign a string literal (i.e. \"foo\") */\n  void str_assign(struct str *x, const char *s) {\n    str_release(x);\n    x.s = s;\n  }\n\n> > Clients which need the value simply access the `.s` member directly.\n> > And there is no need to have any functions to morph the string in any\n> > way. If a client needs that functionality, it is easy enough to create\n> > and populate a proper `strbuf` from the `.s` member.\n>\n> So if we were to make this into a patch, would we implement this as a local\n> helper in config.c, where the original problem started? I imagine this small\n> ownership interface could likely be used in multiple places around the codebase,\n> so my first instinct would be to not restrict it to config.c. Would it be\n> too premature to give this `struct str` its own module? If so, then how would an\n> idea of this sort be first presented to the community as a patch?\n\nMy gut feeling is that it would make sense first to introduce such a\nutility locally in `config.c` where it is needed. If it becomes\napparent that it has value outside of `config.c`, then it could be\nextracted into a reusable component. However, others may feel\ndifferently, and even I don't feel strongly about it.\n\nOne reason I hesitate to suggest that this would be generally useful\nis that the existing \"to_free\" idiom employed in Git is already about\nas simple as it gets, and I don't think the proposed \"str\" utility\nwould necessarily make it any simpler or improve code quality. For\ninstance, a typical use of \"to_free\" might be something like this:\n\n  const char *name = \"default\";\n  char *to_free = NULL;\n  ...do stuff...\n  if (some_condition)\n    name = to_free = xstrdup(some_str_var);\n  ...do stuff...\n  free(to_free);\n\nChanging this to take advantage of the proposed \"str\" might result in:\n\n  struct str name = STR_INIT(\"default\");\n  ...do stuff...\n  if (some_condition)\n    str_take(&name, xstrdup(some_str_var));\n  ...do stuff...\n  str_release(&name);\n\nwhich is only one line shorter, and not necessarily any clearer or\nless noisy. So, there isn't a strong reason (outside of `config.c`) to\nconvert such code to use \"str\", and any such conversion just for the\nsake of conversion would probably be unwanted churn.\n"}]}